2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
40 #include "alcontext.h"
42 #include "alListener.h"
47 #include "alAuxEffectSlot.h"
49 #include "mastering.h"
50 #include "bformatdec.h"
51 #include "uhjfilter.h"
54 #include "ringbuffer.h"
55 #include "filters/splitter.h"
57 #include "fpu_modes.h"
63 #include "backends/base.h"
64 #include "backends/null.h"
65 #include "backends/loopback.h"
67 #include "backends/jack.h"
69 #ifdef HAVE_PULSEAUDIO
70 #include "backends/pulseaudio.h"
73 #include "backends/alsa.h"
76 #include "backends/wasapi.h"
79 #include "backends/coreaudio.h"
82 #include "backends/opensl.h"
85 #include "backends/solaris.h"
88 #include "backends/sndio.h"
91 #include "backends/oss.h"
94 #include "backends/qsa.h"
97 #include "backends/dsound.h"
100 #include "backends/winmm.h"
102 #ifdef HAVE_PORTAUDIO
103 #include "backends/portaudio.h"
106 #include "backends/sdl2.h"
109 #include "backends/wave.h"
115 /************************************************
117 ************************************************/
120 BackendFactory
& (*getFactory
)(void);
123 struct BackendInfo BackendList
[] = {
125 { "jack", JackBackendFactory::getFactory
},
127 #ifdef HAVE_PULSEAUDIO
128 { "pulse", PulseBackendFactory::getFactory
},
131 { "alsa", AlsaBackendFactory::getFactory
},
134 { "wasapi", WasapiBackendFactory::getFactory
},
136 #ifdef HAVE_COREAUDIO
137 { "core", CoreAudioBackendFactory::getFactory
},
140 { "opensl", OSLBackendFactory::getFactory
},
143 { "solaris", SolarisBackendFactory::getFactory
},
146 { "sndio", SndIOBackendFactory::getFactory
},
149 { "oss", OSSBackendFactory::getFactory
},
152 { "qsa", QSABackendFactory::getFactory
},
155 { "dsound", DSoundBackendFactory::getFactory
},
158 { "winmm", WinMMBackendFactory::getFactory
},
160 #ifdef HAVE_PORTAUDIO
161 { "port", PortBackendFactory::getFactory
},
164 { "sdl2", SDL2BackendFactory::getFactory
},
167 { "null", NullBackendFactory::getFactory
},
169 { "wave", WaveBackendFactory::getFactory
},
172 ALsizei BackendListSize
= COUNTOF(BackendList
);
174 struct BackendInfo PlaybackBackend
;
175 struct BackendInfo CaptureBackend
;
178 /************************************************
179 * Functions, enums, and errors
180 ************************************************/
181 #define DECL(x) { #x, (ALCvoid*)(x) }
183 const ALCchar
*funcName
;
186 DECL(alcCreateContext
),
187 DECL(alcMakeContextCurrent
),
188 DECL(alcProcessContext
),
189 DECL(alcSuspendContext
),
190 DECL(alcDestroyContext
),
191 DECL(alcGetCurrentContext
),
192 DECL(alcGetContextsDevice
),
194 DECL(alcCloseDevice
),
196 DECL(alcIsExtensionPresent
),
197 DECL(alcGetProcAddress
),
198 DECL(alcGetEnumValue
),
200 DECL(alcGetIntegerv
),
201 DECL(alcCaptureOpenDevice
),
202 DECL(alcCaptureCloseDevice
),
203 DECL(alcCaptureStart
),
204 DECL(alcCaptureStop
),
205 DECL(alcCaptureSamples
),
207 DECL(alcSetThreadContext
),
208 DECL(alcGetThreadContext
),
210 DECL(alcLoopbackOpenDeviceSOFT
),
211 DECL(alcIsRenderFormatSupportedSOFT
),
212 DECL(alcRenderSamplesSOFT
),
214 DECL(alcDevicePauseSOFT
),
215 DECL(alcDeviceResumeSOFT
),
217 DECL(alcGetStringiSOFT
),
218 DECL(alcResetDeviceSOFT
),
220 DECL(alcGetInteger64vSOFT
),
235 DECL(alIsExtensionPresent
),
236 DECL(alGetProcAddress
),
237 DECL(alGetEnumValue
),
244 DECL(alGetListenerf
),
245 DECL(alGetListener3f
),
246 DECL(alGetListenerfv
),
247 DECL(alGetListeneri
),
248 DECL(alGetListener3i
),
249 DECL(alGetListeneriv
),
251 DECL(alDeleteSources
),
267 DECL(alSourceRewindv
),
268 DECL(alSourcePausev
),
271 DECL(alSourceRewind
),
273 DECL(alSourceQueueBuffers
),
274 DECL(alSourceUnqueueBuffers
),
276 DECL(alDeleteBuffers
),
291 DECL(alDopplerFactor
),
292 DECL(alDopplerVelocity
),
293 DECL(alSpeedOfSound
),
294 DECL(alDistanceModel
),
297 DECL(alDeleteFilters
),
308 DECL(alDeleteEffects
),
318 DECL(alGenAuxiliaryEffectSlots
),
319 DECL(alDeleteAuxiliaryEffectSlots
),
320 DECL(alIsAuxiliaryEffectSlot
),
321 DECL(alAuxiliaryEffectSloti
),
322 DECL(alAuxiliaryEffectSlotiv
),
323 DECL(alAuxiliaryEffectSlotf
),
324 DECL(alAuxiliaryEffectSlotfv
),
325 DECL(alGetAuxiliaryEffectSloti
),
326 DECL(alGetAuxiliaryEffectSlotiv
),
327 DECL(alGetAuxiliaryEffectSlotf
),
328 DECL(alGetAuxiliaryEffectSlotfv
),
330 DECL(alDeferUpdatesSOFT
),
331 DECL(alProcessUpdatesSOFT
),
334 DECL(alSource3dSOFT
),
335 DECL(alSourcedvSOFT
),
336 DECL(alGetSourcedSOFT
),
337 DECL(alGetSource3dSOFT
),
338 DECL(alGetSourcedvSOFT
),
339 DECL(alSourcei64SOFT
),
340 DECL(alSource3i64SOFT
),
341 DECL(alSourcei64vSOFT
),
342 DECL(alGetSourcei64SOFT
),
343 DECL(alGetSource3i64SOFT
),
344 DECL(alGetSourcei64vSOFT
),
346 DECL(alGetStringiSOFT
),
348 DECL(alBufferStorageSOFT
),
349 DECL(alMapBufferSOFT
),
350 DECL(alUnmapBufferSOFT
),
351 DECL(alFlushMappedBufferSOFT
),
353 DECL(alEventControlSOFT
),
354 DECL(alEventCallbackSOFT
),
355 DECL(alGetPointerSOFT
),
356 DECL(alGetPointervSOFT
),
360 #define DECL(x) { #x, (x) }
362 const ALCchar
*enumName
;
364 } alcEnumerations
[] = {
369 DECL(ALC_MAJOR_VERSION
),
370 DECL(ALC_MINOR_VERSION
),
371 DECL(ALC_ATTRIBUTES_SIZE
),
372 DECL(ALC_ALL_ATTRIBUTES
),
373 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
374 DECL(ALC_DEVICE_SPECIFIER
),
375 DECL(ALC_ALL_DEVICES_SPECIFIER
),
376 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
377 DECL(ALC_EXTENSIONS
),
381 DECL(ALC_MONO_SOURCES
),
382 DECL(ALC_STEREO_SOURCES
),
383 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
384 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
385 DECL(ALC_CAPTURE_SAMPLES
),
388 DECL(ALC_EFX_MAJOR_VERSION
),
389 DECL(ALC_EFX_MINOR_VERSION
),
390 DECL(ALC_MAX_AUXILIARY_SENDS
),
392 DECL(ALC_FORMAT_CHANNELS_SOFT
),
393 DECL(ALC_FORMAT_TYPE_SOFT
),
396 DECL(ALC_STEREO_SOFT
),
398 DECL(ALC_5POINT1_SOFT
),
399 DECL(ALC_6POINT1_SOFT
),
400 DECL(ALC_7POINT1_SOFT
),
401 DECL(ALC_BFORMAT3D_SOFT
),
404 DECL(ALC_UNSIGNED_BYTE_SOFT
),
405 DECL(ALC_SHORT_SOFT
),
406 DECL(ALC_UNSIGNED_SHORT_SOFT
),
408 DECL(ALC_UNSIGNED_INT_SOFT
),
409 DECL(ALC_FLOAT_SOFT
),
412 DECL(ALC_DONT_CARE_SOFT
),
413 DECL(ALC_HRTF_STATUS_SOFT
),
414 DECL(ALC_HRTF_DISABLED_SOFT
),
415 DECL(ALC_HRTF_ENABLED_SOFT
),
416 DECL(ALC_HRTF_DENIED_SOFT
),
417 DECL(ALC_HRTF_REQUIRED_SOFT
),
418 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
419 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
420 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
421 DECL(ALC_HRTF_SPECIFIER_SOFT
),
422 DECL(ALC_HRTF_ID_SOFT
),
424 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
425 DECL(ALC_AMBISONIC_SCALING_SOFT
),
426 DECL(ALC_AMBISONIC_ORDER_SOFT
),
432 DECL(ALC_OUTPUT_LIMITER_SOFT
),
435 DECL(ALC_INVALID_DEVICE
),
436 DECL(ALC_INVALID_CONTEXT
),
437 DECL(ALC_INVALID_ENUM
),
438 DECL(ALC_INVALID_VALUE
),
439 DECL(ALC_OUT_OF_MEMORY
),
447 DECL(AL_SOURCE_RELATIVE
),
448 DECL(AL_CONE_INNER_ANGLE
),
449 DECL(AL_CONE_OUTER_ANGLE
),
459 DECL(AL_ORIENTATION
),
460 DECL(AL_REFERENCE_DISTANCE
),
461 DECL(AL_ROLLOFF_FACTOR
),
462 DECL(AL_CONE_OUTER_GAIN
),
463 DECL(AL_MAX_DISTANCE
),
465 DECL(AL_SAMPLE_OFFSET
),
466 DECL(AL_BYTE_OFFSET
),
467 DECL(AL_SOURCE_TYPE
),
470 DECL(AL_UNDETERMINED
),
471 DECL(AL_METERS_PER_UNIT
),
472 DECL(AL_LOOP_POINTS_SOFT
),
473 DECL(AL_DIRECT_CHANNELS_SOFT
),
475 DECL(AL_DIRECT_FILTER
),
476 DECL(AL_AUXILIARY_SEND_FILTER
),
477 DECL(AL_AIR_ABSORPTION_FACTOR
),
478 DECL(AL_ROOM_ROLLOFF_FACTOR
),
479 DECL(AL_CONE_OUTER_GAINHF
),
480 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
481 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
482 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
484 DECL(AL_SOURCE_STATE
),
490 DECL(AL_BUFFERS_QUEUED
),
491 DECL(AL_BUFFERS_PROCESSED
),
493 DECL(AL_FORMAT_MONO8
),
494 DECL(AL_FORMAT_MONO16
),
495 DECL(AL_FORMAT_MONO_FLOAT32
),
496 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
497 DECL(AL_FORMAT_STEREO8
),
498 DECL(AL_FORMAT_STEREO16
),
499 DECL(AL_FORMAT_STEREO_FLOAT32
),
500 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
501 DECL(AL_FORMAT_MONO_IMA4
),
502 DECL(AL_FORMAT_STEREO_IMA4
),
503 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
504 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
505 DECL(AL_FORMAT_QUAD8_LOKI
),
506 DECL(AL_FORMAT_QUAD16_LOKI
),
507 DECL(AL_FORMAT_QUAD8
),
508 DECL(AL_FORMAT_QUAD16
),
509 DECL(AL_FORMAT_QUAD32
),
510 DECL(AL_FORMAT_51CHN8
),
511 DECL(AL_FORMAT_51CHN16
),
512 DECL(AL_FORMAT_51CHN32
),
513 DECL(AL_FORMAT_61CHN8
),
514 DECL(AL_FORMAT_61CHN16
),
515 DECL(AL_FORMAT_61CHN32
),
516 DECL(AL_FORMAT_71CHN8
),
517 DECL(AL_FORMAT_71CHN16
),
518 DECL(AL_FORMAT_71CHN32
),
519 DECL(AL_FORMAT_REAR8
),
520 DECL(AL_FORMAT_REAR16
),
521 DECL(AL_FORMAT_REAR32
),
522 DECL(AL_FORMAT_MONO_MULAW
),
523 DECL(AL_FORMAT_MONO_MULAW_EXT
),
524 DECL(AL_FORMAT_STEREO_MULAW
),
525 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
526 DECL(AL_FORMAT_QUAD_MULAW
),
527 DECL(AL_FORMAT_51CHN_MULAW
),
528 DECL(AL_FORMAT_61CHN_MULAW
),
529 DECL(AL_FORMAT_71CHN_MULAW
),
530 DECL(AL_FORMAT_REAR_MULAW
),
531 DECL(AL_FORMAT_MONO_ALAW_EXT
),
532 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
534 DECL(AL_FORMAT_BFORMAT2D_8
),
535 DECL(AL_FORMAT_BFORMAT2D_16
),
536 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
537 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
538 DECL(AL_FORMAT_BFORMAT3D_8
),
539 DECL(AL_FORMAT_BFORMAT3D_16
),
540 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
541 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
547 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
548 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
550 DECL(AL_SOURCE_RADIUS
),
552 DECL(AL_STEREO_ANGLES
),
559 DECL(AL_INVALID_NAME
),
560 DECL(AL_INVALID_ENUM
),
561 DECL(AL_INVALID_VALUE
),
562 DECL(AL_INVALID_OPERATION
),
563 DECL(AL_OUT_OF_MEMORY
),
570 DECL(AL_DOPPLER_FACTOR
),
571 DECL(AL_DOPPLER_VELOCITY
),
572 DECL(AL_DISTANCE_MODEL
),
573 DECL(AL_SPEED_OF_SOUND
),
574 DECL(AL_SOURCE_DISTANCE_MODEL
),
575 DECL(AL_DEFERRED_UPDATES_SOFT
),
576 DECL(AL_GAIN_LIMIT_SOFT
),
578 DECL(AL_INVERSE_DISTANCE
),
579 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
580 DECL(AL_LINEAR_DISTANCE
),
581 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
582 DECL(AL_EXPONENT_DISTANCE
),
583 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
585 DECL(AL_FILTER_TYPE
),
586 DECL(AL_FILTER_NULL
),
587 DECL(AL_FILTER_LOWPASS
),
588 DECL(AL_FILTER_HIGHPASS
),
589 DECL(AL_FILTER_BANDPASS
),
591 DECL(AL_LOWPASS_GAIN
),
592 DECL(AL_LOWPASS_GAINHF
),
594 DECL(AL_HIGHPASS_GAIN
),
595 DECL(AL_HIGHPASS_GAINLF
),
597 DECL(AL_BANDPASS_GAIN
),
598 DECL(AL_BANDPASS_GAINHF
),
599 DECL(AL_BANDPASS_GAINLF
),
601 DECL(AL_EFFECT_TYPE
),
602 DECL(AL_EFFECT_NULL
),
603 DECL(AL_EFFECT_REVERB
),
604 DECL(AL_EFFECT_EAXREVERB
),
605 DECL(AL_EFFECT_CHORUS
),
606 DECL(AL_EFFECT_DISTORTION
),
607 DECL(AL_EFFECT_ECHO
),
608 DECL(AL_EFFECT_FLANGER
),
609 DECL(AL_EFFECT_PITCH_SHIFTER
),
610 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
612 DECL(AL_EFFECT_VOCAL_MORPHER
),
614 DECL(AL_EFFECT_RING_MODULATOR
),
615 DECL(AL_EFFECT_AUTOWAH
),
616 DECL(AL_EFFECT_COMPRESSOR
),
617 DECL(AL_EFFECT_EQUALIZER
),
618 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
619 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
621 DECL(AL_EFFECTSLOT_EFFECT
),
622 DECL(AL_EFFECTSLOT_GAIN
),
623 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
624 DECL(AL_EFFECTSLOT_NULL
),
626 DECL(AL_EAXREVERB_DENSITY
),
627 DECL(AL_EAXREVERB_DIFFUSION
),
628 DECL(AL_EAXREVERB_GAIN
),
629 DECL(AL_EAXREVERB_GAINHF
),
630 DECL(AL_EAXREVERB_GAINLF
),
631 DECL(AL_EAXREVERB_DECAY_TIME
),
632 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
633 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
634 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
635 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
636 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
637 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
638 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
639 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
640 DECL(AL_EAXREVERB_ECHO_TIME
),
641 DECL(AL_EAXREVERB_ECHO_DEPTH
),
642 DECL(AL_EAXREVERB_MODULATION_TIME
),
643 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
644 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
645 DECL(AL_EAXREVERB_HFREFERENCE
),
646 DECL(AL_EAXREVERB_LFREFERENCE
),
647 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
648 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
650 DECL(AL_REVERB_DENSITY
),
651 DECL(AL_REVERB_DIFFUSION
),
652 DECL(AL_REVERB_GAIN
),
653 DECL(AL_REVERB_GAINHF
),
654 DECL(AL_REVERB_DECAY_TIME
),
655 DECL(AL_REVERB_DECAY_HFRATIO
),
656 DECL(AL_REVERB_REFLECTIONS_GAIN
),
657 DECL(AL_REVERB_REFLECTIONS_DELAY
),
658 DECL(AL_REVERB_LATE_REVERB_GAIN
),
659 DECL(AL_REVERB_LATE_REVERB_DELAY
),
660 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
661 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
662 DECL(AL_REVERB_DECAY_HFLIMIT
),
664 DECL(AL_CHORUS_WAVEFORM
),
665 DECL(AL_CHORUS_PHASE
),
666 DECL(AL_CHORUS_RATE
),
667 DECL(AL_CHORUS_DEPTH
),
668 DECL(AL_CHORUS_FEEDBACK
),
669 DECL(AL_CHORUS_DELAY
),
671 DECL(AL_DISTORTION_EDGE
),
672 DECL(AL_DISTORTION_GAIN
),
673 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
674 DECL(AL_DISTORTION_EQCENTER
),
675 DECL(AL_DISTORTION_EQBANDWIDTH
),
678 DECL(AL_ECHO_LRDELAY
),
679 DECL(AL_ECHO_DAMPING
),
680 DECL(AL_ECHO_FEEDBACK
),
681 DECL(AL_ECHO_SPREAD
),
683 DECL(AL_FLANGER_WAVEFORM
),
684 DECL(AL_FLANGER_PHASE
),
685 DECL(AL_FLANGER_RATE
),
686 DECL(AL_FLANGER_DEPTH
),
687 DECL(AL_FLANGER_FEEDBACK
),
688 DECL(AL_FLANGER_DELAY
),
690 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
691 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
692 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
694 DECL(AL_RING_MODULATOR_FREQUENCY
),
695 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
696 DECL(AL_RING_MODULATOR_WAVEFORM
),
698 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
699 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
701 DECL(AL_COMPRESSOR_ONOFF
),
703 DECL(AL_EQUALIZER_LOW_GAIN
),
704 DECL(AL_EQUALIZER_LOW_CUTOFF
),
705 DECL(AL_EQUALIZER_MID1_GAIN
),
706 DECL(AL_EQUALIZER_MID1_CENTER
),
707 DECL(AL_EQUALIZER_MID1_WIDTH
),
708 DECL(AL_EQUALIZER_MID2_GAIN
),
709 DECL(AL_EQUALIZER_MID2_CENTER
),
710 DECL(AL_EQUALIZER_MID2_WIDTH
),
711 DECL(AL_EQUALIZER_HIGH_GAIN
),
712 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
714 DECL(AL_DEDICATED_GAIN
),
716 DECL(AL_AUTOWAH_ATTACK_TIME
),
717 DECL(AL_AUTOWAH_RELEASE_TIME
),
718 DECL(AL_AUTOWAH_RESONANCE
),
719 DECL(AL_AUTOWAH_PEAK_GAIN
),
721 DECL(AL_NUM_RESAMPLERS_SOFT
),
722 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
723 DECL(AL_SOURCE_RESAMPLER_SOFT
),
724 DECL(AL_RESAMPLER_NAME_SOFT
),
726 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
729 DECL(AL_MAP_READ_BIT_SOFT
),
730 DECL(AL_MAP_WRITE_BIT_SOFT
),
731 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
732 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
734 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
735 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
736 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
737 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
738 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
739 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
740 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
744 constexpr ALCchar alcNoError
[] = "No Error";
745 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
746 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
747 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
748 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
749 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
752 /************************************************
754 ************************************************/
756 /* Enumerated device names */
757 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
759 std::string alcAllDevicesList
;
760 std::string alcCaptureDeviceList
;
762 /* Default is always the first in the list */
763 std::string alcDefaultAllDevicesSpecifier
;
764 std::string alcCaptureDefaultDeviceSpecifier
;
766 /* Default context extensions */
767 constexpr ALchar alExtList
[] =
771 "AL_EXT_EXPONENT_DISTANCE "
774 "AL_EXT_LINEAR_DISTANCE "
777 "AL_EXT_MULAW_BFORMAT "
778 "AL_EXT_MULAW_MCFORMATS "
780 "AL_EXT_source_distance_model "
781 "AL_EXT_SOURCE_RADIUS "
782 "AL_EXT_STEREO_ANGLES "
783 "AL_LOKI_quadriphonic "
784 "AL_SOFT_block_alignment "
785 "AL_SOFT_deferred_updates "
786 "AL_SOFT_direct_channels "
788 "AL_SOFTX_filter_gain_ex "
789 "AL_SOFT_gain_clamp_ex "
790 "AL_SOFT_loop_points "
791 "AL_SOFTX_map_buffer "
793 "AL_SOFT_source_latency "
794 "AL_SOFT_source_length "
795 "AL_SOFT_source_resampler "
796 "AL_SOFT_source_spatialize";
798 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
800 /* Thread-local current context */
801 std::atomic
<void(*)(ALCcontext
*)> ThreadCtxProc
{nullptr};
803 ALCcontext
*ctx
{nullptr};
808 auto destruct
= ThreadCtxProc
.load();
814 ALCcontext
*get() const noexcept
{ return ctx
; }
815 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
817 thread_local ThreadCtx LocalContext
;
818 /* Process-wide current context */
819 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
821 /* Flag to trap ALC device errors */
822 bool TrapALCError
{false};
824 /* One-time configuration init control */
825 std::once_flag alc_config_once
{};
827 /* Default effect that applies to sources that don't have an effect on send 0 */
828 ALeffect DefaultEffect
;
830 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
833 bool SuspendDefers
{true};
836 /************************************************
838 ************************************************/
839 constexpr ALCchar alcNoDeviceExtList
[] =
840 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
841 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
842 constexpr ALCchar alcExtensionList
[] =
843 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
844 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
845 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
846 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
847 constexpr ALCint alcMajorVersion
= 1;
848 constexpr ALCint alcMinorVersion
= 1;
850 constexpr ALCint alcEFXMajorVersion
= 1;
851 constexpr ALCint alcEFXMinorVersion
= 0;
854 /************************************************
856 ************************************************/
857 std::atomic
<ALCdevice
*> DeviceList
{nullptr};
859 std::recursive_mutex ListLock
;
863 /* Mixing thread piority level */
868 enum LogLevel LogLevel
= LogWarning
;
870 enum LogLevel LogLevel
= LogError
;
873 /************************************************
874 * Library initialization
875 ************************************************/
877 static void alc_init(void);
878 static void alc_deinit(void);
879 static void alc_deinit_safe(void);
881 #ifndef AL_LIBTYPE_STATIC
882 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
886 case DLL_PROCESS_ATTACH
:
887 /* Pin the DLL so we won't get unloaded until the process terminates */
888 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
889 (WCHAR
*)hModule
, &hModule
);
893 case DLL_PROCESS_DETACH
:
902 #elif defined(_MSC_VER)
903 #pragma section(".CRT$XCU",read)
904 static void alc_constructor(void);
905 static void alc_destructor(void);
906 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
908 static void alc_constructor(void)
910 atexit(alc_destructor
);
914 static void alc_destructor(void)
918 #elif defined(HAVE_GCC_DESTRUCTOR)
919 static void alc_init(void) __attribute__((constructor
));
920 static void alc_deinit(void) __attribute__((destructor
));
922 #error "No static initialization available on this platform!"
925 #elif defined(HAVE_GCC_DESTRUCTOR)
927 static void alc_init(void) __attribute__((constructor
));
928 static void alc_deinit(void) __attribute__((destructor
));
931 #error "No global initialization available on this platform!"
934 static void ReleaseThreadCtx(ALCcontext
*ctx
);
935 static void alc_init(void)
939 const char *str
{getenv("__ALSOFT_HALF_ANGLE_CONES")};
940 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
943 str
= getenv("__ALSOFT_REVERSE_Z");
944 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
947 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
948 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
949 OverrideReverbSpeedOfSound
= AL_TRUE
;
951 ThreadCtxProc
= ReleaseThreadCtx
;
954 static void alc_initconfig(void)
956 const char *devs
, *str
;
961 str
= getenv("ALSOFT_LOGLEVEL");
964 long lvl
= strtol(str
, nullptr, 0);
965 if(lvl
>= NoLog
&& lvl
<= LogRef
)
966 LogLevel
= static_cast<enum LogLevel
>(lvl
);
969 str
= getenv("ALSOFT_LOGFILE");
973 std::wstring wname
{utf8_to_wstr(str
)};
974 FILE *logfile
= _wfopen(wname
.c_str(), L
"wt");
976 FILE *logfile
= fopen(str
, "wt");
978 if(logfile
) LogFile
= logfile
;
979 else ERR("Failed to open log file '%s'\n", str
);
982 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
983 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
986 if(BackendListSize
> 0)
987 names
+= BackendList
[0].name
;
988 for(i
= 1;i
< BackendListSize
;i
++)
991 names
+= BackendList
[i
].name
;
993 TRACE("Supported backends: %s\n", names
.c_str());
997 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
1000 if(strcasecmp(str
, "ignore") == 0)
1002 SuspendDefers
= false;
1003 TRACE("Selected context suspend behavior, \"ignore\"\n");
1006 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
1010 #if defined(HAVE_SSE4_1)
1011 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1012 #elif defined(HAVE_SSE3)
1013 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1014 #elif defined(HAVE_SSE2)
1015 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1016 #elif defined(HAVE_SSE)
1017 capfilter
|= CPU_CAP_SSE
;
1020 capfilter
|= CPU_CAP_NEON
;
1022 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str
))
1024 if(strcasecmp(str
, "all") == 0)
1029 const char *next
= str
;
1033 while(isspace(str
[0]))
1035 next
= strchr(str
, ',');
1037 if(!str
[0] || str
[0] == ',')
1040 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1041 while(len
> 0 && isspace(str
[len
-1]))
1043 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
1044 capfilter
&= ~CPU_CAP_SSE
;
1045 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
1046 capfilter
&= ~CPU_CAP_SSE2
;
1047 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
1048 capfilter
&= ~CPU_CAP_SSE3
;
1049 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
1050 capfilter
&= ~CPU_CAP_SSE4_1
;
1051 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
1052 capfilter
&= ~CPU_CAP_NEON
;
1054 WARN("Invalid CPU extension \"%s\"\n", str
);
1058 FillCPUCaps(capfilter
);
1065 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel
);
1070 str
= getenv("ALSOFT_TRAP_ERROR");
1071 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1073 TrapALError
= AL_TRUE
;
1074 TrapALCError
= true;
1078 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1079 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1080 TrapALError
= AL_TRUE
;
1081 TrapALError
= GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError
);
1083 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1084 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1085 TrapALCError
= true;
1086 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError
);
1089 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf
))
1090 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1092 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1093 ConfigValueStr(nullptr, nullptr, "drivers", &devs
))
1097 const char *next
= devs
;
1098 int endlist
, delitem
;
1103 while(isspace(devs
[0]))
1105 next
= strchr(devs
, ',');
1107 delitem
= (devs
[0] == '-');
1108 if(devs
[0] == '-') devs
++;
1110 if(!devs
[0] || devs
[0] == ',')
1117 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1118 while(len
> 0 && isspace(devs
[len
-1]))
1121 /* HACK: For backwards compatibility, convert backend references of
1122 * mmdevapi to wasapi. This should eventually be removed.
1124 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1130 for(n
= i
;n
< BackendListSize
;n
++)
1132 if(len
== strlen(BackendList
[n
].name
) &&
1133 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1137 for(;n
+1 < BackendListSize
;n
++)
1138 BackendList
[n
] = BackendList
[n
+1];
1143 struct BackendInfo Bkp
= BackendList
[n
];
1145 BackendList
[n
] = BackendList
[n
-1];
1146 BackendList
[n
] = Bkp
;
1156 BackendListSize
= i
;
1159 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1161 BackendList
[n
] = BackendList
[i
];
1163 BackendFactory
&factory
= BackendList
[n
].getFactory();
1166 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1170 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1171 if(!PlaybackBackend
.name
&& factory
.querySupport(ALCbackend_Playback
))
1173 PlaybackBackend
= BackendList
[n
];
1174 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1176 if(!CaptureBackend
.name
&& factory
.querySupport(ALCbackend_Capture
))
1178 CaptureBackend
= BackendList
[n
];
1179 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1183 BackendListSize
= n
;
1185 LoopbackBackendFactory::getFactory().init();
1187 if(!PlaybackBackend
.name
)
1188 WARN("No playback backend available!\n");
1189 if(!CaptureBackend
.name
)
1190 WARN("No capture backend available!\n");
1192 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str
))
1195 const char *next
= str
;
1199 next
= strchr(str
, ',');
1201 if(!str
[0] || next
== str
)
1204 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1205 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1207 if(len
== strlen(EffectList
[n
].name
) &&
1208 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1209 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1214 InitEffect(&DefaultEffect
);
1215 str
= getenv("ALSOFT_DEFAULT_REVERB");
1216 if((str
&& str
[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str
))
1217 LoadReverbPreset(str
, &DefaultEffect
);
1219 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1222 /************************************************
1223 * Library deinitialization
1224 ************************************************/
1225 static void alc_cleanup(void)
1227 alcAllDevicesList
.clear();
1228 alcCaptureDeviceList
.clear();
1230 alcDefaultAllDevicesSpecifier
.clear();
1231 alcCaptureDefaultDeviceSpecifier
.clear();
1233 if(ALCdevice
*dev
{DeviceList
.exchange(nullptr)})
1238 dev
= dev
->next
.load(std::memory_order_relaxed
);
1239 } while(dev
!= nullptr);
1240 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1244 static void alc_deinit_safe(void)
1251 ThreadCtxProc
= nullptr;
1253 if(LogFile
!= stderr
)
1258 static void alc_deinit(void)
1264 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1265 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1267 for(i
= 0;i
< BackendListSize
;i
++)
1268 BackendList
[i
].getFactory().deinit();
1270 LoopbackBackendFactory::getFactory().deinit();
1276 /************************************************
1277 * Device enumeration
1278 ************************************************/
1279 static void ProbeDevices(std::string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1283 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1285 if(backendinfo
->getFactory
)
1286 backendinfo
->getFactory().probe(type
, list
);
1288 static void ProbeAllDevicesList(void)
1289 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1290 static void ProbeCaptureDeviceList(void)
1291 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1294 /************************************************
1295 * Device format information
1296 ************************************************/
1297 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1301 case DevFmtByte
: return "Signed Byte";
1302 case DevFmtUByte
: return "Unsigned Byte";
1303 case DevFmtShort
: return "Signed Short";
1304 case DevFmtUShort
: return "Unsigned Short";
1305 case DevFmtInt
: return "Signed Int";
1306 case DevFmtUInt
: return "Unsigned Int";
1307 case DevFmtFloat
: return "Float";
1309 return "(unknown type)";
1311 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1315 case DevFmtMono
: return "Mono";
1316 case DevFmtStereo
: return "Stereo";
1317 case DevFmtQuad
: return "Quadraphonic";
1318 case DevFmtX51
: return "5.1 Surround";
1319 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1320 case DevFmtX61
: return "6.1 Surround";
1321 case DevFmtX71
: return "7.1 Surround";
1322 case DevFmtAmbi3D
: return "Ambisonic 3D";
1324 return "(unknown channels)";
1327 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1331 case DevFmtByte
: return sizeof(ALbyte
);
1332 case DevFmtUByte
: return sizeof(ALubyte
);
1333 case DevFmtShort
: return sizeof(ALshort
);
1334 case DevFmtUShort
: return sizeof(ALushort
);
1335 case DevFmtInt
: return sizeof(ALint
);
1336 case DevFmtUInt
: return sizeof(ALuint
);
1337 case DevFmtFloat
: return sizeof(ALfloat
);
1341 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1345 case DevFmtMono
: return 1;
1346 case DevFmtStereo
: return 2;
1347 case DevFmtQuad
: return 4;
1348 case DevFmtX51
: return 6;
1349 case DevFmtX51Rear
: return 6;
1350 case DevFmtX61
: return 7;
1351 case DevFmtX71
: return 8;
1352 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1353 (ambiorder
== 2) ? 9 :
1354 (ambiorder
== 1) ? 4 : 1;
1359 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1360 enum DevFmtType
*type
)
1362 static const struct {
1364 enum DevFmtChannels channels
;
1365 enum DevFmtType type
;
1367 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1368 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1369 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1371 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1372 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1373 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1375 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1376 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1377 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1379 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1380 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1381 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1383 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1384 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1385 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1387 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1388 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1389 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1393 for(i
= 0;i
< COUNTOF(list
);i
++)
1395 if(list
[i
].format
== format
)
1397 *chans
= list
[i
].channels
;
1398 *type
= list
[i
].type
;
1406 static ALCboolean
IsValidALCType(ALCenum type
)
1411 case ALC_UNSIGNED_BYTE_SOFT
:
1412 case ALC_SHORT_SOFT
:
1413 case ALC_UNSIGNED_SHORT_SOFT
:
1415 case ALC_UNSIGNED_INT_SOFT
:
1416 case ALC_FLOAT_SOFT
:
1422 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1427 case ALC_STEREO_SOFT
:
1429 case ALC_5POINT1_SOFT
:
1430 case ALC_6POINT1_SOFT
:
1431 case ALC_7POINT1_SOFT
:
1432 case ALC_BFORMAT3D_SOFT
:
1438 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1449 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1461 /************************************************
1462 * Miscellaneous ALC helpers
1463 ************************************************/
1465 /* SetDefaultWFXChannelOrder
1467 * Sets the default channel order used by WaveFormatEx.
1469 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1473 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1474 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1476 switch(device
->FmtChans
)
1479 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1482 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1483 device
->RealOut
.ChannelName
[1] = FrontRight
;
1486 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1487 device
->RealOut
.ChannelName
[1] = FrontRight
;
1488 device
->RealOut
.ChannelName
[2] = BackLeft
;
1489 device
->RealOut
.ChannelName
[3] = BackRight
;
1492 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1493 device
->RealOut
.ChannelName
[1] = FrontRight
;
1494 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1495 device
->RealOut
.ChannelName
[3] = LFE
;
1496 device
->RealOut
.ChannelName
[4] = SideLeft
;
1497 device
->RealOut
.ChannelName
[5] = SideRight
;
1500 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1501 device
->RealOut
.ChannelName
[1] = FrontRight
;
1502 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1503 device
->RealOut
.ChannelName
[3] = LFE
;
1504 device
->RealOut
.ChannelName
[4] = BackLeft
;
1505 device
->RealOut
.ChannelName
[5] = BackRight
;
1508 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1509 device
->RealOut
.ChannelName
[1] = FrontRight
;
1510 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1511 device
->RealOut
.ChannelName
[3] = LFE
;
1512 device
->RealOut
.ChannelName
[4] = BackCenter
;
1513 device
->RealOut
.ChannelName
[5] = SideLeft
;
1514 device
->RealOut
.ChannelName
[6] = SideRight
;
1517 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1518 device
->RealOut
.ChannelName
[1] = FrontRight
;
1519 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1520 device
->RealOut
.ChannelName
[3] = LFE
;
1521 device
->RealOut
.ChannelName
[4] = BackLeft
;
1522 device
->RealOut
.ChannelName
[5] = BackRight
;
1523 device
->RealOut
.ChannelName
[6] = SideLeft
;
1524 device
->RealOut
.ChannelName
[7] = SideRight
;
1527 device
->RealOut
.ChannelName
[0] = Aux0
;
1528 if(device
->mAmbiOrder
> 0)
1530 device
->RealOut
.ChannelName
[1] = Aux1
;
1531 device
->RealOut
.ChannelName
[2] = Aux2
;
1532 device
->RealOut
.ChannelName
[3] = Aux3
;
1534 if(device
->mAmbiOrder
> 1)
1536 device
->RealOut
.ChannelName
[4] = Aux4
;
1537 device
->RealOut
.ChannelName
[5] = Aux5
;
1538 device
->RealOut
.ChannelName
[6] = Aux6
;
1539 device
->RealOut
.ChannelName
[7] = Aux7
;
1540 device
->RealOut
.ChannelName
[8] = Aux8
;
1542 if(device
->mAmbiOrder
> 2)
1544 device
->RealOut
.ChannelName
[9] = Aux9
;
1545 device
->RealOut
.ChannelName
[10] = Aux10
;
1546 device
->RealOut
.ChannelName
[11] = Aux11
;
1547 device
->RealOut
.ChannelName
[12] = Aux12
;
1548 device
->RealOut
.ChannelName
[13] = Aux13
;
1549 device
->RealOut
.ChannelName
[14] = Aux14
;
1550 device
->RealOut
.ChannelName
[15] = Aux15
;
1556 /* SetDefaultChannelOrder
1558 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1560 void SetDefaultChannelOrder(ALCdevice
*device
)
1564 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1565 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1567 switch(device
->FmtChans
)
1570 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1571 device
->RealOut
.ChannelName
[1] = FrontRight
;
1572 device
->RealOut
.ChannelName
[2] = BackLeft
;
1573 device
->RealOut
.ChannelName
[3] = BackRight
;
1574 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1575 device
->RealOut
.ChannelName
[5] = LFE
;
1578 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1579 device
->RealOut
.ChannelName
[1] = FrontRight
;
1580 device
->RealOut
.ChannelName
[2] = BackLeft
;
1581 device
->RealOut
.ChannelName
[3] = BackRight
;
1582 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1583 device
->RealOut
.ChannelName
[5] = LFE
;
1584 device
->RealOut
.ChannelName
[6] = SideLeft
;
1585 device
->RealOut
.ChannelName
[7] = SideRight
;
1588 /* Same as WFX order */
1595 SetDefaultWFXChannelOrder(device
);
1601 /* ALCcontext_DeferUpdates
1603 * Defers/suspends updates for the given context's listener and sources. This
1604 * does *NOT* stop mixing, but rather prevents certain property changes from
1607 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1609 context
->DeferUpdates
.store(true);
1612 /* ALCcontext_ProcessUpdates
1614 * Resumes update processing after being deferred.
1616 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1618 std::lock_guard
<almtx_t
> _
{context
->PropLock
};
1619 if(context
->DeferUpdates
.exchange(false))
1621 /* Tell the mixer to stop applying updates, then wait for any active
1622 * updating to finish, before providing updates.
1624 context
->HoldUpdates
.store(AL_TRUE
);
1625 while((context
->UpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1628 if(!context
->PropsClean
.test_and_set(std::memory_order_acq_rel
))
1629 UpdateContextProps(context
);
1630 if(!context
->Listener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1631 UpdateListenerProps(context
);
1632 UpdateAllEffectSlotProps(context
);
1633 UpdateAllSourceProps(context
);
1635 /* Now with all updates declared, let the mixer continue applying them
1636 * so they all happen at once.
1638 context
->HoldUpdates
.store(AL_FALSE
);
1645 * Stores the latest ALC device error
1647 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1649 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1653 /* DebugBreak() will cause an exception if there is no debugger */
1654 if(IsDebuggerPresent())
1656 #elif defined(SIGTRAP)
1662 device
->LastError
.store(errorCode
);
1664 LastNullDeviceError
.store(errorCode
);
1668 static struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1670 return CompressorInit(device
->RealOut
.NumChannels
, device
->Frequency
,
1671 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
,
1672 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1677 * Updates the device's base clock time with however many samples have been
1678 * done. This is used so frequency changes on the device don't cause the time
1679 * to jump forward or back. Must not be called while the device is running/
1682 static inline void UpdateClockBase(ALCdevice
*device
)
1684 IncrementRef(&device
->MixCount
);
1685 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1686 device
->SamplesDone
= 0;
1687 IncrementRef(&device
->MixCount
);
1690 /* UpdateDeviceParams
1692 * Updates device parameters according to the attribute list (caller is
1693 * responsible for holding the list lock).
1695 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1697 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1698 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1699 ALCenum gainLimiter
= device
->LimiterState
;
1700 const ALsizei old_sends
= device
->NumAuxSends
;
1701 ALsizei new_sends
= device
->NumAuxSends
;
1702 enum DevFmtChannels oldChans
;
1703 enum DevFmtType oldType
;
1704 ALboolean update_failed
;
1705 ALCsizei hrtf_id
= -1;
1706 ALCcontext
*context
;
1711 // Check for attributes
1712 if(device
->Type
== Loopback
)
1714 ALCsizei numMono
, numStereo
, numSends
;
1715 ALCenum alayout
= AL_NONE
;
1716 ALCenum ascale
= AL_NONE
;
1717 ALCenum schans
= AL_NONE
;
1718 ALCenum stype
= AL_NONE
;
1719 ALCsizei attrIdx
= 0;
1720 ALCsizei aorder
= 0;
1725 WARN("Missing attributes for loopback device\n");
1726 return ALC_INVALID_VALUE
;
1729 numMono
= device
->NumMonoSources
;
1730 numStereo
= device
->NumStereoSources
;
1731 numSends
= old_sends
;
1733 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1734 while(attrList
[attrIdx
])
1736 switch(attrList
[attrIdx
])
1738 case ALC_FORMAT_CHANNELS_SOFT
:
1739 schans
= attrList
[attrIdx
+ 1];
1740 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1741 if(!IsValidALCChannels(schans
))
1742 return ALC_INVALID_VALUE
;
1745 case ALC_FORMAT_TYPE_SOFT
:
1746 stype
= attrList
[attrIdx
+ 1];
1747 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1748 if(!IsValidALCType(stype
))
1749 return ALC_INVALID_VALUE
;
1753 freq
= attrList
[attrIdx
+ 1];
1754 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1755 if(freq
< MIN_OUTPUT_RATE
)
1756 return ALC_INVALID_VALUE
;
1759 case ALC_AMBISONIC_LAYOUT_SOFT
:
1760 alayout
= attrList
[attrIdx
+ 1];
1761 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1762 if(!IsValidAmbiLayout(alayout
))
1763 return ALC_INVALID_VALUE
;
1766 case ALC_AMBISONIC_SCALING_SOFT
:
1767 ascale
= attrList
[attrIdx
+ 1];
1768 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1769 if(!IsValidAmbiScaling(ascale
))
1770 return ALC_INVALID_VALUE
;
1773 case ALC_AMBISONIC_ORDER_SOFT
:
1774 aorder
= attrList
[attrIdx
+ 1];
1775 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1776 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1777 return ALC_INVALID_VALUE
;
1780 case ALC_MONO_SOURCES
:
1781 numMono
= attrList
[attrIdx
+ 1];
1782 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1783 numMono
= maxi(numMono
, 0);
1786 case ALC_STEREO_SOURCES
:
1787 numStereo
= attrList
[attrIdx
+ 1];
1788 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1789 numStereo
= maxi(numStereo
, 0);
1792 case ALC_MAX_AUXILIARY_SENDS
:
1793 numSends
= attrList
[attrIdx
+ 1];
1794 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1795 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1799 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1800 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1801 hrtf_appreq
= Hrtf_Disable
;
1802 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1803 hrtf_appreq
= Hrtf_Enable
;
1805 hrtf_appreq
= Hrtf_Default
;
1808 case ALC_HRTF_ID_SOFT
:
1809 hrtf_id
= attrList
[attrIdx
+ 1];
1810 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1813 case ALC_OUTPUT_LIMITER_SOFT
:
1814 gainLimiter
= attrList
[attrIdx
+ 1];
1815 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1819 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1820 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1828 if(!schans
|| !stype
|| !freq
)
1830 WARN("Missing format for loopback device\n");
1831 return ALC_INVALID_VALUE
;
1833 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1835 WARN("Missing ambisonic info for loopback device\n");
1836 return ALC_INVALID_VALUE
;
1839 if((device
->Flags
&DEVICE_RUNNING
))
1840 V0(device
->Backend
,stop
)();
1841 device
->Flags
&= ~DEVICE_RUNNING
;
1843 UpdateClockBase(device
);
1845 device
->Frequency
= freq
;
1846 device
->FmtChans
= static_cast<enum DevFmtChannels
>(schans
);
1847 device
->FmtType
= static_cast<enum DevFmtType
>(stype
);
1848 if(schans
== ALC_BFORMAT3D_SOFT
)
1850 device
->mAmbiOrder
= aorder
;
1851 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1852 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1855 if(numMono
> INT_MAX
-numStereo
)
1856 numMono
= INT_MAX
-numStereo
;
1857 numMono
+= numStereo
;
1858 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono
))
1864 numMono
= maxi(numMono
, 256);
1865 numStereo
= mini(numStereo
, numMono
);
1866 numMono
-= numStereo
;
1867 device
->SourcesMax
= numMono
+ numStereo
;
1869 device
->NumMonoSources
= numMono
;
1870 device
->NumStereoSources
= numStereo
;
1872 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends
))
1873 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1875 new_sends
= numSends
;
1877 else if(attrList
&& attrList
[0])
1879 ALCsizei numMono
, numStereo
, numSends
;
1880 ALCsizei attrIdx
= 0;
1883 /* If a context is already running on the device, stop playback so the
1884 * device attributes can be updated. */
1885 if((device
->Flags
&DEVICE_RUNNING
))
1886 V0(device
->Backend
,stop
)();
1887 device
->Flags
&= ~DEVICE_RUNNING
;
1889 UpdateClockBase(device
);
1891 freq
= device
->Frequency
;
1892 numMono
= device
->NumMonoSources
;
1893 numStereo
= device
->NumStereoSources
;
1894 numSends
= old_sends
;
1896 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1897 while(attrList
[attrIdx
])
1899 switch(attrList
[attrIdx
])
1902 freq
= attrList
[attrIdx
+ 1];
1903 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1904 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1907 case ALC_MONO_SOURCES
:
1908 numMono
= attrList
[attrIdx
+ 1];
1909 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1910 numMono
= maxi(numMono
, 0);
1913 case ALC_STEREO_SOURCES
:
1914 numStereo
= attrList
[attrIdx
+ 1];
1915 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1916 numStereo
= maxi(numStereo
, 0);
1919 case ALC_MAX_AUXILIARY_SENDS
:
1920 numSends
= attrList
[attrIdx
+ 1];
1921 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1922 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1926 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1927 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1928 hrtf_appreq
= Hrtf_Disable
;
1929 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1930 hrtf_appreq
= Hrtf_Enable
;
1932 hrtf_appreq
= Hrtf_Default
;
1935 case ALC_HRTF_ID_SOFT
:
1936 hrtf_id
= attrList
[attrIdx
+ 1];
1937 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1940 case ALC_OUTPUT_LIMITER_SOFT
:
1941 gainLimiter
= attrList
[attrIdx
+ 1];
1942 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1946 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1947 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1955 ConfigValueUInt(device
->DeviceName
.c_str(), nullptr, "frequency", &freq
);
1956 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1958 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1960 /* SSE and Neon do best with the update size being a multiple of 4 */
1961 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1962 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1964 device
->Frequency
= freq
;
1966 if(numMono
> INT_MAX
-numStereo
)
1967 numMono
= INT_MAX
-numStereo
;
1968 numMono
+= numStereo
;
1969 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sources", &numMono
))
1975 numMono
= maxi(numMono
, 256);
1976 numStereo
= mini(numStereo
, numMono
);
1977 numMono
-= numStereo
;
1978 device
->SourcesMax
= numMono
+ numStereo
;
1980 device
->NumMonoSources
= numMono
;
1981 device
->NumStereoSources
= numStereo
;
1983 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sends", &new_sends
))
1984 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1986 new_sends
= numSends
;
1989 if((device
->Flags
&DEVICE_RUNNING
))
1990 return ALC_NO_ERROR
;
1992 device
->Uhj_Encoder
= nullptr;
1994 al_free(device
->Bs2b
);
1995 device
->Bs2b
= nullptr;
1997 device
->ChannelDelay
.clear();
1998 device
->ChannelDelay
.shrink_to_fit();
2000 device
->Dry
.Buffer
= nullptr;
2001 device
->Dry
.NumChannels
= 0;
2002 device
->FOAOut
.Buffer
= nullptr;
2003 device
->FOAOut
.NumChannels
= 0;
2004 device
->RealOut
.Buffer
= nullptr;
2005 device
->RealOut
.NumChannels
= 0;
2006 device
->MixBuffer
.clear();
2007 device
->MixBuffer
.shrink_to_fit();
2009 UpdateClockBase(device
);
2010 device
->FixedLatency
= 0;
2012 device
->DitherSeed
= DITHER_RNG_SEED
;
2014 /*************************************************************************
2015 * Update device format request if HRTF is requested
2017 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2018 if(device
->Type
!= Loopback
)
2021 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf", &hrtf
))
2023 if(strcasecmp(hrtf
, "true") == 0)
2024 hrtf_userreq
= Hrtf_Enable
;
2025 else if(strcasecmp(hrtf
, "false") == 0)
2026 hrtf_userreq
= Hrtf_Disable
;
2027 else if(strcasecmp(hrtf
, "auto") != 0)
2028 ERR("Unexpected hrtf value: %s\n", hrtf
);
2031 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2033 struct Hrtf
*hrtf
= nullptr;
2034 if(device
->HrtfList
.empty())
2035 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
2036 if(!device
->HrtfList
.empty())
2038 if(hrtf_id
>= 0 && (size_t)hrtf_id
< device
->HrtfList
.size())
2039 hrtf
= GetLoadedHrtf(device
->HrtfList
[hrtf_id
].hrtf
);
2041 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
2046 device
->FmtChans
= DevFmtStereo
;
2047 device
->Frequency
= hrtf
->sampleRate
;
2048 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2049 if(device
->HrtfHandle
)
2050 Hrtf_DecRef(device
->HrtfHandle
);
2051 device
->HrtfHandle
= hrtf
;
2055 hrtf_userreq
= Hrtf_Default
;
2056 hrtf_appreq
= Hrtf_Disable
;
2057 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2062 oldFreq
= device
->Frequency
;
2063 oldChans
= device
->FmtChans
;
2064 oldType
= device
->FmtType
;
2066 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2067 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2068 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2069 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2070 device
->UpdateSize
, device
->NumUpdates
2073 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2074 return ALC_INVALID_DEVICE
;
2076 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2078 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2079 DevFmtChannelsString(device
->FmtChans
));
2080 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2082 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2084 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2085 DevFmtTypeString(device
->FmtType
));
2086 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2088 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2090 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2091 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2094 if((device
->UpdateSize
&3) != 0)
2096 if((CPUCapFlags
&CPU_CAP_SSE
))
2097 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2098 if((CPUCapFlags
&CPU_CAP_NEON
))
2099 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2102 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2103 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2104 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2107 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2108 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2109 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2111 /* Allocate extra channels for any post-filter output. */
2112 ALsizei num_chans
{device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2113 device
->RealOut
.NumChannels
};
2115 TRACE("Allocating %d channels, " SZFMT
" bytes\n", num_chans
,
2116 num_chans
*sizeof(device
->MixBuffer
[0]));
2117 device
->MixBuffer
.resize(num_chans
);
2119 device
->Dry
.Buffer
= &reinterpret_cast<ALfloat(&)[BUFFERSIZE
]>(device
->MixBuffer
[0]);
2120 if(device
->RealOut
.NumChannels
!= 0)
2121 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2122 device
->FOAOut
.NumChannels
;
2125 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2126 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2129 if(device
->FOAOut
.NumChannels
!= 0)
2130 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2133 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2134 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2137 device
->NumAuxSends
= new_sends
;
2138 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2139 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2140 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2142 device
->DitherDepth
= 0.0f
;
2143 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2146 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth", &depth
);
2149 switch(device
->FmtType
)
2168 depth
= clampi(depth
, 2, 24);
2169 device
->DitherDepth
= std::pow(2.0f
, (ALfloat
)(depth
-1));
2172 if(!(device
->DitherDepth
> 0.0f
))
2173 TRACE("Dithering disabled\n");
2175 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2176 device
->DitherDepth
);
2178 device
->LimiterState
= gainLimiter
;
2179 if(ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter", &val
))
2180 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2182 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2183 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2184 * output (where samples must be clamped), and don't for floating-point
2185 * (which can take unclamped samples).
2187 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2189 switch(device
->FmtType
)
2197 gainLimiter
= ALC_TRUE
;
2200 gainLimiter
= ALC_FALSE
;
2204 if(gainLimiter
!= ALC_FALSE
)
2206 ALfloat thrshld
= 1.0f
;
2207 switch(device
->FmtType
)
2211 thrshld
= 127.0f
/ 128.0f
;
2215 thrshld
= 32767.0f
/ 32768.0f
;
2222 if(device
->DitherDepth
> 0.0f
)
2223 thrshld
-= 1.0f
/ device
->DitherDepth
;
2225 device
->Limiter
.reset(CreateDeviceLimiter(device
, std::log10(thrshld
) * 20.0f
));
2226 device
->FixedLatency
+= (ALuint
)(GetCompressorLookAhead(device
->Limiter
.get()) *
2227 DEVICE_CLOCK_RES
/ device
->Frequency
);
2230 device
->Limiter
= nullptr;
2231 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2233 aluSelectPostProcess(device
);
2235 TRACE("Fixed device latency: %uns\n", device
->FixedLatency
);
2237 /* Need to delay returning failure until replacement Send arrays have been
2238 * allocated with the appropriate size.
2240 update_failed
= AL_FALSE
;
2241 FPUCtl mixer_mode
{};
2242 context
= device
->ContextList
.load();
2245 struct ALvoiceProps
*vprops
;
2248 if(context
->DefaultSlot
)
2250 ALeffectslot
*slot
= context
->DefaultSlot
.get();
2251 EffectState
*state
= slot
->Effect
.State
;
2253 state
->mOutBuffer
= device
->Dry
.Buffer
;
2254 state
->mOutChannels
= device
->Dry
.NumChannels
;
2255 if(state
->deviceUpdate(device
) == AL_FALSE
)
2256 update_failed
= AL_TRUE
;
2258 UpdateEffectSlotProps(slot
, context
);
2261 std::unique_lock
<almtx_t
> proplock
{context
->PropLock
};
2262 std::unique_lock
<almtx_t
> slotlock
{context
->EffectSlotLock
};
2263 for(auto &slot
: context
->EffectSlotList
)
2265 EffectState
*state
= slot
->Effect
.State
;
2267 state
->mOutBuffer
= device
->Dry
.Buffer
;
2268 state
->mOutChannels
= device
->Dry
.NumChannels
;
2269 if(state
->deviceUpdate(device
) == AL_FALSE
)
2270 update_failed
= AL_TRUE
;
2272 UpdateEffectSlotProps(slot
.get(), context
);
2276 std::unique_lock
<almtx_t
> srclock
{context
->SourceLock
};
2277 for(auto &sublist
: context
->SourceList
)
2279 uint64_t usemask
= ~sublist
.FreeMask
;
2282 ALsizei idx
= CTZ64(usemask
);
2283 ALsource
*source
= sublist
.Sources
+ idx
;
2285 usemask
&= ~(U64(1) << idx
);
2287 if(old_sends
!= device
->NumAuxSends
)
2290 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2292 if(source
->Send
[s
].Slot
)
2293 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2294 source
->Send
[s
].Slot
= nullptr;
2296 source
->Send
.resize(device
->NumAuxSends
);
2297 source
->Send
.shrink_to_fit();
2298 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2300 source
->Send
[s
].Slot
= nullptr;
2301 source
->Send
[s
].Gain
= 1.0f
;
2302 source
->Send
[s
].GainHF
= 1.0f
;
2303 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2304 source
->Send
[s
].GainLF
= 1.0f
;
2305 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2309 source
->PropsClean
.clear(std::memory_order_release
);
2313 /* Clear any pre-existing voice property structs, in case the number of
2314 * auxiliary sends is changing. Active sources will have updates
2315 * respecified in UpdateAllSourceProps.
2317 vprops
= context
->FreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
);
2320 struct ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2325 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2326 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2328 ALvoice
*voice
= context
->Voices
[pos
];
2330 al_free(voice
->Update
.exchange(nullptr, std::memory_order_acq_rel
));
2332 if(voice
->Source
.load(std::memory_order_acquire
) == nullptr)
2335 if(device
->AvgSpeakerDist
> 0.0f
)
2337 /* Reinitialize the NFC filters for new parameters. */
2338 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2339 (device
->AvgSpeakerDist
* device
->Frequency
);
2340 for(i
= 0;i
< voice
->NumChannels
;i
++)
2341 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2346 context
->PropsClean
.test_and_set(std::memory_order_release
);
2347 UpdateContextProps(context
);
2348 context
->Listener
.PropsClean
.test_and_set(std::memory_order_release
);
2349 UpdateListenerProps(context
);
2350 UpdateAllSourceProps(context
);
2352 context
= context
->next
.load(std::memory_order_relaxed
);
2356 return ALC_INVALID_DEVICE
;
2358 if(!(device
->Flags
&DEVICE_PAUSED
))
2360 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2361 return ALC_INVALID_DEVICE
;
2362 device
->Flags
|= DEVICE_RUNNING
;
2365 return ALC_NO_ERROR
;
2369 ALCdevice_struct::ALCdevice_struct(DeviceType type
)
2372 almtx_init(&BufferLock
, almtx_plain
);
2373 almtx_init(&EffectLock
, almtx_plain
);
2374 almtx_init(&FilterLock
, almtx_plain
);
2376 almtx_init(&BackendLock
, almtx_plain
);
2379 /* ALCdevice_struct::~ALCdevice_struct
2381 * Frees the device structure, and destroys any objects the app failed to
2382 * delete. Called once there's no more references on the device.
2384 ALCdevice_struct::~ALCdevice_struct()
2386 TRACE("%p\n", this);
2389 DELETE_OBJ(Backend
);
2392 almtx_destroy(&BackendLock
);
2394 ReleaseALBuffers(this);
2395 std::for_each(BufferList
.begin(), BufferList
.end(),
2396 [](BufferSubList
&entry
) noexcept
-> void
2397 { al_free(entry
.Buffers
); }
2400 almtx_destroy(&BufferLock
);
2402 ReleaseALEffects(this);
2403 std::for_each(EffectList
.begin(), EffectList
.end(),
2404 [](EffectSubList
&entry
) noexcept
-> void
2405 { al_free(entry
.Effects
); }
2408 almtx_destroy(&EffectLock
);
2410 ReleaseALFilters(this);
2411 std::for_each(FilterList
.begin(), FilterList
.end(),
2412 [](FilterSubList
&entry
) noexcept
-> void
2413 { al_free(entry
.Filters
); }
2416 almtx_destroy(&FilterLock
);
2420 Hrtf_DecRef(HrtfHandle
);
2421 HrtfHandle
= nullptr;
2430 void ALCdevice_IncRef(ALCdevice
*device
)
2432 auto ref
= IncrementRef(&device
->ref
);
2433 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2436 void ALCdevice_DecRef(ALCdevice
*device
)
2438 auto ref
= DecrementRef(&device
->ref
);
2439 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2440 if(ref
== 0) delete device
;
2445 * Checks if the device handle is valid, and increments its ref count if so.
2447 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2449 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2450 ALCdevice
*tmpDevice
{DeviceList
.load()};
2453 if(tmpDevice
== *device
)
2455 ALCdevice_IncRef(tmpDevice
);
2458 tmpDevice
= tmpDevice
->next
.load(std::memory_order_relaxed
);
2466 ALCcontext_struct::ALCcontext_struct(ALCdevice
*device
)
2473 * Initializes context fields
2475 static ALvoid
InitContext(ALCcontext
*Context
)
2477 ALlistener
&listener
= Context
->Listener
;
2478 struct ALeffectslotArray
*auxslots
;
2481 almtx_init(&Context
->PropLock
, almtx_plain
);
2482 almtx_init(&Context
->SourceLock
, almtx_plain
);
2483 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2485 if(Context
->DefaultSlot
)
2487 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2488 FAM_SIZE(struct ALeffectslotArray
, slot
, 1)));
2489 auxslots
->count
= 1;
2490 auxslots
->slot
[0] = Context
->DefaultSlot
.get();
2494 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2495 sizeof(struct ALeffectslotArray
)));
2496 auxslots
->count
= 0;
2498 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2501 Context
->mDistanceModel
= DistanceModel::Default
;
2502 Context
->SourceDistanceModel
= AL_FALSE
;
2503 Context
->DopplerFactor
= 1.0f
;
2504 Context
->DopplerVelocity
= 1.0f
;
2505 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2506 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2507 alsem_init(&Context
->EventSem
, 0);
2509 Context
->ExtensionList
= alExtList
;
2512 listener
.Params
.Matrix
= aluMatrixf::Identity
;
2513 aluVectorSet(&listener
.Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2514 listener
.Params
.Gain
= listener
.Gain
;
2515 listener
.Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2516 listener
.Params
.DopplerFactor
= Context
->DopplerFactor
;
2517 listener
.Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2518 listener
.Params
.ReverbSpeedOfSound
= listener
.Params
.SpeedOfSound
*
2519 listener
.Params
.MetersPerUnit
;
2520 listener
.Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2521 listener
.Params
.mDistanceModel
= Context
->mDistanceModel
;
2524 Context
->AsyncEvents
= ll_ringbuffer_create(63, sizeof(AsyncEvent
), false);
2525 StartEventThrd(Context
);
2529 /* ALCcontext_struct::~ALCcontext_struct()
2531 * Cleans up the context, and destroys any remaining objects the app failed to
2532 * delete. Called once there's no more references on the context.
2534 ALCcontext_struct::~ALCcontext_struct()
2536 TRACE("%p\n", this);
2538 struct ALcontextProps
*cprops
{Update
.load(std::memory_order_relaxed
)};
2541 TRACE("Freed unapplied context update %p\n", cprops
);
2545 cprops
= FreeContextProps
.load(std::memory_order_acquire
);
2548 struct ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2553 TRACE("Freed " SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2555 al_free(ActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
));
2556 DefaultSlot
= nullptr;
2558 ReleaseALSources(this);
2559 std::for_each(SourceList
.begin(), SourceList
.end(),
2560 [](const SourceSubList
&entry
) noexcept
-> void
2561 { al_free(entry
.Sources
); }
2565 almtx_destroy(&SourceLock
);
2568 struct ALeffectslotProps
*eprops
{FreeEffectslotProps
.load(std::memory_order_acquire
)};
2571 struct ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2572 if(eprops
->State
) eprops
->State
->DecRef();
2577 TRACE("Freed " SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2579 ReleaseALAuxiliaryEffectSlots(this);
2580 EffectSlotList
.clear();
2581 almtx_destroy(&EffectSlotLock
);
2584 struct ALvoiceProps
*vprops
{FreeVoiceProps
.load(std::memory_order_acquire
)};
2587 struct ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2592 TRACE("Freed " SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2594 for(ALsizei i
{0};i
< VoiceCount
;i
++)
2595 DeinitVoice(Voices
[i
]);
2601 struct ALlistenerProps
*lprops
{Listener
.Update
.load(std::memory_order_relaxed
)};
2604 TRACE("Freed unapplied listener update %p\n", lprops
);
2608 lprops
= FreeListenerProps
.load(std::memory_order_acquire
);
2611 struct ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2616 TRACE("Freed " SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2618 alsem_destroy(&EventSem
);
2620 ll_ringbuffer_free(AsyncEvents
);
2621 AsyncEvents
= nullptr;
2623 almtx_destroy(&PropLock
);
2625 ALCdevice_DecRef(Device
);
2630 * Removes the context reference from the given device and removes it from
2631 * being current on the running thread or globally. Returns true if other
2632 * contexts still exist on the device.
2634 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2636 ALCcontext
*origctx
, *newhead
;
2639 if(LocalContext
.get() == context
)
2641 WARN("%p released while current on thread\n", context
);
2642 LocalContext
.set(nullptr);
2643 ALCcontext_DecRef(context
);
2647 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2648 ALCcontext_DecRef(context
);
2650 V0(device
->Backend
,lock
)();
2652 newhead
= context
->next
.load(std::memory_order_relaxed
);
2653 if(!device
->ContextList
.compare_exchange_strong(origctx
, newhead
))
2657 /* origctx is what the desired context failed to match. Try
2658 * swapping out the next one in the list.
2662 } while(!list
->next
.compare_exchange_strong(origctx
, newhead
));
2666 V0(device
->Backend
,unlock
)();
2668 /* Make sure the context is finished and no longer processing in the mixer
2669 * before sending the message queue kill event. The backend's lock does
2670 * this, although waiting for a non-odd mix count would work too.
2673 StopEventThrd(context
);
2675 ALCcontext_DecRef(context
);
2679 static void ALCcontext_IncRef(ALCcontext
*context
)
2681 auto ref
= IncrementRef(&context
->ref
);
2682 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2685 void ALCcontext_DecRef(ALCcontext
*context
)
2687 auto ref
= DecrementRef(&context
->ref
);
2688 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2689 if(ref
== 0) delete context
;
2692 static void ReleaseThreadCtx(ALCcontext
*context
)
2694 auto ref
= DecrementRef(&context
->ref
);
2695 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2696 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2701 * Checks if the given context is valid, returning a new reference to it if so.
2703 static ContextRef
VerifyContext(ALCcontext
*context
)
2705 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2706 ALCdevice
*dev
{DeviceList
.load()};
2709 ALCcontext
*ctx
= dev
->ContextList
.load(std::memory_order_acquire
);
2714 ALCcontext_IncRef(ctx
);
2715 return ContextRef
{ctx
};
2717 ctx
= ctx
->next
.load(std::memory_order_relaxed
);
2719 dev
= dev
->next
.load(std::memory_order_relaxed
);
2722 return ContextRef
{};
2728 * Returns the currently active context for this thread, and adds a reference
2729 * without locking it.
2731 ALCcontext
*GetContextRef(void)
2733 ALCcontext
*context
{LocalContext
.get()};
2735 ALCcontext_IncRef(context
);
2738 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2739 context
= GlobalContext
.load(std::memory_order_acquire
);
2740 if(context
) ALCcontext_IncRef(context
);
2747 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2749 ALCdevice
*device
= context
->Device
;
2750 ALsizei num_sends
= device
->NumAuxSends
;
2751 struct ALvoiceProps
*props
;
2752 size_t sizeof_props
;
2753 size_t sizeof_voice
;
2759 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2762 /* Allocate the voice pointers, voices, and the voices' stored source
2763 * property set (including the dynamically-sized Send[] array) in one
2766 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2767 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2768 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2770 voices
= static_cast<ALvoice
**>(al_calloc(16, RoundUp(size
*num_voices
, 16)));
2771 /* The voice and property objects are stored interleaved since they're
2774 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2775 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2779 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2780 const ALsizei s_count
= mini(old_sends
, num_sends
);
2782 for(;v
< v_count
;v
++)
2784 ALvoice
*old_voice
= context
->Voices
[v
];
2787 /* Copy the old voice data and source property set to the new
2790 memcpy(voice
, old_voice
, sizeof(*voice
));
2791 for(i
= 0;i
< s_count
;i
++)
2792 voice
->Send
[i
] = old_voice
->Send
[i
];
2794 memcpy(props
, old_voice
->Props
, sizeof(*props
));
2795 for(i
= 0;i
< s_count
;i
++)
2796 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2798 /* Set this voice's property set pointer and voice reference. */
2799 voice
->Props
= props
;
2802 /* Increment pointers to the next storage space. */
2803 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2804 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2806 /* Deinit any left over voices that weren't copied over to the new
2807 * array. NOTE: If this does anything, v equals num_voices and
2808 * num_voices is less than VoiceCount, so the following loop won't do
2811 for(;v
< context
->VoiceCount
;v
++)
2812 DeinitVoice(context
->Voices
[v
]);
2814 /* Finish setting the voices' property set pointers and references. */
2815 for(;v
< num_voices
;v
++)
2817 ATOMIC_INIT(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr));
2819 voice
->Props
= props
;
2822 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2823 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2826 al_free(context
->Voices
);
2827 context
->Voices
= voices
;
2828 context
->MaxVoices
= num_voices
;
2829 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2833 /************************************************
2834 * Standard ALC functions
2835 ************************************************/
2839 * Return last ALC generated error code for the given device
2841 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2845 if(VerifyDevice(&device
))
2847 errorCode
= device
->LastError
.exchange(ALC_NO_ERROR
);
2848 ALCdevice_DecRef(device
);
2851 errorCode
= LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2857 /* alcSuspendContext
2859 * Suspends updates for the given context
2861 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2866 ContextRef ctx
{VerifyContext(context
)};
2868 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2870 ALCcontext_DeferUpdates(ctx
.get());
2873 /* alcProcessContext
2875 * Resumes processing updates for the given context
2877 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2882 ContextRef ctx
{VerifyContext(context
)};
2884 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2886 ALCcontext_ProcessUpdates(ctx
.get());
2892 * Returns information about the device, and error strings
2894 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2896 const ALCchar
*value
= nullptr;
2904 case ALC_INVALID_ENUM
:
2905 value
= alcErrInvalidEnum
;
2908 case ALC_INVALID_VALUE
:
2909 value
= alcErrInvalidValue
;
2912 case ALC_INVALID_DEVICE
:
2913 value
= alcErrInvalidDevice
;
2916 case ALC_INVALID_CONTEXT
:
2917 value
= alcErrInvalidContext
;
2920 case ALC_OUT_OF_MEMORY
:
2921 value
= alcErrOutOfMemory
;
2924 case ALC_DEVICE_SPECIFIER
:
2925 value
= alcDefaultName
;
2928 case ALC_ALL_DEVICES_SPECIFIER
:
2929 if(VerifyDevice(&Device
))
2931 value
= Device
->DeviceName
.c_str();
2932 ALCdevice_DecRef(Device
);
2936 ProbeAllDevicesList();
2937 value
= alcAllDevicesList
.c_str();
2941 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2942 if(VerifyDevice(&Device
))
2944 value
= Device
->DeviceName
.c_str();
2945 ALCdevice_DecRef(Device
);
2949 ProbeCaptureDeviceList();
2950 value
= alcCaptureDeviceList
.c_str();
2954 /* Default devices are always first in the list */
2955 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2956 value
= alcDefaultName
;
2959 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2960 if(alcAllDevicesList
.empty())
2961 ProbeAllDevicesList();
2963 /* Copy first entry as default. */
2964 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2965 value
= alcDefaultAllDevicesSpecifier
.c_str();
2968 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2969 if(alcCaptureDeviceList
.empty())
2970 ProbeCaptureDeviceList();
2972 /* Copy first entry as default. */
2973 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2974 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2977 case ALC_EXTENSIONS
:
2978 if(!VerifyDevice(&Device
))
2979 value
= alcNoDeviceExtList
;
2982 value
= alcExtensionList
;
2983 ALCdevice_DecRef(Device
);
2987 case ALC_HRTF_SPECIFIER_SOFT
:
2988 if(!VerifyDevice(&Device
))
2989 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2992 { std::lock_guard
<almtx_t
> _
{Device
->BackendLock
};
2993 value
= (Device
->HrtfHandle
? Device
->HrtfName
.c_str() : "");
2995 ALCdevice_DecRef(Device
);
3000 VerifyDevice(&Device
);
3001 alcSetError(Device
, ALC_INVALID_ENUM
);
3002 if(Device
) ALCdevice_DecRef(Device
);
3010 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3012 if(device
->Type
== Capture
) return 9;
3013 if(device
->Type
!= Loopback
) return 29;
3014 if(device
->FmtChans
== DevFmtAmbi3D
)
3019 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3023 if(size
<= 0 || values
== nullptr)
3025 alcSetError(device
, ALC_INVALID_VALUE
);
3033 case ALC_MAJOR_VERSION
:
3034 values
[0] = alcMajorVersion
;
3036 case ALC_MINOR_VERSION
:
3037 values
[0] = alcMinorVersion
;
3040 case ALC_ATTRIBUTES_SIZE
:
3041 case ALC_ALL_ATTRIBUTES
:
3045 case ALC_MONO_SOURCES
:
3046 case ALC_STEREO_SOURCES
:
3047 case ALC_CAPTURE_SAMPLES
:
3048 case ALC_FORMAT_CHANNELS_SOFT
:
3049 case ALC_FORMAT_TYPE_SOFT
:
3050 case ALC_AMBISONIC_LAYOUT_SOFT
:
3051 case ALC_AMBISONIC_SCALING_SOFT
:
3052 case ALC_AMBISONIC_ORDER_SOFT
:
3053 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3054 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3058 alcSetError(nullptr, ALC_INVALID_ENUM
);
3064 if(device
->Type
== Capture
)
3068 case ALC_ATTRIBUTES_SIZE
:
3069 values
[0] = NumAttrsForDevice(device
);
3072 case ALC_ALL_ATTRIBUTES
:
3074 if(size
< NumAttrsForDevice(device
))
3075 alcSetError(device
, ALC_INVALID_VALUE
);
3078 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3079 values
[i
++] = ALC_MAJOR_VERSION
;
3080 values
[i
++] = alcMajorVersion
;
3081 values
[i
++] = ALC_MINOR_VERSION
;
3082 values
[i
++] = alcMinorVersion
;
3083 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3084 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3085 values
[i
++] = ALC_CONNECTED
;
3086 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
3091 case ALC_MAJOR_VERSION
:
3092 values
[0] = alcMajorVersion
;
3094 case ALC_MINOR_VERSION
:
3095 values
[0] = alcMinorVersion
;
3098 case ALC_CAPTURE_SAMPLES
:
3099 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3100 values
[0] = V0(device
->Backend
,availableSamples
)();
3105 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3109 alcSetError(device
, ALC_INVALID_ENUM
);
3118 case ALC_ATTRIBUTES_SIZE
:
3119 values
[0] = NumAttrsForDevice(device
);
3122 case ALC_ALL_ATTRIBUTES
:
3124 if(size
< NumAttrsForDevice(device
))
3125 alcSetError(device
, ALC_INVALID_VALUE
);
3128 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3129 values
[i
++] = ALC_MAJOR_VERSION
;
3130 values
[i
++] = alcMajorVersion
;
3131 values
[i
++] = ALC_MINOR_VERSION
;
3132 values
[i
++] = alcMinorVersion
;
3133 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3134 values
[i
++] = alcEFXMajorVersion
;
3135 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3136 values
[i
++] = alcEFXMinorVersion
;
3138 values
[i
++] = ALC_FREQUENCY
;
3139 values
[i
++] = device
->Frequency
;
3140 if(device
->Type
!= Loopback
)
3142 values
[i
++] = ALC_REFRESH
;
3143 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3145 values
[i
++] = ALC_SYNC
;
3146 values
[i
++] = ALC_FALSE
;
3150 if(device
->FmtChans
== DevFmtAmbi3D
)
3152 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3153 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
3155 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3156 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
3158 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3159 values
[i
++] = device
->mAmbiOrder
;
3162 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3163 values
[i
++] = device
->FmtChans
;
3165 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3166 values
[i
++] = device
->FmtType
;
3169 values
[i
++] = ALC_MONO_SOURCES
;
3170 values
[i
++] = device
->NumMonoSources
;
3172 values
[i
++] = ALC_STEREO_SOURCES
;
3173 values
[i
++] = device
->NumStereoSources
;
3175 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3176 values
[i
++] = device
->NumAuxSends
;
3178 values
[i
++] = ALC_HRTF_SOFT
;
3179 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3181 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3182 values
[i
++] = device
->HrtfStatus
;
3184 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3185 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3187 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3188 values
[i
++] = MAX_AMBI_ORDER
;
3194 case ALC_MAJOR_VERSION
:
3195 values
[0] = alcMajorVersion
;
3198 case ALC_MINOR_VERSION
:
3199 values
[0] = alcMinorVersion
;
3202 case ALC_EFX_MAJOR_VERSION
:
3203 values
[0] = alcEFXMajorVersion
;
3206 case ALC_EFX_MINOR_VERSION
:
3207 values
[0] = alcEFXMinorVersion
;
3211 values
[0] = device
->Frequency
;
3215 if(device
->Type
== Loopback
)
3217 alcSetError(device
, ALC_INVALID_DEVICE
);
3220 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3221 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3226 if(device
->Type
== Loopback
)
3228 alcSetError(device
, ALC_INVALID_DEVICE
);
3231 values
[0] = ALC_FALSE
;
3234 case ALC_FORMAT_CHANNELS_SOFT
:
3235 if(device
->Type
!= Loopback
)
3237 alcSetError(device
, ALC_INVALID_DEVICE
);
3240 values
[0] = device
->FmtChans
;
3243 case ALC_FORMAT_TYPE_SOFT
:
3244 if(device
->Type
!= Loopback
)
3246 alcSetError(device
, ALC_INVALID_DEVICE
);
3249 values
[0] = device
->FmtType
;
3252 case ALC_AMBISONIC_LAYOUT_SOFT
:
3253 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3255 alcSetError(device
, ALC_INVALID_DEVICE
);
3258 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
3261 case ALC_AMBISONIC_SCALING_SOFT
:
3262 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3264 alcSetError(device
, ALC_INVALID_DEVICE
);
3267 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
3270 case ALC_AMBISONIC_ORDER_SOFT
:
3271 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3273 alcSetError(device
, ALC_INVALID_DEVICE
);
3276 values
[0] = device
->mAmbiOrder
;
3279 case ALC_MONO_SOURCES
:
3280 values
[0] = device
->NumMonoSources
;
3283 case ALC_STEREO_SOURCES
:
3284 values
[0] = device
->NumStereoSources
;
3287 case ALC_MAX_AUXILIARY_SENDS
:
3288 values
[0] = device
->NumAuxSends
;
3292 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3296 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3299 case ALC_HRTF_STATUS_SOFT
:
3300 values
[0] = device
->HrtfStatus
;
3303 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3304 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3305 device
->HrtfList
.clear();
3306 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3307 values
[0] = (ALCint
)device
->HrtfList
.size();
3311 case ALC_OUTPUT_LIMITER_SOFT
:
3312 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3315 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3316 values
[0] = MAX_AMBI_ORDER
;
3320 alcSetError(device
, ALC_INVALID_ENUM
);
3328 * Returns information about the device and the version of OpenAL
3330 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3332 VerifyDevice(&device
);
3333 if(size
<= 0 || values
== nullptr)
3334 alcSetError(device
, ALC_INVALID_VALUE
);
3336 GetIntegerv(device
, param
, size
, values
);
3337 if(device
) ALCdevice_DecRef(device
);
3340 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3342 VerifyDevice(&device
);
3343 if(size
<= 0 || values
== nullptr)
3344 alcSetError(device
, ALC_INVALID_VALUE
);
3345 else if(!device
|| device
->Type
== Capture
)
3347 std::vector
<ALCint
> ivals(size
);
3348 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3349 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3351 else /* render device */
3355 case ALC_ATTRIBUTES_SIZE
:
3356 *values
= NumAttrsForDevice(device
)+4;
3359 case ALC_ALL_ATTRIBUTES
:
3360 if(size
< NumAttrsForDevice(device
)+4)
3361 alcSetError(device
, ALC_INVALID_VALUE
);
3365 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3366 values
[i
++] = ALC_FREQUENCY
;
3367 values
[i
++] = device
->Frequency
;
3369 if(device
->Type
!= Loopback
)
3371 values
[i
++] = ALC_REFRESH
;
3372 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3374 values
[i
++] = ALC_SYNC
;
3375 values
[i
++] = ALC_FALSE
;
3379 if(device
->FmtChans
== DevFmtAmbi3D
)
3381 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3382 values
[i
++] = static_cast<ALCint64SOFT
>(device
->mAmbiLayout
);
3384 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3385 values
[i
++] = static_cast<ALCint64SOFT
>(device
->mAmbiScale
);
3387 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3388 values
[i
++] = device
->mAmbiOrder
;
3391 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3392 values
[i
++] = device
->FmtChans
;
3394 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3395 values
[i
++] = device
->FmtType
;
3398 values
[i
++] = ALC_MONO_SOURCES
;
3399 values
[i
++] = device
->NumMonoSources
;
3401 values
[i
++] = ALC_STEREO_SOURCES
;
3402 values
[i
++] = device
->NumStereoSources
;
3404 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3405 values
[i
++] = device
->NumAuxSends
;
3407 values
[i
++] = ALC_HRTF_SOFT
;
3408 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3410 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3411 values
[i
++] = device
->HrtfStatus
;
3413 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3414 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3416 ClockLatency clock
{GetClockLatency(device
)};
3417 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3418 values
[i
++] = clock
.ClockTime
;
3420 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3421 values
[i
++] = clock
.Latency
;
3427 case ALC_DEVICE_CLOCK_SOFT
:
3428 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3433 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3435 basecount
= device
->ClockBase
;
3436 samplecount
= device
->SamplesDone
;
3437 } while(refcount
!= ReadRef(&device
->MixCount
));
3438 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3442 case ALC_DEVICE_LATENCY_SOFT
:
3443 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3444 ClockLatency clock
{GetClockLatency(device
)};
3445 *values
= clock
.Latency
;
3449 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3451 alcSetError(device
, ALC_INVALID_VALUE
);
3454 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3455 ClockLatency clock
{GetClockLatency(device
)};
3456 values
[0] = clock
.ClockTime
;
3457 values
[1] = clock
.Latency
;
3462 std::vector
<ALCint
> ivals(size
);
3463 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3464 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3469 ALCdevice_DecRef(device
);
3473 /* alcIsExtensionPresent
3475 * Determines if there is support for a particular extension
3477 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3479 ALCboolean bResult
= ALC_FALSE
;
3481 VerifyDevice(&device
);
3484 alcSetError(device
, ALC_INVALID_VALUE
);
3487 size_t len
= strlen(extName
);
3488 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3491 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3492 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3497 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3501 } while(isspace(*ptr
));
3506 ALCdevice_DecRef(device
);
3511 /* alcGetProcAddress
3513 * Retrieves the function address for a particular extension function
3515 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3517 ALCvoid
*ptr
= nullptr;
3521 VerifyDevice(&device
);
3522 alcSetError(device
, ALC_INVALID_VALUE
);
3523 if(device
) ALCdevice_DecRef(device
);
3528 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3530 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3532 ptr
= alcFunctions
[i
].address
;
3544 * Get the value for a particular ALC enumeration name
3546 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3552 VerifyDevice(&device
);
3553 alcSetError(device
, ALC_INVALID_VALUE
);
3554 if(device
) ALCdevice_DecRef(device
);
3559 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3561 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3563 val
= alcEnumerations
[i
].value
;
3575 * Create and attach a context to the given device.
3577 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3579 ALCcontext
*ALContext
;
3583 /* Explicitly hold the list lock while taking the BackendLock in case the
3584 * device is asynchronously destropyed, to ensure this new context is
3585 * properly cleaned up after being made.
3587 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3588 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3589 !device
->Connected
.load(std::memory_order_relaxed
))
3592 alcSetError(device
, ALC_INVALID_DEVICE
);
3593 if(device
) ALCdevice_DecRef(device
);
3596 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
3599 device
->LastError
.store(ALC_NO_ERROR
);
3601 ALContext
= new ALCcontext
{device
};
3602 ALCdevice_IncRef(ALContext
->Device
);
3604 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3609 ALContext
= nullptr;
3611 alcSetError(device
, err
);
3612 if(err
== ALC_INVALID_DEVICE
)
3614 V0(device
->Backend
,lock
)();
3615 aluHandleDisconnect(device
, "Device update failure");
3616 V0(device
->Backend
,unlock
)();
3618 ALCdevice_DecRef(device
);
3621 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3623 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3625 ALContext
->DefaultSlot
.reset(new ALeffectslot
{});
3626 if(InitEffectSlot(ALContext
->DefaultSlot
.get()) == AL_NO_ERROR
)
3627 aluInitEffectPanning(ALContext
->DefaultSlot
.get());
3630 ALContext
->DefaultSlot
= nullptr;
3631 ERR("Failed to initialize the default effect slot\n");
3635 InitContext(ALContext
);
3637 if(ConfigValueFloat(device
->DeviceName
.c_str(), nullptr, "volume-adjust", &valf
))
3639 if(!std::isfinite(valf
))
3640 ERR("volume-adjust must be finite: %f\n", valf
);
3643 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3645 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3646 ALContext
->GainBoost
= std::pow(10.0f
, db
/20.0f
);
3647 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3650 UpdateListenerProps(ALContext
);
3653 ALCcontext
*head
= device
->ContextList
.load();
3655 ALContext
->next
.store(head
, std::memory_order_relaxed
);
3656 } while(!device
->ContextList
.compare_exchange_weak(head
, ALContext
));
3660 if(ALContext
->DefaultSlot
)
3662 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3663 UpdateEffectSlotProps(ALContext
->DefaultSlot
.get(), ALContext
);
3665 ERR("Failed to initialize the default effect\n");
3668 ALCdevice_DecRef(device
);
3670 TRACE("Created context %p\n", ALContext
);
3674 /* alcDestroyContext
3676 * Remove a context from its device
3678 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3680 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3681 ContextRef ctx
{VerifyContext(context
)};
3685 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3689 ALCdevice
* Device
{ctx
->Device
};
3692 std::lock_guard
<almtx_t
> _
{Device
->BackendLock
};
3693 if(!ReleaseContext(ctx
.get(), Device
))
3695 V0(Device
->Backend
,stop
)();
3696 Device
->Flags
&= ~DEVICE_RUNNING
;
3703 /* alcGetCurrentContext
3705 * Returns the currently active context on the calling thread
3707 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3709 ALCcontext
*Context
{LocalContext
.get()};
3710 if(!Context
) Context
= GlobalContext
.load();
3714 /* alcGetThreadContext
3716 * Returns the currently active thread-local context
3718 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3720 return LocalContext
.get();
3724 /* alcMakeContextCurrent
3726 * Makes the given context the active process-wide context, and removes the
3727 * thread-local context for the calling thread.
3729 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3731 /* context must be valid or nullptr */
3735 ctx
= VerifyContext(context
);
3738 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3742 /* Release this reference (if any) to store it in the GlobalContext
3743 * pointer. Take ownership of the reference (if any) that was previously
3746 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3748 /* Reset (decrement) the previous global reference by replacing it with the
3749 * thread-local context. Take ownership of the thread-local context
3750 * reference (if any), clearing the storage to null.
3752 ctx
= ContextRef
{LocalContext
.get()};
3753 if(ctx
) LocalContext
.set(nullptr);
3754 /* Reset (decrement) the previous thread-local reference. */
3759 /* alcSetThreadContext
3761 * Makes the given context the active context for the current thread
3763 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3765 /* context must be valid or nullptr */
3769 ctx
= VerifyContext(context
);
3772 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3776 /* context's reference count is already incremented */
3777 ContextRef old
{LocalContext
.get()};
3778 LocalContext
.set(ctx
.release());
3784 /* alcGetContextsDevice
3786 * Returns the device that a particular context is attached to
3788 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3790 ContextRef ctx
{VerifyContext(Context
)};
3793 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3802 * Opens the named device.
3804 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3808 if(!PlaybackBackend
.name
)
3810 alcSetError(nullptr, ALC_INVALID_VALUE
);
3814 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3816 /* Some old Windows apps hardcode these expecting OpenAL to use a
3817 * specific audio API, even when they're not enumerated. Creative's
3818 * router effectively ignores them too.
3820 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3821 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3824 deviceName
= nullptr;
3826 auto device
= new ALCdevice
{Playback
};
3829 device
->FmtChans
= DevFmtChannelsDefault
;
3830 device
->FmtType
= DevFmtTypeDefault
;
3831 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3832 device
->LimiterState
= ALC_TRUE
;
3833 device
->NumUpdates
= 3;
3834 device
->UpdateSize
= 1024;
3836 device
->SourcesMax
= 256;
3837 device
->AuxiliaryEffectSlotMax
= 64;
3838 device
->NumAuxSends
= DEFAULT_SENDS
;
3840 const ALCchar
*fmt
{};
3841 if(ConfigValueStr(deviceName
, nullptr, "channels", &fmt
))
3843 static constexpr struct ChannelMap
{
3844 const char name
[16];
3845 enum DevFmtChannels chans
;
3848 { "mono", DevFmtMono
, 0 },
3849 { "stereo", DevFmtStereo
, 0 },
3850 { "quad", DevFmtQuad
, 0 },
3851 { "surround51", DevFmtX51
, 0 },
3852 { "surround61", DevFmtX61
, 0 },
3853 { "surround71", DevFmtX71
, 0 },
3854 { "surround51rear", DevFmtX51Rear
, 0 },
3855 { "ambi1", DevFmtAmbi3D
, 1 },
3856 { "ambi2", DevFmtAmbi3D
, 2 },
3857 { "ambi3", DevFmtAmbi3D
, 3 },
3860 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3861 [fmt
](const ChannelMap
&entry
) -> bool
3862 { return strcasecmp(entry
.name
, fmt
) == 0; }
3864 if(iter
== std::end(chanlist
))
3865 ERR("Unsupported channels: %s\n", fmt
);
3868 device
->FmtChans
= iter
->chans
;
3869 device
->mAmbiOrder
= iter
->order
;
3870 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3873 if(ConfigValueStr(deviceName
, nullptr, "sample-type", &fmt
))
3875 static constexpr struct TypeMap
{
3876 const char name
[16];
3877 enum DevFmtType type
;
3879 { "int8", DevFmtByte
},
3880 { "uint8", DevFmtUByte
},
3881 { "int16", DevFmtShort
},
3882 { "uint16", DevFmtUShort
},
3883 { "int32", DevFmtInt
},
3884 { "uint32", DevFmtUInt
},
3885 { "float32", DevFmtFloat
},
3888 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3889 [fmt
](const TypeMap
&entry
) -> bool
3890 { return strcasecmp(entry
.name
, fmt
) == 0; }
3892 if(iter
== std::end(typelist
))
3893 ERR("Unsupported sample-type: %s\n", fmt
);
3896 device
->FmtType
= iter
->type
;
3897 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3901 if(ConfigValueUInt(deviceName
, nullptr, "frequency", &device
->Frequency
))
3903 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3904 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3905 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3906 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3909 ConfigValueUInt(deviceName
, nullptr, "periods", &device
->NumUpdates
);
3910 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3912 ConfigValueUInt(deviceName
, nullptr, "period_size", &device
->UpdateSize
);
3913 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3914 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3915 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3917 ConfigValueUInt(deviceName
, nullptr, "sources", &device
->SourcesMax
);
3918 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3920 ConfigValueUInt(deviceName
, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
3921 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3922 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
3924 if(ConfigValueInt(deviceName
, nullptr, "sends", &device
->NumAuxSends
))
3925 device
->NumAuxSends
= clampi(
3926 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3929 device
->NumStereoSources
= 1;
3930 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3932 device
->Backend
= PlaybackBackend
.getFactory().createBackend(device
, ALCbackend_Playback
);
3933 if(!device
->Backend
)
3936 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
3940 // Find a playback device to open
3941 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
3942 if(err
!= ALC_NO_ERROR
)
3945 alcSetError(nullptr, err
);
3949 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "ambi-format", &fmt
))
3951 if(strcasecmp(fmt
, "fuma") == 0)
3953 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3954 device
->mAmbiScale
= AmbiNorm::FuMa
;
3956 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3958 device
->mAmbiLayout
= AmbiLayout::ACN
;
3959 device
->mAmbiScale
= AmbiNorm::SN3D
;
3961 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3963 device
->mAmbiLayout
= AmbiLayout::ACN
;
3964 device
->mAmbiScale
= AmbiNorm::N3D
;
3967 ERR("Unsupported ambi-format: %s\n", fmt
);
3971 ALCdevice
*head
{DeviceList
.load()};
3973 device
->next
.store(head
, std::memory_order_relaxed
);
3974 } while(!DeviceList
.compare_exchange_weak(head
, device
));
3977 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
3983 * Closes the given device.
3985 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3987 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3988 ALCdevice
*iter
{DeviceList
.load()};
3992 iter
= iter
->next
.load(std::memory_order_relaxed
);
3993 } while(iter
!= nullptr);
3994 if(!iter
|| iter
->Type
== Capture
)
3996 alcSetError(iter
, ALC_INVALID_DEVICE
);
3999 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
4001 ALCdevice
*origdev
{device
};
4002 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4003 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4009 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4013 ALCcontext
*ctx
{device
->ContextList
.load()};
4014 while(ctx
!= nullptr)
4016 ALCcontext
*next
= ctx
->next
.load(std::memory_order_relaxed
);
4017 WARN("Releasing context %p\n", ctx
);
4018 ReleaseContext(ctx
, device
);
4021 if((device
->Flags
&DEVICE_RUNNING
))
4022 V0(device
->Backend
,stop
)();
4023 device
->Flags
&= ~DEVICE_RUNNING
;
4026 ALCdevice_DecRef(device
);
4032 /************************************************
4033 * ALC capture functions
4034 ************************************************/
4035 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4039 if(!CaptureBackend
.name
)
4041 alcSetError(nullptr, ALC_INVALID_VALUE
);
4047 alcSetError(nullptr, ALC_INVALID_VALUE
);
4051 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4052 deviceName
= nullptr;
4054 auto device
= new ALCdevice
{Capture
};
4056 device
->Frequency
= frequency
;
4057 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4059 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4062 alcSetError(nullptr, ALC_INVALID_ENUM
);
4065 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4067 device
->UpdateSize
= samples
;
4068 device
->NumUpdates
= 1;
4070 device
->Backend
= CaptureBackend
.getFactory().createBackend(device
, ALCbackend_Capture
);
4071 if(!device
->Backend
)
4074 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4078 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4079 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4080 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4082 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
4083 if(err
!= ALC_NO_ERROR
)
4086 alcSetError(nullptr, err
);
4091 ALCdevice
*head
{DeviceList
.load()};
4093 device
->next
.store(head
, std::memory_order_relaxed
);
4094 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4097 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
4101 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4103 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4105 ALCdevice
*iter
{DeviceList
.load()};
4109 iter
= iter
->next
.load(std::memory_order_relaxed
);
4110 } while(iter
!= nullptr);
4111 if(!iter
|| iter
->Type
!= Capture
)
4113 alcSetError(iter
, ALC_INVALID_DEVICE
);
4117 ALCdevice
*origdev
{device
};
4118 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4119 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4125 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4129 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4130 if((device
->Flags
&DEVICE_RUNNING
))
4131 V0(device
->Backend
,stop
)();
4132 device
->Flags
&= ~DEVICE_RUNNING
;
4135 ALCdevice_DecRef(device
);
4140 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4142 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4143 alcSetError(device
, ALC_INVALID_DEVICE
);
4146 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4147 if(!device
->Connected
.load(std::memory_order_acquire
))
4148 alcSetError(device
, ALC_INVALID_DEVICE
);
4149 else if(!(device
->Flags
&DEVICE_RUNNING
))
4151 if(V0(device
->Backend
,start
)())
4152 device
->Flags
|= DEVICE_RUNNING
;
4155 aluHandleDisconnect(device
, "Device start failure");
4156 alcSetError(device
, ALC_INVALID_DEVICE
);
4161 if(device
) ALCdevice_DecRef(device
);
4164 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4166 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4167 alcSetError(device
, ALC_INVALID_DEVICE
);
4170 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4171 if((device
->Flags
&DEVICE_RUNNING
))
4172 V0(device
->Backend
,stop
)();
4173 device
->Flags
&= ~DEVICE_RUNNING
;
4176 if(device
) ALCdevice_DecRef(device
);
4179 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4181 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4182 alcSetError(device
, ALC_INVALID_DEVICE
);
4185 ALCenum err
= ALC_INVALID_VALUE
;
4186 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4187 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4188 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4190 if(err
!= ALC_NO_ERROR
)
4191 alcSetError(device
, err
);
4193 if(device
) ALCdevice_DecRef(device
);
4197 /************************************************
4198 * ALC loopback functions
4199 ************************************************/
4201 /* alcLoopbackOpenDeviceSOFT
4203 * Open a loopback device, for manual rendering.
4205 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4209 /* Make sure the device name, if specified, is us. */
4210 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4212 alcSetError(nullptr, ALC_INVALID_VALUE
);
4216 auto device
= new ALCdevice
{Loopback
};
4218 device
->SourcesMax
= 256;
4219 device
->AuxiliaryEffectSlotMax
= 64;
4220 device
->NumAuxSends
= DEFAULT_SENDS
;
4223 device
->NumUpdates
= 0;
4224 device
->UpdateSize
= 0;
4226 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4227 device
->FmtChans
= DevFmtChannelsDefault
;
4228 device
->FmtType
= DevFmtTypeDefault
;
4230 ConfigValueUInt(nullptr, nullptr, "sources", &device
->SourcesMax
);
4231 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4233 ConfigValueUInt(nullptr, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4234 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4235 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4237 if(ConfigValueInt(nullptr, nullptr, "sends", &device
->NumAuxSends
))
4238 device
->NumAuxSends
= clampi(
4239 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4242 device
->NumStereoSources
= 1;
4243 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4245 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(
4246 device
, ALCbackend_Loopback
);
4247 if(!device
->Backend
)
4250 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4254 // Open the "backend"
4255 V(device
->Backend
,open
)("Loopback");
4258 ALCdevice
*head
{DeviceList
.load()};
4260 device
->next
.store(head
, std::memory_order_relaxed
);
4261 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4264 TRACE("Created device %p\n", device
);
4268 /* alcIsRenderFormatSupportedSOFT
4270 * Determines if the loopback device supports the given format for rendering.
4272 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4274 ALCboolean ret
{ALC_FALSE
};
4276 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4277 alcSetError(device
, ALC_INVALID_DEVICE
);
4279 alcSetError(device
, ALC_INVALID_VALUE
);
4282 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4285 if(device
) ALCdevice_DecRef(device
);
4290 /* alcRenderSamplesSOFT
4292 * Renders some samples into a buffer, using the format last set by the
4293 * attributes given to alcCreateContext.
4295 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4297 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4298 alcSetError(device
, ALC_INVALID_DEVICE
);
4299 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4300 alcSetError(device
, ALC_INVALID_VALUE
);
4303 V0(device
->Backend
,lock
)();
4304 aluMixData(device
, buffer
, samples
);
4305 V0(device
->Backend
,unlock
)();
4307 if(device
) ALCdevice_DecRef(device
);
4311 /************************************************
4312 * ALC DSP pause/resume functions
4313 ************************************************/
4315 /* alcDevicePauseSOFT
4317 * Pause the DSP to stop audio processing.
4319 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4321 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4322 alcSetError(device
, ALC_INVALID_DEVICE
);
4325 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4326 if((device
->Flags
&DEVICE_RUNNING
))
4327 V0(device
->Backend
,stop
)();
4328 device
->Flags
&= ~DEVICE_RUNNING
;
4329 device
->Flags
|= DEVICE_PAUSED
;
4331 if(device
) ALCdevice_DecRef(device
);
4334 /* alcDeviceResumeSOFT
4336 * Resume the DSP to restart audio processing.
4338 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4340 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4341 alcSetError(device
, ALC_INVALID_DEVICE
);
4344 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4345 if((device
->Flags
&DEVICE_PAUSED
))
4347 device
->Flags
&= ~DEVICE_PAUSED
;
4348 if(device
->ContextList
.load() != nullptr)
4350 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4351 device
->Flags
|= DEVICE_RUNNING
;
4354 V0(device
->Backend
,lock
)();
4355 aluHandleDisconnect(device
, "Device start failure");
4356 V0(device
->Backend
,unlock
)();
4357 alcSetError(device
, ALC_INVALID_DEVICE
);
4362 if(device
) ALCdevice_DecRef(device
);
4366 /************************************************
4367 * ALC HRTF functions
4368 ************************************************/
4370 /* alcGetStringiSOFT
4372 * Gets a string parameter at the given index.
4374 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4376 const ALCchar
*str
{nullptr};
4378 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4379 alcSetError(device
, ALC_INVALID_DEVICE
);
4380 else switch(paramName
)
4382 case ALC_HRTF_SPECIFIER_SOFT
:
4383 if(index
>= 0 && (size_t)index
< device
->HrtfList
.size())
4384 str
= device
->HrtfList
[index
].name
.c_str();
4386 alcSetError(device
, ALC_INVALID_VALUE
);
4390 alcSetError(device
, ALC_INVALID_ENUM
);
4393 if(device
) ALCdevice_DecRef(device
);
4398 /* alcResetDeviceSOFT
4400 * Resets the given device output, using the specified attribute list.
4402 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4404 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4405 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4406 !device
->Connected
.load(std::memory_order_relaxed
))
4409 alcSetError(device
, ALC_INVALID_DEVICE
);
4410 if(device
) ALCdevice_DecRef(device
);
4413 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
4416 ALCenum err
{UpdateDeviceParams(device
, attribs
)};
4419 if(err
!= ALC_NO_ERROR
)
4421 alcSetError(device
, err
);
4422 if(err
== ALC_INVALID_DEVICE
)
4424 V0(device
->Backend
,lock
)();
4425 aluHandleDisconnect(device
, "Device start failure");
4426 V0(device
->Backend
,unlock
)();
4428 ALCdevice_DecRef(device
);
4431 ALCdevice_DecRef(device
);