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"
53 #include "ringbuffer.h"
55 #include "fpu_modes.h"
61 #include "backends/base.h"
62 #include "backends/null.h"
63 #include "backends/loopback.h"
65 #include "backends/jack.h"
67 #ifdef HAVE_PULSEAUDIO
68 #include "backends/pulseaudio.h"
71 #include "backends/alsa.h"
74 #include "backends/wasapi.h"
77 #include "backends/coreaudio.h"
80 #include "backends/opensl.h"
83 #include "backends/solaris.h"
86 #include "backends/sndio.h"
89 #include "backends/oss.h"
92 #include "backends/qsa.h"
95 #include "backends/dsound.h"
98 #include "backends/winmm.h"
100 #ifdef HAVE_PORTAUDIO
101 #include "backends/portaudio.h"
104 #include "backends/sdl2.h"
107 #include "backends/wave.h"
113 /************************************************
115 ************************************************/
118 BackendFactory
& (*getFactory
)(void);
121 struct BackendInfo BackendList
[] = {
123 { "jack", JackBackendFactory::getFactory
},
125 #ifdef HAVE_PULSEAUDIO
126 { "pulse", PulseBackendFactory::getFactory
},
129 { "alsa", AlsaBackendFactory::getFactory
},
132 { "wasapi", WasapiBackendFactory::getFactory
},
134 #ifdef HAVE_COREAUDIO
135 { "core", CoreAudioBackendFactory::getFactory
},
138 { "opensl", OSLBackendFactory::getFactory
},
141 { "solaris", SolarisBackendFactory::getFactory
},
144 { "sndio", SndIOBackendFactory::getFactory
},
147 { "oss", OSSBackendFactory::getFactory
},
150 { "qsa", QSABackendFactory::getFactory
},
153 { "dsound", DSoundBackendFactory::getFactory
},
156 { "winmm", WinMMBackendFactory::getFactory
},
158 #ifdef HAVE_PORTAUDIO
159 { "port", PortBackendFactory::getFactory
},
162 { "sdl2", SDL2BackendFactory::getFactory
},
165 { "null", NullBackendFactory::getFactory
},
167 { "wave", WaveBackendFactory::getFactory
},
170 ALsizei BackendListSize
= COUNTOF(BackendList
);
172 struct BackendInfo PlaybackBackend
;
173 struct BackendInfo CaptureBackend
;
176 /************************************************
177 * Functions, enums, and errors
178 ************************************************/
179 #define DECL(x) { #x, (ALCvoid*)(x) }
181 const ALCchar
*funcName
;
184 DECL(alcCreateContext
),
185 DECL(alcMakeContextCurrent
),
186 DECL(alcProcessContext
),
187 DECL(alcSuspendContext
),
188 DECL(alcDestroyContext
),
189 DECL(alcGetCurrentContext
),
190 DECL(alcGetContextsDevice
),
192 DECL(alcCloseDevice
),
194 DECL(alcIsExtensionPresent
),
195 DECL(alcGetProcAddress
),
196 DECL(alcGetEnumValue
),
198 DECL(alcGetIntegerv
),
199 DECL(alcCaptureOpenDevice
),
200 DECL(alcCaptureCloseDevice
),
201 DECL(alcCaptureStart
),
202 DECL(alcCaptureStop
),
203 DECL(alcCaptureSamples
),
205 DECL(alcSetThreadContext
),
206 DECL(alcGetThreadContext
),
208 DECL(alcLoopbackOpenDeviceSOFT
),
209 DECL(alcIsRenderFormatSupportedSOFT
),
210 DECL(alcRenderSamplesSOFT
),
212 DECL(alcDevicePauseSOFT
),
213 DECL(alcDeviceResumeSOFT
),
215 DECL(alcGetStringiSOFT
),
216 DECL(alcResetDeviceSOFT
),
218 DECL(alcGetInteger64vSOFT
),
233 DECL(alIsExtensionPresent
),
234 DECL(alGetProcAddress
),
235 DECL(alGetEnumValue
),
242 DECL(alGetListenerf
),
243 DECL(alGetListener3f
),
244 DECL(alGetListenerfv
),
245 DECL(alGetListeneri
),
246 DECL(alGetListener3i
),
247 DECL(alGetListeneriv
),
249 DECL(alDeleteSources
),
265 DECL(alSourceRewindv
),
266 DECL(alSourcePausev
),
269 DECL(alSourceRewind
),
271 DECL(alSourceQueueBuffers
),
272 DECL(alSourceUnqueueBuffers
),
274 DECL(alDeleteBuffers
),
289 DECL(alDopplerFactor
),
290 DECL(alDopplerVelocity
),
291 DECL(alSpeedOfSound
),
292 DECL(alDistanceModel
),
295 DECL(alDeleteFilters
),
306 DECL(alDeleteEffects
),
316 DECL(alGenAuxiliaryEffectSlots
),
317 DECL(alDeleteAuxiliaryEffectSlots
),
318 DECL(alIsAuxiliaryEffectSlot
),
319 DECL(alAuxiliaryEffectSloti
),
320 DECL(alAuxiliaryEffectSlotiv
),
321 DECL(alAuxiliaryEffectSlotf
),
322 DECL(alAuxiliaryEffectSlotfv
),
323 DECL(alGetAuxiliaryEffectSloti
),
324 DECL(alGetAuxiliaryEffectSlotiv
),
325 DECL(alGetAuxiliaryEffectSlotf
),
326 DECL(alGetAuxiliaryEffectSlotfv
),
328 DECL(alDeferUpdatesSOFT
),
329 DECL(alProcessUpdatesSOFT
),
332 DECL(alSource3dSOFT
),
333 DECL(alSourcedvSOFT
),
334 DECL(alGetSourcedSOFT
),
335 DECL(alGetSource3dSOFT
),
336 DECL(alGetSourcedvSOFT
),
337 DECL(alSourcei64SOFT
),
338 DECL(alSource3i64SOFT
),
339 DECL(alSourcei64vSOFT
),
340 DECL(alGetSourcei64SOFT
),
341 DECL(alGetSource3i64SOFT
),
342 DECL(alGetSourcei64vSOFT
),
344 DECL(alGetStringiSOFT
),
346 DECL(alBufferStorageSOFT
),
347 DECL(alMapBufferSOFT
),
348 DECL(alUnmapBufferSOFT
),
349 DECL(alFlushMappedBufferSOFT
),
351 DECL(alEventControlSOFT
),
352 DECL(alEventCallbackSOFT
),
353 DECL(alGetPointerSOFT
),
354 DECL(alGetPointervSOFT
),
358 #define DECL(x) { #x, (x) }
360 const ALCchar
*enumName
;
362 } alcEnumerations
[] = {
367 DECL(ALC_MAJOR_VERSION
),
368 DECL(ALC_MINOR_VERSION
),
369 DECL(ALC_ATTRIBUTES_SIZE
),
370 DECL(ALC_ALL_ATTRIBUTES
),
371 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
372 DECL(ALC_DEVICE_SPECIFIER
),
373 DECL(ALC_ALL_DEVICES_SPECIFIER
),
374 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
375 DECL(ALC_EXTENSIONS
),
379 DECL(ALC_MONO_SOURCES
),
380 DECL(ALC_STEREO_SOURCES
),
381 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
382 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
383 DECL(ALC_CAPTURE_SAMPLES
),
386 DECL(ALC_EFX_MAJOR_VERSION
),
387 DECL(ALC_EFX_MINOR_VERSION
),
388 DECL(ALC_MAX_AUXILIARY_SENDS
),
390 DECL(ALC_FORMAT_CHANNELS_SOFT
),
391 DECL(ALC_FORMAT_TYPE_SOFT
),
394 DECL(ALC_STEREO_SOFT
),
396 DECL(ALC_5POINT1_SOFT
),
397 DECL(ALC_6POINT1_SOFT
),
398 DECL(ALC_7POINT1_SOFT
),
399 DECL(ALC_BFORMAT3D_SOFT
),
402 DECL(ALC_UNSIGNED_BYTE_SOFT
),
403 DECL(ALC_SHORT_SOFT
),
404 DECL(ALC_UNSIGNED_SHORT_SOFT
),
406 DECL(ALC_UNSIGNED_INT_SOFT
),
407 DECL(ALC_FLOAT_SOFT
),
410 DECL(ALC_DONT_CARE_SOFT
),
411 DECL(ALC_HRTF_STATUS_SOFT
),
412 DECL(ALC_HRTF_DISABLED_SOFT
),
413 DECL(ALC_HRTF_ENABLED_SOFT
),
414 DECL(ALC_HRTF_DENIED_SOFT
),
415 DECL(ALC_HRTF_REQUIRED_SOFT
),
416 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
417 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
418 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
419 DECL(ALC_HRTF_SPECIFIER_SOFT
),
420 DECL(ALC_HRTF_ID_SOFT
),
422 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
423 DECL(ALC_AMBISONIC_SCALING_SOFT
),
424 DECL(ALC_AMBISONIC_ORDER_SOFT
),
430 DECL(ALC_OUTPUT_LIMITER_SOFT
),
433 DECL(ALC_INVALID_DEVICE
),
434 DECL(ALC_INVALID_CONTEXT
),
435 DECL(ALC_INVALID_ENUM
),
436 DECL(ALC_INVALID_VALUE
),
437 DECL(ALC_OUT_OF_MEMORY
),
445 DECL(AL_SOURCE_RELATIVE
),
446 DECL(AL_CONE_INNER_ANGLE
),
447 DECL(AL_CONE_OUTER_ANGLE
),
457 DECL(AL_ORIENTATION
),
458 DECL(AL_REFERENCE_DISTANCE
),
459 DECL(AL_ROLLOFF_FACTOR
),
460 DECL(AL_CONE_OUTER_GAIN
),
461 DECL(AL_MAX_DISTANCE
),
463 DECL(AL_SAMPLE_OFFSET
),
464 DECL(AL_BYTE_OFFSET
),
465 DECL(AL_SOURCE_TYPE
),
468 DECL(AL_UNDETERMINED
),
469 DECL(AL_METERS_PER_UNIT
),
470 DECL(AL_LOOP_POINTS_SOFT
),
471 DECL(AL_DIRECT_CHANNELS_SOFT
),
473 DECL(AL_DIRECT_FILTER
),
474 DECL(AL_AUXILIARY_SEND_FILTER
),
475 DECL(AL_AIR_ABSORPTION_FACTOR
),
476 DECL(AL_ROOM_ROLLOFF_FACTOR
),
477 DECL(AL_CONE_OUTER_GAINHF
),
478 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
479 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
480 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
482 DECL(AL_SOURCE_STATE
),
488 DECL(AL_BUFFERS_QUEUED
),
489 DECL(AL_BUFFERS_PROCESSED
),
491 DECL(AL_FORMAT_MONO8
),
492 DECL(AL_FORMAT_MONO16
),
493 DECL(AL_FORMAT_MONO_FLOAT32
),
494 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
495 DECL(AL_FORMAT_STEREO8
),
496 DECL(AL_FORMAT_STEREO16
),
497 DECL(AL_FORMAT_STEREO_FLOAT32
),
498 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
499 DECL(AL_FORMAT_MONO_IMA4
),
500 DECL(AL_FORMAT_STEREO_IMA4
),
501 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
502 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
503 DECL(AL_FORMAT_QUAD8_LOKI
),
504 DECL(AL_FORMAT_QUAD16_LOKI
),
505 DECL(AL_FORMAT_QUAD8
),
506 DECL(AL_FORMAT_QUAD16
),
507 DECL(AL_FORMAT_QUAD32
),
508 DECL(AL_FORMAT_51CHN8
),
509 DECL(AL_FORMAT_51CHN16
),
510 DECL(AL_FORMAT_51CHN32
),
511 DECL(AL_FORMAT_61CHN8
),
512 DECL(AL_FORMAT_61CHN16
),
513 DECL(AL_FORMAT_61CHN32
),
514 DECL(AL_FORMAT_71CHN8
),
515 DECL(AL_FORMAT_71CHN16
),
516 DECL(AL_FORMAT_71CHN32
),
517 DECL(AL_FORMAT_REAR8
),
518 DECL(AL_FORMAT_REAR16
),
519 DECL(AL_FORMAT_REAR32
),
520 DECL(AL_FORMAT_MONO_MULAW
),
521 DECL(AL_FORMAT_MONO_MULAW_EXT
),
522 DECL(AL_FORMAT_STEREO_MULAW
),
523 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
524 DECL(AL_FORMAT_QUAD_MULAW
),
525 DECL(AL_FORMAT_51CHN_MULAW
),
526 DECL(AL_FORMAT_61CHN_MULAW
),
527 DECL(AL_FORMAT_71CHN_MULAW
),
528 DECL(AL_FORMAT_REAR_MULAW
),
529 DECL(AL_FORMAT_MONO_ALAW_EXT
),
530 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
532 DECL(AL_FORMAT_BFORMAT2D_8
),
533 DECL(AL_FORMAT_BFORMAT2D_16
),
534 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
535 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
536 DECL(AL_FORMAT_BFORMAT3D_8
),
537 DECL(AL_FORMAT_BFORMAT3D_16
),
538 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
539 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
545 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
546 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
548 DECL(AL_SOURCE_RADIUS
),
550 DECL(AL_STEREO_ANGLES
),
557 DECL(AL_INVALID_NAME
),
558 DECL(AL_INVALID_ENUM
),
559 DECL(AL_INVALID_VALUE
),
560 DECL(AL_INVALID_OPERATION
),
561 DECL(AL_OUT_OF_MEMORY
),
568 DECL(AL_DOPPLER_FACTOR
),
569 DECL(AL_DOPPLER_VELOCITY
),
570 DECL(AL_DISTANCE_MODEL
),
571 DECL(AL_SPEED_OF_SOUND
),
572 DECL(AL_SOURCE_DISTANCE_MODEL
),
573 DECL(AL_DEFERRED_UPDATES_SOFT
),
574 DECL(AL_GAIN_LIMIT_SOFT
),
576 DECL(AL_INVERSE_DISTANCE
),
577 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
578 DECL(AL_LINEAR_DISTANCE
),
579 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
580 DECL(AL_EXPONENT_DISTANCE
),
581 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
583 DECL(AL_FILTER_TYPE
),
584 DECL(AL_FILTER_NULL
),
585 DECL(AL_FILTER_LOWPASS
),
586 DECL(AL_FILTER_HIGHPASS
),
587 DECL(AL_FILTER_BANDPASS
),
589 DECL(AL_LOWPASS_GAIN
),
590 DECL(AL_LOWPASS_GAINHF
),
592 DECL(AL_HIGHPASS_GAIN
),
593 DECL(AL_HIGHPASS_GAINLF
),
595 DECL(AL_BANDPASS_GAIN
),
596 DECL(AL_BANDPASS_GAINHF
),
597 DECL(AL_BANDPASS_GAINLF
),
599 DECL(AL_EFFECT_TYPE
),
600 DECL(AL_EFFECT_NULL
),
601 DECL(AL_EFFECT_REVERB
),
602 DECL(AL_EFFECT_EAXREVERB
),
603 DECL(AL_EFFECT_CHORUS
),
604 DECL(AL_EFFECT_DISTORTION
),
605 DECL(AL_EFFECT_ECHO
),
606 DECL(AL_EFFECT_FLANGER
),
607 DECL(AL_EFFECT_PITCH_SHIFTER
),
608 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
610 DECL(AL_EFFECT_VOCAL_MORPHER
),
612 DECL(AL_EFFECT_RING_MODULATOR
),
613 DECL(AL_EFFECT_AUTOWAH
),
614 DECL(AL_EFFECT_COMPRESSOR
),
615 DECL(AL_EFFECT_EQUALIZER
),
616 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
617 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
619 DECL(AL_EFFECTSLOT_EFFECT
),
620 DECL(AL_EFFECTSLOT_GAIN
),
621 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
622 DECL(AL_EFFECTSLOT_NULL
),
624 DECL(AL_EAXREVERB_DENSITY
),
625 DECL(AL_EAXREVERB_DIFFUSION
),
626 DECL(AL_EAXREVERB_GAIN
),
627 DECL(AL_EAXREVERB_GAINHF
),
628 DECL(AL_EAXREVERB_GAINLF
),
629 DECL(AL_EAXREVERB_DECAY_TIME
),
630 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
631 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
632 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
633 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
634 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
635 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
636 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
637 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
638 DECL(AL_EAXREVERB_ECHO_TIME
),
639 DECL(AL_EAXREVERB_ECHO_DEPTH
),
640 DECL(AL_EAXREVERB_MODULATION_TIME
),
641 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
642 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
643 DECL(AL_EAXREVERB_HFREFERENCE
),
644 DECL(AL_EAXREVERB_LFREFERENCE
),
645 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
646 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
648 DECL(AL_REVERB_DENSITY
),
649 DECL(AL_REVERB_DIFFUSION
),
650 DECL(AL_REVERB_GAIN
),
651 DECL(AL_REVERB_GAINHF
),
652 DECL(AL_REVERB_DECAY_TIME
),
653 DECL(AL_REVERB_DECAY_HFRATIO
),
654 DECL(AL_REVERB_REFLECTIONS_GAIN
),
655 DECL(AL_REVERB_REFLECTIONS_DELAY
),
656 DECL(AL_REVERB_LATE_REVERB_GAIN
),
657 DECL(AL_REVERB_LATE_REVERB_DELAY
),
658 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
659 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
660 DECL(AL_REVERB_DECAY_HFLIMIT
),
662 DECL(AL_CHORUS_WAVEFORM
),
663 DECL(AL_CHORUS_PHASE
),
664 DECL(AL_CHORUS_RATE
),
665 DECL(AL_CHORUS_DEPTH
),
666 DECL(AL_CHORUS_FEEDBACK
),
667 DECL(AL_CHORUS_DELAY
),
669 DECL(AL_DISTORTION_EDGE
),
670 DECL(AL_DISTORTION_GAIN
),
671 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
672 DECL(AL_DISTORTION_EQCENTER
),
673 DECL(AL_DISTORTION_EQBANDWIDTH
),
676 DECL(AL_ECHO_LRDELAY
),
677 DECL(AL_ECHO_DAMPING
),
678 DECL(AL_ECHO_FEEDBACK
),
679 DECL(AL_ECHO_SPREAD
),
681 DECL(AL_FLANGER_WAVEFORM
),
682 DECL(AL_FLANGER_PHASE
),
683 DECL(AL_FLANGER_RATE
),
684 DECL(AL_FLANGER_DEPTH
),
685 DECL(AL_FLANGER_FEEDBACK
),
686 DECL(AL_FLANGER_DELAY
),
688 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
689 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
690 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
692 DECL(AL_RING_MODULATOR_FREQUENCY
),
693 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
694 DECL(AL_RING_MODULATOR_WAVEFORM
),
696 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
697 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
699 DECL(AL_COMPRESSOR_ONOFF
),
701 DECL(AL_EQUALIZER_LOW_GAIN
),
702 DECL(AL_EQUALIZER_LOW_CUTOFF
),
703 DECL(AL_EQUALIZER_MID1_GAIN
),
704 DECL(AL_EQUALIZER_MID1_CENTER
),
705 DECL(AL_EQUALIZER_MID1_WIDTH
),
706 DECL(AL_EQUALIZER_MID2_GAIN
),
707 DECL(AL_EQUALIZER_MID2_CENTER
),
708 DECL(AL_EQUALIZER_MID2_WIDTH
),
709 DECL(AL_EQUALIZER_HIGH_GAIN
),
710 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
712 DECL(AL_DEDICATED_GAIN
),
714 DECL(AL_AUTOWAH_ATTACK_TIME
),
715 DECL(AL_AUTOWAH_RELEASE_TIME
),
716 DECL(AL_AUTOWAH_RESONANCE
),
717 DECL(AL_AUTOWAH_PEAK_GAIN
),
719 DECL(AL_NUM_RESAMPLERS_SOFT
),
720 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
721 DECL(AL_SOURCE_RESAMPLER_SOFT
),
722 DECL(AL_RESAMPLER_NAME_SOFT
),
724 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
727 DECL(AL_MAP_READ_BIT_SOFT
),
728 DECL(AL_MAP_WRITE_BIT_SOFT
),
729 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
730 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
732 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
733 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
734 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
735 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
736 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
737 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
738 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
742 constexpr ALCchar alcNoError
[] = "No Error";
743 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
744 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
745 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
746 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
747 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
750 /************************************************
752 ************************************************/
754 /* Enumerated device names */
755 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
757 std::string alcAllDevicesList
;
758 std::string alcCaptureDeviceList
;
760 /* Default is always the first in the list */
761 std::string alcDefaultAllDevicesSpecifier
;
762 std::string alcCaptureDefaultDeviceSpecifier
;
764 /* Default context extensions */
765 constexpr ALchar alExtList
[] =
769 "AL_EXT_EXPONENT_DISTANCE "
772 "AL_EXT_LINEAR_DISTANCE "
775 "AL_EXT_MULAW_BFORMAT "
776 "AL_EXT_MULAW_MCFORMATS "
778 "AL_EXT_source_distance_model "
779 "AL_EXT_SOURCE_RADIUS "
780 "AL_EXT_STEREO_ANGLES "
781 "AL_LOKI_quadriphonic "
782 "AL_SOFT_block_alignment "
783 "AL_SOFT_deferred_updates "
784 "AL_SOFT_direct_channels "
786 "AL_SOFTX_filter_gain_ex "
787 "AL_SOFT_gain_clamp_ex "
788 "AL_SOFT_loop_points "
789 "AL_SOFTX_map_buffer "
791 "AL_SOFT_source_latency "
792 "AL_SOFT_source_length "
793 "AL_SOFT_source_resampler "
794 "AL_SOFT_source_spatialize";
796 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
798 /* Thread-local current context */
799 std::atomic
<void(*)(ALCcontext
*)> ThreadCtxProc
{nullptr};
801 ALCcontext
*ctx
{nullptr};
806 auto destruct
= ThreadCtxProc
.load();
812 ALCcontext
*get() const noexcept
{ return ctx
; }
813 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
815 thread_local ThreadCtx LocalContext
;
816 /* Process-wide current context */
817 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
819 /* Flag to trap ALC device errors */
820 bool TrapALCError
{false};
822 /* One-time configuration init control */
823 std::once_flag alc_config_once
{};
825 /* Default effect that applies to sources that don't have an effect on send 0 */
826 ALeffect DefaultEffect
;
828 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
831 bool SuspendDefers
{true};
834 /************************************************
836 ************************************************/
837 constexpr ALCchar alcNoDeviceExtList
[] =
838 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
839 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
840 constexpr ALCchar alcExtensionList
[] =
841 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
842 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
843 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
844 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
845 constexpr ALCint alcMajorVersion
= 1;
846 constexpr ALCint alcMinorVersion
= 1;
848 constexpr ALCint alcEFXMajorVersion
= 1;
849 constexpr ALCint alcEFXMinorVersion
= 0;
852 /************************************************
854 ************************************************/
855 std::atomic
<ALCdevice
*> DeviceList
{nullptr};
857 std::recursive_mutex ListLock
;
861 /* Mixing thread piority level */
866 enum LogLevel LogLevel
= LogWarning
;
868 enum LogLevel LogLevel
= LogError
;
871 /************************************************
872 * Library initialization
873 ************************************************/
875 static void alc_init(void);
876 static void alc_deinit(void);
877 static void alc_deinit_safe(void);
879 #ifndef AL_LIBTYPE_STATIC
880 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
884 case DLL_PROCESS_ATTACH
:
885 /* Pin the DLL so we won't get unloaded until the process terminates */
886 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
887 (WCHAR
*)hModule
, &hModule
);
891 case DLL_PROCESS_DETACH
:
900 #elif defined(_MSC_VER)
901 #pragma section(".CRT$XCU",read)
902 static void alc_constructor(void);
903 static void alc_destructor(void);
904 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
906 static void alc_constructor(void)
908 atexit(alc_destructor
);
912 static void alc_destructor(void)
916 #elif defined(HAVE_GCC_DESTRUCTOR)
917 static void alc_init(void) __attribute__((constructor
));
918 static void alc_deinit(void) __attribute__((destructor
));
920 #error "No static initialization available on this platform!"
923 #elif defined(HAVE_GCC_DESTRUCTOR)
925 static void alc_init(void) __attribute__((constructor
));
926 static void alc_deinit(void) __attribute__((destructor
));
929 #error "No global initialization available on this platform!"
932 static void ReleaseThreadCtx(ALCcontext
*ctx
);
933 static void alc_init(void)
937 const char *str
{getenv("__ALSOFT_HALF_ANGLE_CONES")};
938 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
941 str
= getenv("__ALSOFT_REVERSE_Z");
942 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
945 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
946 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
947 OverrideReverbSpeedOfSound
= AL_TRUE
;
949 ThreadCtxProc
= ReleaseThreadCtx
;
952 static void alc_initconfig(void)
954 const char *devs
, *str
;
959 str
= getenv("ALSOFT_LOGLEVEL");
962 long lvl
= strtol(str
, nullptr, 0);
963 if(lvl
>= NoLog
&& lvl
<= LogRef
)
964 LogLevel
= static_cast<enum LogLevel
>(lvl
);
967 str
= getenv("ALSOFT_LOGFILE");
971 std::wstring wname
{utf8_to_wstr(str
)};
972 FILE *logfile
= _wfopen(wname
.c_str(), L
"wt");
974 FILE *logfile
= fopen(str
, "wt");
976 if(logfile
) LogFile
= logfile
;
977 else ERR("Failed to open log file '%s'\n", str
);
980 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
981 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
984 if(BackendListSize
> 0)
985 names
+= BackendList
[0].name
;
986 for(i
= 1;i
< BackendListSize
;i
++)
989 names
+= BackendList
[i
].name
;
991 TRACE("Supported backends: %s\n", names
.c_str());
995 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
998 if(strcasecmp(str
, "ignore") == 0)
1000 SuspendDefers
= false;
1001 TRACE("Selected context suspend behavior, \"ignore\"\n");
1004 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
1008 #if defined(HAVE_SSE4_1)
1009 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1010 #elif defined(HAVE_SSE3)
1011 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1012 #elif defined(HAVE_SSE2)
1013 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1014 #elif defined(HAVE_SSE)
1015 capfilter
|= CPU_CAP_SSE
;
1018 capfilter
|= CPU_CAP_NEON
;
1020 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str
))
1022 if(strcasecmp(str
, "all") == 0)
1027 const char *next
= str
;
1031 while(isspace(str
[0]))
1033 next
= strchr(str
, ',');
1035 if(!str
[0] || str
[0] == ',')
1038 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1039 while(len
> 0 && isspace(str
[len
-1]))
1041 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
1042 capfilter
&= ~CPU_CAP_SSE
;
1043 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
1044 capfilter
&= ~CPU_CAP_SSE2
;
1045 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
1046 capfilter
&= ~CPU_CAP_SSE3
;
1047 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
1048 capfilter
&= ~CPU_CAP_SSE4_1
;
1049 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
1050 capfilter
&= ~CPU_CAP_NEON
;
1052 WARN("Invalid CPU extension \"%s\"\n", str
);
1056 FillCPUCaps(capfilter
);
1063 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel
);
1068 str
= getenv("ALSOFT_TRAP_ERROR");
1069 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1071 TrapALError
= AL_TRUE
;
1072 TrapALCError
= true;
1076 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1077 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1078 TrapALError
= AL_TRUE
;
1079 TrapALError
= GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError
);
1081 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1082 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1083 TrapALCError
= true;
1084 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError
);
1087 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf
))
1088 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1090 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1091 ConfigValueStr(nullptr, nullptr, "drivers", &devs
))
1095 const char *next
= devs
;
1096 int endlist
, delitem
;
1101 while(isspace(devs
[0]))
1103 next
= strchr(devs
, ',');
1105 delitem
= (devs
[0] == '-');
1106 if(devs
[0] == '-') devs
++;
1108 if(!devs
[0] || devs
[0] == ',')
1115 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1116 while(len
> 0 && isspace(devs
[len
-1]))
1119 /* HACK: For backwards compatibility, convert backend references of
1120 * mmdevapi to wasapi. This should eventually be removed.
1122 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1128 for(n
= i
;n
< BackendListSize
;n
++)
1130 if(len
== strlen(BackendList
[n
].name
) &&
1131 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1135 for(;n
+1 < BackendListSize
;n
++)
1136 BackendList
[n
] = BackendList
[n
+1];
1141 struct BackendInfo Bkp
= BackendList
[n
];
1143 BackendList
[n
] = BackendList
[n
-1];
1144 BackendList
[n
] = Bkp
;
1154 BackendListSize
= i
;
1157 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1159 BackendList
[n
] = BackendList
[i
];
1161 BackendFactory
&factory
= BackendList
[n
].getFactory();
1164 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1168 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1169 if(!PlaybackBackend
.name
&& factory
.querySupport(ALCbackend_Playback
))
1171 PlaybackBackend
= BackendList
[n
];
1172 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1174 if(!CaptureBackend
.name
&& factory
.querySupport(ALCbackend_Capture
))
1176 CaptureBackend
= BackendList
[n
];
1177 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1181 BackendListSize
= n
;
1183 LoopbackBackendFactory::getFactory().init();
1185 if(!PlaybackBackend
.name
)
1186 WARN("No playback backend available!\n");
1187 if(!CaptureBackend
.name
)
1188 WARN("No capture backend available!\n");
1190 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str
))
1193 const char *next
= str
;
1197 next
= strchr(str
, ',');
1199 if(!str
[0] || next
== str
)
1202 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1203 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1205 if(len
== strlen(EffectList
[n
].name
) &&
1206 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1207 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1212 InitEffect(&DefaultEffect
);
1213 str
= getenv("ALSOFT_DEFAULT_REVERB");
1214 if((str
&& str
[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str
))
1215 LoadReverbPreset(str
, &DefaultEffect
);
1217 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1220 /************************************************
1221 * Library deinitialization
1222 ************************************************/
1223 static void alc_cleanup(void)
1225 alcAllDevicesList
.clear();
1226 alcCaptureDeviceList
.clear();
1228 alcDefaultAllDevicesSpecifier
.clear();
1229 alcCaptureDefaultDeviceSpecifier
.clear();
1231 if(ALCdevice
*dev
{DeviceList
.exchange(nullptr)})
1236 dev
= dev
->next
.load(std::memory_order_relaxed
);
1237 } while(dev
!= nullptr);
1238 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1242 static void alc_deinit_safe(void)
1249 ThreadCtxProc
= nullptr;
1251 if(LogFile
!= stderr
)
1256 static void alc_deinit(void)
1262 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1263 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1265 for(i
= 0;i
< BackendListSize
;i
++)
1266 BackendList
[i
].getFactory().deinit();
1268 LoopbackBackendFactory::getFactory().deinit();
1274 /************************************************
1275 * Device enumeration
1276 ************************************************/
1277 static void ProbeDevices(std::string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1281 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1283 if(backendinfo
->getFactory
)
1284 backendinfo
->getFactory().probe(type
, list
);
1286 static void ProbeAllDevicesList(void)
1287 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1288 static void ProbeCaptureDeviceList(void)
1289 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1292 /************************************************
1293 * Device format information
1294 ************************************************/
1295 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1299 case DevFmtByte
: return "Signed Byte";
1300 case DevFmtUByte
: return "Unsigned Byte";
1301 case DevFmtShort
: return "Signed Short";
1302 case DevFmtUShort
: return "Unsigned Short";
1303 case DevFmtInt
: return "Signed Int";
1304 case DevFmtUInt
: return "Unsigned Int";
1305 case DevFmtFloat
: return "Float";
1307 return "(unknown type)";
1309 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1313 case DevFmtMono
: return "Mono";
1314 case DevFmtStereo
: return "Stereo";
1315 case DevFmtQuad
: return "Quadraphonic";
1316 case DevFmtX51
: return "5.1 Surround";
1317 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1318 case DevFmtX61
: return "6.1 Surround";
1319 case DevFmtX71
: return "7.1 Surround";
1320 case DevFmtAmbi3D
: return "Ambisonic 3D";
1322 return "(unknown channels)";
1325 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1329 case DevFmtByte
: return sizeof(ALbyte
);
1330 case DevFmtUByte
: return sizeof(ALubyte
);
1331 case DevFmtShort
: return sizeof(ALshort
);
1332 case DevFmtUShort
: return sizeof(ALushort
);
1333 case DevFmtInt
: return sizeof(ALint
);
1334 case DevFmtUInt
: return sizeof(ALuint
);
1335 case DevFmtFloat
: return sizeof(ALfloat
);
1339 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1343 case DevFmtMono
: return 1;
1344 case DevFmtStereo
: return 2;
1345 case DevFmtQuad
: return 4;
1346 case DevFmtX51
: return 6;
1347 case DevFmtX51Rear
: return 6;
1348 case DevFmtX61
: return 7;
1349 case DevFmtX71
: return 8;
1350 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1351 (ambiorder
== 2) ? 9 :
1352 (ambiorder
== 1) ? 4 : 1;
1357 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1358 enum DevFmtType
*type
)
1360 static const struct {
1362 enum DevFmtChannels channels
;
1363 enum DevFmtType type
;
1365 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1366 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1367 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1369 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1370 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1371 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1373 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1374 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1375 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1377 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1378 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1379 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1381 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1382 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1383 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1385 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1386 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1387 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1391 for(i
= 0;i
< COUNTOF(list
);i
++)
1393 if(list
[i
].format
== format
)
1395 *chans
= list
[i
].channels
;
1396 *type
= list
[i
].type
;
1404 static ALCboolean
IsValidALCType(ALCenum type
)
1409 case ALC_UNSIGNED_BYTE_SOFT
:
1410 case ALC_SHORT_SOFT
:
1411 case ALC_UNSIGNED_SHORT_SOFT
:
1413 case ALC_UNSIGNED_INT_SOFT
:
1414 case ALC_FLOAT_SOFT
:
1420 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1425 case ALC_STEREO_SOFT
:
1427 case ALC_5POINT1_SOFT
:
1428 case ALC_6POINT1_SOFT
:
1429 case ALC_7POINT1_SOFT
:
1430 case ALC_BFORMAT3D_SOFT
:
1436 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1447 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1459 /************************************************
1460 * Miscellaneous ALC helpers
1461 ************************************************/
1463 /* SetDefaultWFXChannelOrder
1465 * Sets the default channel order used by WaveFormatEx.
1467 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1471 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1472 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1474 switch(device
->FmtChans
)
1477 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1480 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1481 device
->RealOut
.ChannelName
[1] = FrontRight
;
1484 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1485 device
->RealOut
.ChannelName
[1] = FrontRight
;
1486 device
->RealOut
.ChannelName
[2] = BackLeft
;
1487 device
->RealOut
.ChannelName
[3] = BackRight
;
1490 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1491 device
->RealOut
.ChannelName
[1] = FrontRight
;
1492 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1493 device
->RealOut
.ChannelName
[3] = LFE
;
1494 device
->RealOut
.ChannelName
[4] = SideLeft
;
1495 device
->RealOut
.ChannelName
[5] = SideRight
;
1498 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1499 device
->RealOut
.ChannelName
[1] = FrontRight
;
1500 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1501 device
->RealOut
.ChannelName
[3] = LFE
;
1502 device
->RealOut
.ChannelName
[4] = BackLeft
;
1503 device
->RealOut
.ChannelName
[5] = BackRight
;
1506 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1507 device
->RealOut
.ChannelName
[1] = FrontRight
;
1508 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1509 device
->RealOut
.ChannelName
[3] = LFE
;
1510 device
->RealOut
.ChannelName
[4] = BackCenter
;
1511 device
->RealOut
.ChannelName
[5] = SideLeft
;
1512 device
->RealOut
.ChannelName
[6] = SideRight
;
1515 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1516 device
->RealOut
.ChannelName
[1] = FrontRight
;
1517 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1518 device
->RealOut
.ChannelName
[3] = LFE
;
1519 device
->RealOut
.ChannelName
[4] = BackLeft
;
1520 device
->RealOut
.ChannelName
[5] = BackRight
;
1521 device
->RealOut
.ChannelName
[6] = SideLeft
;
1522 device
->RealOut
.ChannelName
[7] = SideRight
;
1525 device
->RealOut
.ChannelName
[0] = Aux0
;
1526 if(device
->mAmbiOrder
> 0)
1528 device
->RealOut
.ChannelName
[1] = Aux1
;
1529 device
->RealOut
.ChannelName
[2] = Aux2
;
1530 device
->RealOut
.ChannelName
[3] = Aux3
;
1532 if(device
->mAmbiOrder
> 1)
1534 device
->RealOut
.ChannelName
[4] = Aux4
;
1535 device
->RealOut
.ChannelName
[5] = Aux5
;
1536 device
->RealOut
.ChannelName
[6] = Aux6
;
1537 device
->RealOut
.ChannelName
[7] = Aux7
;
1538 device
->RealOut
.ChannelName
[8] = Aux8
;
1540 if(device
->mAmbiOrder
> 2)
1542 device
->RealOut
.ChannelName
[9] = Aux9
;
1543 device
->RealOut
.ChannelName
[10] = Aux10
;
1544 device
->RealOut
.ChannelName
[11] = Aux11
;
1545 device
->RealOut
.ChannelName
[12] = Aux12
;
1546 device
->RealOut
.ChannelName
[13] = Aux13
;
1547 device
->RealOut
.ChannelName
[14] = Aux14
;
1548 device
->RealOut
.ChannelName
[15] = Aux15
;
1554 /* SetDefaultChannelOrder
1556 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1558 void SetDefaultChannelOrder(ALCdevice
*device
)
1562 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1563 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1565 switch(device
->FmtChans
)
1568 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1569 device
->RealOut
.ChannelName
[1] = FrontRight
;
1570 device
->RealOut
.ChannelName
[2] = BackLeft
;
1571 device
->RealOut
.ChannelName
[3] = BackRight
;
1572 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1573 device
->RealOut
.ChannelName
[5] = LFE
;
1576 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1577 device
->RealOut
.ChannelName
[1] = FrontRight
;
1578 device
->RealOut
.ChannelName
[2] = BackLeft
;
1579 device
->RealOut
.ChannelName
[3] = BackRight
;
1580 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1581 device
->RealOut
.ChannelName
[5] = LFE
;
1582 device
->RealOut
.ChannelName
[6] = SideLeft
;
1583 device
->RealOut
.ChannelName
[7] = SideRight
;
1586 /* Same as WFX order */
1593 SetDefaultWFXChannelOrder(device
);
1599 /* ALCcontext_DeferUpdates
1601 * Defers/suspends updates for the given context's listener and sources. This
1602 * does *NOT* stop mixing, but rather prevents certain property changes from
1605 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1607 context
->DeferUpdates
.store(true);
1610 /* ALCcontext_ProcessUpdates
1612 * Resumes update processing after being deferred.
1614 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1616 std::lock_guard
<almtx_t
> _
{context
->PropLock
};
1617 if(context
->DeferUpdates
.exchange(false))
1619 /* Tell the mixer to stop applying updates, then wait for any active
1620 * updating to finish, before providing updates.
1622 context
->HoldUpdates
.store(AL_TRUE
);
1623 while((context
->UpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1626 if(!context
->PropsClean
.test_and_set(std::memory_order_acq_rel
))
1627 UpdateContextProps(context
);
1628 if(!context
->Listener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1629 UpdateListenerProps(context
);
1630 UpdateAllEffectSlotProps(context
);
1631 UpdateAllSourceProps(context
);
1633 /* Now with all updates declared, let the mixer continue applying them
1634 * so they all happen at once.
1636 context
->HoldUpdates
.store(AL_FALSE
);
1643 * Stores the latest ALC device error
1645 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1647 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1651 /* DebugBreak() will cause an exception if there is no debugger */
1652 if(IsDebuggerPresent())
1654 #elif defined(SIGTRAP)
1660 device
->LastError
.store(errorCode
);
1662 LastNullDeviceError
.store(errorCode
);
1666 static struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1668 return CompressorInit(device
->RealOut
.NumChannels
, device
->Frequency
,
1669 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
,
1670 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1675 * Updates the device's base clock time with however many samples have been
1676 * done. This is used so frequency changes on the device don't cause the time
1677 * to jump forward or back. Must not be called while the device is running/
1680 static inline void UpdateClockBase(ALCdevice
*device
)
1682 IncrementRef(&device
->MixCount
);
1683 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1684 device
->SamplesDone
= 0;
1685 IncrementRef(&device
->MixCount
);
1688 /* UpdateDeviceParams
1690 * Updates device parameters according to the attribute list (caller is
1691 * responsible for holding the list lock).
1693 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1695 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1696 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1697 ALCenum gainLimiter
= device
->LimiterState
;
1698 const ALsizei old_sends
= device
->NumAuxSends
;
1699 ALsizei new_sends
= device
->NumAuxSends
;
1700 enum DevFmtChannels oldChans
;
1701 enum DevFmtType oldType
;
1702 ALboolean update_failed
;
1703 ALCsizei hrtf_id
= -1;
1704 ALCcontext
*context
;
1709 // Check for attributes
1710 if(device
->Type
== Loopback
)
1712 ALCsizei numMono
, numStereo
, numSends
;
1713 ALCenum alayout
= AL_NONE
;
1714 ALCenum ascale
= AL_NONE
;
1715 ALCenum schans
= AL_NONE
;
1716 ALCenum stype
= AL_NONE
;
1717 ALCsizei attrIdx
= 0;
1718 ALCsizei aorder
= 0;
1723 WARN("Missing attributes for loopback device\n");
1724 return ALC_INVALID_VALUE
;
1727 numMono
= device
->NumMonoSources
;
1728 numStereo
= device
->NumStereoSources
;
1729 numSends
= old_sends
;
1731 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1732 while(attrList
[attrIdx
])
1734 switch(attrList
[attrIdx
])
1736 case ALC_FORMAT_CHANNELS_SOFT
:
1737 schans
= attrList
[attrIdx
+ 1];
1738 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1739 if(!IsValidALCChannels(schans
))
1740 return ALC_INVALID_VALUE
;
1743 case ALC_FORMAT_TYPE_SOFT
:
1744 stype
= attrList
[attrIdx
+ 1];
1745 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1746 if(!IsValidALCType(stype
))
1747 return ALC_INVALID_VALUE
;
1751 freq
= attrList
[attrIdx
+ 1];
1752 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1753 if(freq
< MIN_OUTPUT_RATE
)
1754 return ALC_INVALID_VALUE
;
1757 case ALC_AMBISONIC_LAYOUT_SOFT
:
1758 alayout
= attrList
[attrIdx
+ 1];
1759 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1760 if(!IsValidAmbiLayout(alayout
))
1761 return ALC_INVALID_VALUE
;
1764 case ALC_AMBISONIC_SCALING_SOFT
:
1765 ascale
= attrList
[attrIdx
+ 1];
1766 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1767 if(!IsValidAmbiScaling(ascale
))
1768 return ALC_INVALID_VALUE
;
1771 case ALC_AMBISONIC_ORDER_SOFT
:
1772 aorder
= attrList
[attrIdx
+ 1];
1773 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1774 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1775 return ALC_INVALID_VALUE
;
1778 case ALC_MONO_SOURCES
:
1779 numMono
= attrList
[attrIdx
+ 1];
1780 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1781 numMono
= maxi(numMono
, 0);
1784 case ALC_STEREO_SOURCES
:
1785 numStereo
= attrList
[attrIdx
+ 1];
1786 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1787 numStereo
= maxi(numStereo
, 0);
1790 case ALC_MAX_AUXILIARY_SENDS
:
1791 numSends
= attrList
[attrIdx
+ 1];
1792 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1793 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1797 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1798 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1799 hrtf_appreq
= Hrtf_Disable
;
1800 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1801 hrtf_appreq
= Hrtf_Enable
;
1803 hrtf_appreq
= Hrtf_Default
;
1806 case ALC_HRTF_ID_SOFT
:
1807 hrtf_id
= attrList
[attrIdx
+ 1];
1808 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1811 case ALC_OUTPUT_LIMITER_SOFT
:
1812 gainLimiter
= attrList
[attrIdx
+ 1];
1813 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1817 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1818 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1826 if(!schans
|| !stype
|| !freq
)
1828 WARN("Missing format for loopback device\n");
1829 return ALC_INVALID_VALUE
;
1831 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1833 WARN("Missing ambisonic info for loopback device\n");
1834 return ALC_INVALID_VALUE
;
1837 if((device
->Flags
&DEVICE_RUNNING
))
1838 V0(device
->Backend
,stop
)();
1839 device
->Flags
&= ~DEVICE_RUNNING
;
1841 UpdateClockBase(device
);
1843 device
->Frequency
= freq
;
1844 device
->FmtChans
= static_cast<enum DevFmtChannels
>(schans
);
1845 device
->FmtType
= static_cast<enum DevFmtType
>(stype
);
1846 if(schans
== ALC_BFORMAT3D_SOFT
)
1848 device
->mAmbiOrder
= aorder
;
1849 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1850 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1853 if(numMono
> INT_MAX
-numStereo
)
1854 numMono
= INT_MAX
-numStereo
;
1855 numMono
+= numStereo
;
1856 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono
))
1862 numMono
= maxi(numMono
, 256);
1863 numStereo
= mini(numStereo
, numMono
);
1864 numMono
-= numStereo
;
1865 device
->SourcesMax
= numMono
+ numStereo
;
1867 device
->NumMonoSources
= numMono
;
1868 device
->NumStereoSources
= numStereo
;
1870 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends
))
1871 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1873 new_sends
= numSends
;
1875 else if(attrList
&& attrList
[0])
1877 ALCsizei numMono
, numStereo
, numSends
;
1878 ALCsizei attrIdx
= 0;
1881 /* If a context is already running on the device, stop playback so the
1882 * device attributes can be updated. */
1883 if((device
->Flags
&DEVICE_RUNNING
))
1884 V0(device
->Backend
,stop
)();
1885 device
->Flags
&= ~DEVICE_RUNNING
;
1887 UpdateClockBase(device
);
1889 freq
= device
->Frequency
;
1890 numMono
= device
->NumMonoSources
;
1891 numStereo
= device
->NumStereoSources
;
1892 numSends
= old_sends
;
1894 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1895 while(attrList
[attrIdx
])
1897 switch(attrList
[attrIdx
])
1900 freq
= attrList
[attrIdx
+ 1];
1901 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1902 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1905 case ALC_MONO_SOURCES
:
1906 numMono
= attrList
[attrIdx
+ 1];
1907 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1908 numMono
= maxi(numMono
, 0);
1911 case ALC_STEREO_SOURCES
:
1912 numStereo
= attrList
[attrIdx
+ 1];
1913 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1914 numStereo
= maxi(numStereo
, 0);
1917 case ALC_MAX_AUXILIARY_SENDS
:
1918 numSends
= attrList
[attrIdx
+ 1];
1919 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1920 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1924 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1925 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1926 hrtf_appreq
= Hrtf_Disable
;
1927 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1928 hrtf_appreq
= Hrtf_Enable
;
1930 hrtf_appreq
= Hrtf_Default
;
1933 case ALC_HRTF_ID_SOFT
:
1934 hrtf_id
= attrList
[attrIdx
+ 1];
1935 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1938 case ALC_OUTPUT_LIMITER_SOFT
:
1939 gainLimiter
= attrList
[attrIdx
+ 1];
1940 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1944 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1945 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1953 ConfigValueUInt(device
->DeviceName
.c_str(), nullptr, "frequency", &freq
);
1954 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1956 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1958 /* SSE and Neon do best with the update size being a multiple of 4 */
1959 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1960 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1962 device
->Frequency
= freq
;
1964 if(numMono
> INT_MAX
-numStereo
)
1965 numMono
= INT_MAX
-numStereo
;
1966 numMono
+= numStereo
;
1967 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sources", &numMono
))
1973 numMono
= maxi(numMono
, 256);
1974 numStereo
= mini(numStereo
, numMono
);
1975 numMono
-= numStereo
;
1976 device
->SourcesMax
= numMono
+ numStereo
;
1978 device
->NumMonoSources
= numMono
;
1979 device
->NumStereoSources
= numStereo
;
1981 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sends", &new_sends
))
1982 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1984 new_sends
= numSends
;
1987 if((device
->Flags
&DEVICE_RUNNING
))
1988 return ALC_NO_ERROR
;
1990 al_free(device
->Uhj_Encoder
);
1991 device
->Uhj_Encoder
= nullptr;
1993 al_free(device
->Bs2b
);
1994 device
->Bs2b
= nullptr;
1996 device
->ChannelDelay
.clear();
1997 device
->ChannelDelay
.shrink_to_fit();
1999 device
->Dry
.Buffer
= nullptr;
2000 device
->Dry
.NumChannels
= 0;
2001 device
->FOAOut
.Buffer
= nullptr;
2002 device
->FOAOut
.NumChannels
= 0;
2003 device
->RealOut
.Buffer
= nullptr;
2004 device
->RealOut
.NumChannels
= 0;
2005 device
->MixBuffer
.clear();
2006 device
->MixBuffer
.shrink_to_fit();
2008 UpdateClockBase(device
);
2009 device
->FixedLatency
= 0;
2011 device
->DitherSeed
= DITHER_RNG_SEED
;
2013 /*************************************************************************
2014 * Update device format request if HRTF is requested
2016 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2017 if(device
->Type
!= Loopback
)
2020 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf", &hrtf
))
2022 if(strcasecmp(hrtf
, "true") == 0)
2023 hrtf_userreq
= Hrtf_Enable
;
2024 else if(strcasecmp(hrtf
, "false") == 0)
2025 hrtf_userreq
= Hrtf_Disable
;
2026 else if(strcasecmp(hrtf
, "auto") != 0)
2027 ERR("Unexpected hrtf value: %s\n", hrtf
);
2030 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2032 struct Hrtf
*hrtf
= nullptr;
2033 if(device
->HrtfList
.empty())
2034 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
2035 if(!device
->HrtfList
.empty())
2037 if(hrtf_id
>= 0 && (size_t)hrtf_id
< device
->HrtfList
.size())
2038 hrtf
= GetLoadedHrtf(device
->HrtfList
[hrtf_id
].hrtf
);
2040 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
2045 device
->FmtChans
= DevFmtStereo
;
2046 device
->Frequency
= hrtf
->sampleRate
;
2047 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2048 if(device
->HrtfHandle
)
2049 Hrtf_DecRef(device
->HrtfHandle
);
2050 device
->HrtfHandle
= hrtf
;
2054 hrtf_userreq
= Hrtf_Default
;
2055 hrtf_appreq
= Hrtf_Disable
;
2056 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2061 oldFreq
= device
->Frequency
;
2062 oldChans
= device
->FmtChans
;
2063 oldType
= device
->FmtType
;
2065 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2066 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2067 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2068 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2069 device
->UpdateSize
, device
->NumUpdates
2072 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2073 return ALC_INVALID_DEVICE
;
2075 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2077 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2078 DevFmtChannelsString(device
->FmtChans
));
2079 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2081 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2083 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2084 DevFmtTypeString(device
->FmtType
));
2085 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2087 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2089 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2090 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2093 if((device
->UpdateSize
&3) != 0)
2095 if((CPUCapFlags
&CPU_CAP_SSE
))
2096 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2097 if((CPUCapFlags
&CPU_CAP_NEON
))
2098 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2101 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2102 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2103 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2106 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2107 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2108 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2110 /* Allocate extra channels for any post-filter output. */
2111 ALsizei num_chans
{device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2112 device
->RealOut
.NumChannels
};
2114 TRACE("Allocating %d channels, " SZFMT
" bytes\n", num_chans
,
2115 num_chans
*sizeof(device
->MixBuffer
[0]));
2116 device
->MixBuffer
.resize(num_chans
);
2118 device
->Dry
.Buffer
= &reinterpret_cast<ALfloat(&)[BUFFERSIZE
]>(device
->MixBuffer
[0]);
2119 if(device
->RealOut
.NumChannels
!= 0)
2120 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2121 device
->FOAOut
.NumChannels
;
2124 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2125 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2128 if(device
->FOAOut
.NumChannels
!= 0)
2129 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2132 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2133 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2136 device
->NumAuxSends
= new_sends
;
2137 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2138 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2139 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2141 device
->DitherDepth
= 0.0f
;
2142 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2145 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth", &depth
);
2148 switch(device
->FmtType
)
2167 depth
= clampi(depth
, 2, 24);
2168 device
->DitherDepth
= std::pow(2.0f
, (ALfloat
)(depth
-1));
2171 if(!(device
->DitherDepth
> 0.0f
))
2172 TRACE("Dithering disabled\n");
2174 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2175 device
->DitherDepth
);
2177 device
->LimiterState
= gainLimiter
;
2178 if(ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter", &val
))
2179 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2181 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2182 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2183 * output (where samples must be clamped), and don't for floating-point
2184 * (which can take unclamped samples).
2186 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2188 switch(device
->FmtType
)
2196 gainLimiter
= ALC_TRUE
;
2199 gainLimiter
= ALC_FALSE
;
2203 if(gainLimiter
!= ALC_FALSE
)
2205 ALfloat thrshld
= 1.0f
;
2206 switch(device
->FmtType
)
2210 thrshld
= 127.0f
/ 128.0f
;
2214 thrshld
= 32767.0f
/ 32768.0f
;
2221 if(device
->DitherDepth
> 0.0f
)
2222 thrshld
-= 1.0f
/ device
->DitherDepth
;
2224 al_free(device
->Limiter
);
2225 device
->Limiter
= CreateDeviceLimiter(device
, std::log10(thrshld
) * 20.0f
);
2226 device
->FixedLatency
+= (ALuint
)(GetCompressorLookAhead(device
->Limiter
) *
2227 DEVICE_CLOCK_RES
/ device
->Frequency
);
2231 al_free(device
->Limiter
);
2232 device
->Limiter
= nullptr;
2234 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2236 aluSelectPostProcess(device
);
2238 TRACE("Fixed device latency: %uns\n", device
->FixedLatency
);
2240 /* Need to delay returning failure until replacement Send arrays have been
2241 * allocated with the appropriate size.
2243 update_failed
= AL_FALSE
;
2245 context
= device
->ContextList
.load();
2248 struct ALvoiceProps
*vprops
;
2251 if(context
->DefaultSlot
)
2253 ALeffectslot
*slot
= context
->DefaultSlot
.get();
2254 EffectState
*state
= slot
->Effect
.State
;
2256 state
->mOutBuffer
= device
->Dry
.Buffer
;
2257 state
->mOutChannels
= device
->Dry
.NumChannels
;
2258 if(state
->deviceUpdate(device
) == AL_FALSE
)
2259 update_failed
= AL_TRUE
;
2261 UpdateEffectSlotProps(slot
, context
);
2264 std::unique_lock
<almtx_t
> proplock
{context
->PropLock
};
2265 std::unique_lock
<almtx_t
> slotlock
{context
->EffectSlotLock
};
2266 for(auto &slot
: context
->EffectSlotList
)
2268 EffectState
*state
= slot
->Effect
.State
;
2270 state
->mOutBuffer
= device
->Dry
.Buffer
;
2271 state
->mOutChannels
= device
->Dry
.NumChannels
;
2272 if(state
->deviceUpdate(device
) == AL_FALSE
)
2273 update_failed
= AL_TRUE
;
2275 UpdateEffectSlotProps(slot
.get(), context
);
2279 std::unique_lock
<almtx_t
> srclock
{context
->SourceLock
};
2280 for(auto &sublist
: context
->SourceList
)
2282 uint64_t usemask
= ~sublist
.FreeMask
;
2285 ALsizei idx
= CTZ64(usemask
);
2286 ALsource
*source
= sublist
.Sources
+ idx
;
2288 usemask
&= ~(U64(1) << idx
);
2290 if(old_sends
!= device
->NumAuxSends
)
2293 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2295 if(source
->Send
[s
].Slot
)
2296 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2297 source
->Send
[s
].Slot
= nullptr;
2299 source
->Send
.resize(device
->NumAuxSends
);
2300 source
->Send
.shrink_to_fit();
2301 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2303 source
->Send
[s
].Slot
= nullptr;
2304 source
->Send
[s
].Gain
= 1.0f
;
2305 source
->Send
[s
].GainHF
= 1.0f
;
2306 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2307 source
->Send
[s
].GainLF
= 1.0f
;
2308 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2312 source
->PropsClean
.clear(std::memory_order_release
);
2316 /* Clear any pre-existing voice property structs, in case the number of
2317 * auxiliary sends is changing. Active sources will have updates
2318 * respecified in UpdateAllSourceProps.
2320 vprops
= context
->FreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
);
2323 struct ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2328 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2329 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2331 ALvoice
*voice
= context
->Voices
[pos
];
2333 al_free(voice
->Update
.exchange(nullptr, std::memory_order_acq_rel
));
2335 if(voice
->Source
.load(std::memory_order_acquire
) == nullptr)
2338 if(device
->AvgSpeakerDist
> 0.0f
)
2340 /* Reinitialize the NFC filters for new parameters. */
2341 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2342 (device
->AvgSpeakerDist
* device
->Frequency
);
2343 for(i
= 0;i
< voice
->NumChannels
;i
++)
2344 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2349 context
->PropsClean
.test_and_set(std::memory_order_release
);
2350 UpdateContextProps(context
);
2351 context
->Listener
.PropsClean
.test_and_set(std::memory_order_release
);
2352 UpdateListenerProps(context
);
2353 UpdateAllSourceProps(context
);
2355 context
= context
->next
.load(std::memory_order_relaxed
);
2359 return ALC_INVALID_DEVICE
;
2361 if(!(device
->Flags
&DEVICE_PAUSED
))
2363 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2364 return ALC_INVALID_DEVICE
;
2365 device
->Flags
|= DEVICE_RUNNING
;
2368 return ALC_NO_ERROR
;
2372 ALCdevice_struct::ALCdevice_struct(DeviceType type
)
2375 almtx_init(&BufferLock
, almtx_plain
);
2376 almtx_init(&EffectLock
, almtx_plain
);
2377 almtx_init(&FilterLock
, almtx_plain
);
2379 almtx_init(&BackendLock
, almtx_plain
);
2382 /* ALCdevice_struct::~ALCdevice_struct
2384 * Frees the device structure, and destroys any objects the app failed to
2385 * delete. Called once there's no more references on the device.
2387 ALCdevice_struct::~ALCdevice_struct()
2389 TRACE("%p\n", this);
2392 DELETE_OBJ(Backend
);
2395 almtx_destroy(&BackendLock
);
2397 ReleaseALBuffers(this);
2398 std::for_each(BufferList
.begin(), BufferList
.end(),
2399 [](BufferSubList
&entry
) noexcept
-> void
2400 { al_free(entry
.Buffers
); }
2403 almtx_destroy(&BufferLock
);
2405 ReleaseALEffects(this);
2406 std::for_each(EffectList
.begin(), EffectList
.end(),
2407 [](EffectSubList
&entry
) noexcept
-> void
2408 { al_free(entry
.Effects
); }
2411 almtx_destroy(&EffectLock
);
2413 ReleaseALFilters(this);
2414 std::for_each(FilterList
.begin(), FilterList
.end(),
2415 [](FilterSubList
&entry
) noexcept
-> void
2416 { al_free(entry
.Filters
); }
2419 almtx_destroy(&FilterLock
);
2423 Hrtf_DecRef(HrtfHandle
);
2424 HrtfHandle
= nullptr;
2431 al_free(Uhj_Encoder
);
2432 Uhj_Encoder
= nullptr;
2434 bformatdec_free(&AmbiDecoder
);
2435 ambiup_free(&AmbiUp
);
2438 Stablizer
= nullptr;
2445 void ALCdevice_IncRef(ALCdevice
*device
)
2447 auto ref
= IncrementRef(&device
->ref
);
2448 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2451 void ALCdevice_DecRef(ALCdevice
*device
)
2453 auto ref
= DecrementRef(&device
->ref
);
2454 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2455 if(ref
== 0) delete device
;
2460 * Checks if the device handle is valid, and increments its ref count if so.
2462 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2464 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2465 ALCdevice
*tmpDevice
{DeviceList
.load()};
2468 if(tmpDevice
== *device
)
2470 ALCdevice_IncRef(tmpDevice
);
2473 tmpDevice
= tmpDevice
->next
.load(std::memory_order_relaxed
);
2481 ALCcontext_struct::ALCcontext_struct(ALCdevice
*device
)
2488 * Initializes context fields
2490 static ALvoid
InitContext(ALCcontext
*Context
)
2492 ALlistener
&listener
= Context
->Listener
;
2493 struct ALeffectslotArray
*auxslots
;
2496 almtx_init(&Context
->PropLock
, almtx_plain
);
2497 almtx_init(&Context
->SourceLock
, almtx_plain
);
2498 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2500 if(Context
->DefaultSlot
)
2502 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2503 FAM_SIZE(struct ALeffectslotArray
, slot
, 1)));
2504 auxslots
->count
= 1;
2505 auxslots
->slot
[0] = Context
->DefaultSlot
.get();
2509 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2510 sizeof(struct ALeffectslotArray
)));
2511 auxslots
->count
= 0;
2513 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2516 Context
->mDistanceModel
= DistanceModel::Default
;
2517 Context
->SourceDistanceModel
= AL_FALSE
;
2518 Context
->DopplerFactor
= 1.0f
;
2519 Context
->DopplerVelocity
= 1.0f
;
2520 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2521 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2522 alsem_init(&Context
->EventSem
, 0);
2524 Context
->ExtensionList
= alExtList
;
2527 listener
.Params
.Matrix
= aluMatrixf::Identity
;
2528 aluVectorSet(&listener
.Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2529 listener
.Params
.Gain
= listener
.Gain
;
2530 listener
.Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2531 listener
.Params
.DopplerFactor
= Context
->DopplerFactor
;
2532 listener
.Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2533 listener
.Params
.ReverbSpeedOfSound
= listener
.Params
.SpeedOfSound
*
2534 listener
.Params
.MetersPerUnit
;
2535 listener
.Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2536 listener
.Params
.mDistanceModel
= Context
->mDistanceModel
;
2539 Context
->AsyncEvents
= ll_ringbuffer_create(63, sizeof(AsyncEvent
), false);
2540 StartEventThrd(Context
);
2544 /* ALCcontext_struct::~ALCcontext_struct()
2546 * Cleans up the context, and destroys any remaining objects the app failed to
2547 * delete. Called once there's no more references on the context.
2549 ALCcontext_struct::~ALCcontext_struct()
2551 TRACE("%p\n", this);
2553 struct ALcontextProps
*cprops
{Update
.load(std::memory_order_relaxed
)};
2556 TRACE("Freed unapplied context update %p\n", cprops
);
2560 cprops
= FreeContextProps
.load(std::memory_order_acquire
);
2563 struct ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2568 TRACE("Freed " SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2570 al_free(ActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
));
2571 DefaultSlot
= nullptr;
2573 ReleaseALSources(this);
2574 std::for_each(SourceList
.begin(), SourceList
.end(),
2575 [](const SourceSubList
&entry
) noexcept
-> void
2576 { al_free(entry
.Sources
); }
2580 almtx_destroy(&SourceLock
);
2583 struct ALeffectslotProps
*eprops
{FreeEffectslotProps
.load(std::memory_order_acquire
)};
2586 struct ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2587 if(eprops
->State
) eprops
->State
->DecRef();
2592 TRACE("Freed " SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2594 ReleaseALAuxiliaryEffectSlots(this);
2595 EffectSlotList
.clear();
2596 almtx_destroy(&EffectSlotLock
);
2599 struct ALvoiceProps
*vprops
{FreeVoiceProps
.load(std::memory_order_acquire
)};
2602 struct ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2607 TRACE("Freed " SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2609 for(ALsizei i
{0};i
< VoiceCount
;i
++)
2610 DeinitVoice(Voices
[i
]);
2616 struct ALlistenerProps
*lprops
{Listener
.Update
.load(std::memory_order_relaxed
)};
2619 TRACE("Freed unapplied listener update %p\n", lprops
);
2623 lprops
= FreeListenerProps
.load(std::memory_order_acquire
);
2626 struct ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2631 TRACE("Freed " SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2633 alsem_destroy(&EventSem
);
2635 ll_ringbuffer_free(AsyncEvents
);
2636 AsyncEvents
= nullptr;
2638 almtx_destroy(&PropLock
);
2640 ALCdevice_DecRef(Device
);
2645 * Removes the context reference from the given device and removes it from
2646 * being current on the running thread or globally. Returns true if other
2647 * contexts still exist on the device.
2649 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2651 ALCcontext
*origctx
, *newhead
;
2654 if(LocalContext
.get() == context
)
2656 WARN("%p released while current on thread\n", context
);
2657 LocalContext
.set(nullptr);
2658 ALCcontext_DecRef(context
);
2662 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2663 ALCcontext_DecRef(context
);
2665 V0(device
->Backend
,lock
)();
2667 newhead
= context
->next
.load(std::memory_order_relaxed
);
2668 if(!device
->ContextList
.compare_exchange_strong(origctx
, newhead
))
2672 /* origctx is what the desired context failed to match. Try
2673 * swapping out the next one in the list.
2677 } while(!list
->next
.compare_exchange_strong(origctx
, newhead
));
2681 V0(device
->Backend
,unlock
)();
2683 /* Make sure the context is finished and no longer processing in the mixer
2684 * before sending the message queue kill event. The backend's lock does
2685 * this, although waiting for a non-odd mix count would work too.
2688 StopEventThrd(context
);
2690 ALCcontext_DecRef(context
);
2694 static void ALCcontext_IncRef(ALCcontext
*context
)
2696 auto ref
= IncrementRef(&context
->ref
);
2697 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2700 void ALCcontext_DecRef(ALCcontext
*context
)
2702 auto ref
= DecrementRef(&context
->ref
);
2703 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2704 if(ref
== 0) delete context
;
2707 static void ReleaseThreadCtx(ALCcontext
*context
)
2709 auto ref
= DecrementRef(&context
->ref
);
2710 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2711 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2716 * Checks if the given context is valid, returning a new reference to it if so.
2718 static ContextRef
VerifyContext(ALCcontext
*context
)
2720 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2721 ALCdevice
*dev
{DeviceList
.load()};
2724 ALCcontext
*ctx
= dev
->ContextList
.load(std::memory_order_acquire
);
2729 ALCcontext_IncRef(ctx
);
2730 return ContextRef
{ctx
};
2732 ctx
= ctx
->next
.load(std::memory_order_relaxed
);
2734 dev
= dev
->next
.load(std::memory_order_relaxed
);
2737 return ContextRef
{};
2743 * Returns the currently active context for this thread, and adds a reference
2744 * without locking it.
2746 ALCcontext
*GetContextRef(void)
2748 ALCcontext
*context
{LocalContext
.get()};
2750 ALCcontext_IncRef(context
);
2753 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2754 context
= GlobalContext
.load(std::memory_order_acquire
);
2755 if(context
) ALCcontext_IncRef(context
);
2762 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2764 ALCdevice
*device
= context
->Device
;
2765 ALsizei num_sends
= device
->NumAuxSends
;
2766 struct ALvoiceProps
*props
;
2767 size_t sizeof_props
;
2768 size_t sizeof_voice
;
2774 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2777 /* Allocate the voice pointers, voices, and the voices' stored source
2778 * property set (including the dynamically-sized Send[] array) in one
2781 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2782 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2783 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2785 voices
= static_cast<ALvoice
**>(al_calloc(16, RoundUp(size
*num_voices
, 16)));
2786 /* The voice and property objects are stored interleaved since they're
2789 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2790 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2794 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2795 const ALsizei s_count
= mini(old_sends
, num_sends
);
2797 for(;v
< v_count
;v
++)
2799 ALvoice
*old_voice
= context
->Voices
[v
];
2802 /* Copy the old voice data and source property set to the new
2805 memcpy(voice
, old_voice
, sizeof(*voice
));
2806 for(i
= 0;i
< s_count
;i
++)
2807 voice
->Send
[i
] = old_voice
->Send
[i
];
2809 memcpy(props
, old_voice
->Props
, sizeof(*props
));
2810 for(i
= 0;i
< s_count
;i
++)
2811 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2813 /* Set this voice's property set pointer and voice reference. */
2814 voice
->Props
= props
;
2817 /* Increment pointers to the next storage space. */
2818 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2819 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2821 /* Deinit any left over voices that weren't copied over to the new
2822 * array. NOTE: If this does anything, v equals num_voices and
2823 * num_voices is less than VoiceCount, so the following loop won't do
2826 for(;v
< context
->VoiceCount
;v
++)
2827 DeinitVoice(context
->Voices
[v
]);
2829 /* Finish setting the voices' property set pointers and references. */
2830 for(;v
< num_voices
;v
++)
2832 ATOMIC_INIT(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr));
2834 voice
->Props
= props
;
2837 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2838 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2841 al_free(context
->Voices
);
2842 context
->Voices
= voices
;
2843 context
->MaxVoices
= num_voices
;
2844 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2848 /************************************************
2849 * Standard ALC functions
2850 ************************************************/
2854 * Return last ALC generated error code for the given device
2856 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2860 if(VerifyDevice(&device
))
2862 errorCode
= device
->LastError
.exchange(ALC_NO_ERROR
);
2863 ALCdevice_DecRef(device
);
2866 errorCode
= LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2872 /* alcSuspendContext
2874 * Suspends updates for the given context
2876 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2881 ContextRef ctx
{VerifyContext(context
)};
2883 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2885 ALCcontext_DeferUpdates(ctx
.get());
2888 /* alcProcessContext
2890 * Resumes processing updates for the given context
2892 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2897 ContextRef ctx
{VerifyContext(context
)};
2899 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2901 ALCcontext_ProcessUpdates(ctx
.get());
2907 * Returns information about the device, and error strings
2909 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2911 const ALCchar
*value
= nullptr;
2919 case ALC_INVALID_ENUM
:
2920 value
= alcErrInvalidEnum
;
2923 case ALC_INVALID_VALUE
:
2924 value
= alcErrInvalidValue
;
2927 case ALC_INVALID_DEVICE
:
2928 value
= alcErrInvalidDevice
;
2931 case ALC_INVALID_CONTEXT
:
2932 value
= alcErrInvalidContext
;
2935 case ALC_OUT_OF_MEMORY
:
2936 value
= alcErrOutOfMemory
;
2939 case ALC_DEVICE_SPECIFIER
:
2940 value
= alcDefaultName
;
2943 case ALC_ALL_DEVICES_SPECIFIER
:
2944 if(VerifyDevice(&Device
))
2946 value
= Device
->DeviceName
.c_str();
2947 ALCdevice_DecRef(Device
);
2951 ProbeAllDevicesList();
2952 value
= alcAllDevicesList
.c_str();
2956 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2957 if(VerifyDevice(&Device
))
2959 value
= Device
->DeviceName
.c_str();
2960 ALCdevice_DecRef(Device
);
2964 ProbeCaptureDeviceList();
2965 value
= alcCaptureDeviceList
.c_str();
2969 /* Default devices are always first in the list */
2970 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2971 value
= alcDefaultName
;
2974 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2975 if(alcAllDevicesList
.empty())
2976 ProbeAllDevicesList();
2978 /* Copy first entry as default. */
2979 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2980 value
= alcDefaultAllDevicesSpecifier
.c_str();
2983 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2984 if(alcCaptureDeviceList
.empty())
2985 ProbeCaptureDeviceList();
2987 /* Copy first entry as default. */
2988 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2989 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2992 case ALC_EXTENSIONS
:
2993 if(!VerifyDevice(&Device
))
2994 value
= alcNoDeviceExtList
;
2997 value
= alcExtensionList
;
2998 ALCdevice_DecRef(Device
);
3002 case ALC_HRTF_SPECIFIER_SOFT
:
3003 if(!VerifyDevice(&Device
))
3004 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3007 { std::lock_guard
<almtx_t
> _
{Device
->BackendLock
};
3008 value
= (Device
->HrtfHandle
? Device
->HrtfName
.c_str() : "");
3010 ALCdevice_DecRef(Device
);
3015 VerifyDevice(&Device
);
3016 alcSetError(Device
, ALC_INVALID_ENUM
);
3017 if(Device
) ALCdevice_DecRef(Device
);
3025 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3027 if(device
->Type
== Capture
) return 9;
3028 if(device
->Type
!= Loopback
) return 29;
3029 if(device
->FmtChans
== DevFmtAmbi3D
)
3034 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3038 if(size
<= 0 || values
== nullptr)
3040 alcSetError(device
, ALC_INVALID_VALUE
);
3048 case ALC_MAJOR_VERSION
:
3049 values
[0] = alcMajorVersion
;
3051 case ALC_MINOR_VERSION
:
3052 values
[0] = alcMinorVersion
;
3055 case ALC_ATTRIBUTES_SIZE
:
3056 case ALC_ALL_ATTRIBUTES
:
3060 case ALC_MONO_SOURCES
:
3061 case ALC_STEREO_SOURCES
:
3062 case ALC_CAPTURE_SAMPLES
:
3063 case ALC_FORMAT_CHANNELS_SOFT
:
3064 case ALC_FORMAT_TYPE_SOFT
:
3065 case ALC_AMBISONIC_LAYOUT_SOFT
:
3066 case ALC_AMBISONIC_SCALING_SOFT
:
3067 case ALC_AMBISONIC_ORDER_SOFT
:
3068 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3069 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3073 alcSetError(nullptr, ALC_INVALID_ENUM
);
3079 if(device
->Type
== Capture
)
3083 case ALC_ATTRIBUTES_SIZE
:
3084 values
[0] = NumAttrsForDevice(device
);
3087 case ALC_ALL_ATTRIBUTES
:
3089 if(size
< NumAttrsForDevice(device
))
3090 alcSetError(device
, ALC_INVALID_VALUE
);
3093 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3094 values
[i
++] = ALC_MAJOR_VERSION
;
3095 values
[i
++] = alcMajorVersion
;
3096 values
[i
++] = ALC_MINOR_VERSION
;
3097 values
[i
++] = alcMinorVersion
;
3098 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3099 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3100 values
[i
++] = ALC_CONNECTED
;
3101 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
3106 case ALC_MAJOR_VERSION
:
3107 values
[0] = alcMajorVersion
;
3109 case ALC_MINOR_VERSION
:
3110 values
[0] = alcMinorVersion
;
3113 case ALC_CAPTURE_SAMPLES
:
3114 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3115 values
[0] = V0(device
->Backend
,availableSamples
)();
3120 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3124 alcSetError(device
, ALC_INVALID_ENUM
);
3133 case ALC_ATTRIBUTES_SIZE
:
3134 values
[0] = NumAttrsForDevice(device
);
3137 case ALC_ALL_ATTRIBUTES
:
3139 if(size
< NumAttrsForDevice(device
))
3140 alcSetError(device
, ALC_INVALID_VALUE
);
3143 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3144 values
[i
++] = ALC_MAJOR_VERSION
;
3145 values
[i
++] = alcMajorVersion
;
3146 values
[i
++] = ALC_MINOR_VERSION
;
3147 values
[i
++] = alcMinorVersion
;
3148 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3149 values
[i
++] = alcEFXMajorVersion
;
3150 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3151 values
[i
++] = alcEFXMinorVersion
;
3153 values
[i
++] = ALC_FREQUENCY
;
3154 values
[i
++] = device
->Frequency
;
3155 if(device
->Type
!= Loopback
)
3157 values
[i
++] = ALC_REFRESH
;
3158 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3160 values
[i
++] = ALC_SYNC
;
3161 values
[i
++] = ALC_FALSE
;
3165 if(device
->FmtChans
== DevFmtAmbi3D
)
3167 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3168 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
3170 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3171 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
3173 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3174 values
[i
++] = device
->mAmbiOrder
;
3177 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3178 values
[i
++] = device
->FmtChans
;
3180 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3181 values
[i
++] = device
->FmtType
;
3184 values
[i
++] = ALC_MONO_SOURCES
;
3185 values
[i
++] = device
->NumMonoSources
;
3187 values
[i
++] = ALC_STEREO_SOURCES
;
3188 values
[i
++] = device
->NumStereoSources
;
3190 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3191 values
[i
++] = device
->NumAuxSends
;
3193 values
[i
++] = ALC_HRTF_SOFT
;
3194 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3196 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3197 values
[i
++] = device
->HrtfStatus
;
3199 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3200 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3202 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3203 values
[i
++] = MAX_AMBI_ORDER
;
3209 case ALC_MAJOR_VERSION
:
3210 values
[0] = alcMajorVersion
;
3213 case ALC_MINOR_VERSION
:
3214 values
[0] = alcMinorVersion
;
3217 case ALC_EFX_MAJOR_VERSION
:
3218 values
[0] = alcEFXMajorVersion
;
3221 case ALC_EFX_MINOR_VERSION
:
3222 values
[0] = alcEFXMinorVersion
;
3226 values
[0] = device
->Frequency
;
3230 if(device
->Type
== Loopback
)
3232 alcSetError(device
, ALC_INVALID_DEVICE
);
3235 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3236 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3241 if(device
->Type
== Loopback
)
3243 alcSetError(device
, ALC_INVALID_DEVICE
);
3246 values
[0] = ALC_FALSE
;
3249 case ALC_FORMAT_CHANNELS_SOFT
:
3250 if(device
->Type
!= Loopback
)
3252 alcSetError(device
, ALC_INVALID_DEVICE
);
3255 values
[0] = device
->FmtChans
;
3258 case ALC_FORMAT_TYPE_SOFT
:
3259 if(device
->Type
!= Loopback
)
3261 alcSetError(device
, ALC_INVALID_DEVICE
);
3264 values
[0] = device
->FmtType
;
3267 case ALC_AMBISONIC_LAYOUT_SOFT
:
3268 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3270 alcSetError(device
, ALC_INVALID_DEVICE
);
3273 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
3276 case ALC_AMBISONIC_SCALING_SOFT
:
3277 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3279 alcSetError(device
, ALC_INVALID_DEVICE
);
3282 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
3285 case ALC_AMBISONIC_ORDER_SOFT
:
3286 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3288 alcSetError(device
, ALC_INVALID_DEVICE
);
3291 values
[0] = device
->mAmbiOrder
;
3294 case ALC_MONO_SOURCES
:
3295 values
[0] = device
->NumMonoSources
;
3298 case ALC_STEREO_SOURCES
:
3299 values
[0] = device
->NumStereoSources
;
3302 case ALC_MAX_AUXILIARY_SENDS
:
3303 values
[0] = device
->NumAuxSends
;
3307 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3311 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3314 case ALC_HRTF_STATUS_SOFT
:
3315 values
[0] = device
->HrtfStatus
;
3318 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3319 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3320 device
->HrtfList
.clear();
3321 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3322 values
[0] = (ALCint
)device
->HrtfList
.size();
3326 case ALC_OUTPUT_LIMITER_SOFT
:
3327 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3330 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3331 values
[0] = MAX_AMBI_ORDER
;
3335 alcSetError(device
, ALC_INVALID_ENUM
);
3343 * Returns information about the device and the version of OpenAL
3345 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3347 VerifyDevice(&device
);
3348 if(size
<= 0 || values
== nullptr)
3349 alcSetError(device
, ALC_INVALID_VALUE
);
3351 GetIntegerv(device
, param
, size
, values
);
3352 if(device
) ALCdevice_DecRef(device
);
3355 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3357 VerifyDevice(&device
);
3358 if(size
<= 0 || values
== nullptr)
3359 alcSetError(device
, ALC_INVALID_VALUE
);
3360 else if(!device
|| device
->Type
== Capture
)
3362 std::vector
<ALCint
> ivals(size
);
3363 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3364 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3366 else /* render device */
3370 case ALC_ATTRIBUTES_SIZE
:
3371 *values
= NumAttrsForDevice(device
)+4;
3374 case ALC_ALL_ATTRIBUTES
:
3375 if(size
< NumAttrsForDevice(device
)+4)
3376 alcSetError(device
, ALC_INVALID_VALUE
);
3380 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3381 values
[i
++] = ALC_FREQUENCY
;
3382 values
[i
++] = device
->Frequency
;
3384 if(device
->Type
!= Loopback
)
3386 values
[i
++] = ALC_REFRESH
;
3387 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3389 values
[i
++] = ALC_SYNC
;
3390 values
[i
++] = ALC_FALSE
;
3394 if(device
->FmtChans
== DevFmtAmbi3D
)
3396 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3397 values
[i
++] = static_cast<ALCint64SOFT
>(device
->mAmbiLayout
);
3399 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3400 values
[i
++] = static_cast<ALCint64SOFT
>(device
->mAmbiScale
);
3402 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3403 values
[i
++] = device
->mAmbiOrder
;
3406 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3407 values
[i
++] = device
->FmtChans
;
3409 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3410 values
[i
++] = device
->FmtType
;
3413 values
[i
++] = ALC_MONO_SOURCES
;
3414 values
[i
++] = device
->NumMonoSources
;
3416 values
[i
++] = ALC_STEREO_SOURCES
;
3417 values
[i
++] = device
->NumStereoSources
;
3419 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3420 values
[i
++] = device
->NumAuxSends
;
3422 values
[i
++] = ALC_HRTF_SOFT
;
3423 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3425 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3426 values
[i
++] = device
->HrtfStatus
;
3428 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3429 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3431 ClockLatency clock
{GetClockLatency(device
)};
3432 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3433 values
[i
++] = clock
.ClockTime
;
3435 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3436 values
[i
++] = clock
.Latency
;
3442 case ALC_DEVICE_CLOCK_SOFT
:
3443 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3448 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3450 basecount
= device
->ClockBase
;
3451 samplecount
= device
->SamplesDone
;
3452 } while(refcount
!= ReadRef(&device
->MixCount
));
3453 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3457 case ALC_DEVICE_LATENCY_SOFT
:
3458 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3459 ClockLatency clock
{GetClockLatency(device
)};
3460 *values
= clock
.Latency
;
3464 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3466 alcSetError(device
, ALC_INVALID_VALUE
);
3469 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3470 ClockLatency clock
{GetClockLatency(device
)};
3471 values
[0] = clock
.ClockTime
;
3472 values
[1] = clock
.Latency
;
3477 std::vector
<ALCint
> ivals(size
);
3478 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3479 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3484 ALCdevice_DecRef(device
);
3488 /* alcIsExtensionPresent
3490 * Determines if there is support for a particular extension
3492 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3494 ALCboolean bResult
= ALC_FALSE
;
3496 VerifyDevice(&device
);
3499 alcSetError(device
, ALC_INVALID_VALUE
);
3502 size_t len
= strlen(extName
);
3503 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3506 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3507 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3512 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3516 } while(isspace(*ptr
));
3521 ALCdevice_DecRef(device
);
3526 /* alcGetProcAddress
3528 * Retrieves the function address for a particular extension function
3530 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3532 ALCvoid
*ptr
= nullptr;
3536 VerifyDevice(&device
);
3537 alcSetError(device
, ALC_INVALID_VALUE
);
3538 if(device
) ALCdevice_DecRef(device
);
3543 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3545 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3547 ptr
= alcFunctions
[i
].address
;
3559 * Get the value for a particular ALC enumeration name
3561 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3567 VerifyDevice(&device
);
3568 alcSetError(device
, ALC_INVALID_VALUE
);
3569 if(device
) ALCdevice_DecRef(device
);
3574 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3576 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3578 val
= alcEnumerations
[i
].value
;
3590 * Create and attach a context to the given device.
3592 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3594 ALCcontext
*ALContext
;
3598 /* Explicitly hold the list lock while taking the BackendLock in case the
3599 * device is asynchronously destropyed, to ensure this new context is
3600 * properly cleaned up after being made.
3602 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3603 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3604 !device
->Connected
.load(std::memory_order_relaxed
))
3607 alcSetError(device
, ALC_INVALID_DEVICE
);
3608 if(device
) ALCdevice_DecRef(device
);
3611 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
3614 device
->LastError
.store(ALC_NO_ERROR
);
3616 ALContext
= new ALCcontext
{device
};
3617 ALCdevice_IncRef(ALContext
->Device
);
3619 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3624 ALContext
= nullptr;
3626 alcSetError(device
, err
);
3627 if(err
== ALC_INVALID_DEVICE
)
3629 V0(device
->Backend
,lock
)();
3630 aluHandleDisconnect(device
, "Device update failure");
3631 V0(device
->Backend
,unlock
)();
3633 ALCdevice_DecRef(device
);
3636 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3638 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3640 ALContext
->DefaultSlot
.reset(new ALeffectslot
{});
3641 if(InitEffectSlot(ALContext
->DefaultSlot
.get()) == AL_NO_ERROR
)
3642 aluInitEffectPanning(ALContext
->DefaultSlot
.get());
3645 ALContext
->DefaultSlot
= nullptr;
3646 ERR("Failed to initialize the default effect slot\n");
3650 InitContext(ALContext
);
3652 if(ConfigValueFloat(device
->DeviceName
.c_str(), nullptr, "volume-adjust", &valf
))
3654 if(!std::isfinite(valf
))
3655 ERR("volume-adjust must be finite: %f\n", valf
);
3658 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3660 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3661 ALContext
->GainBoost
= std::pow(10.0f
, db
/20.0f
);
3662 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3665 UpdateListenerProps(ALContext
);
3668 ALCcontext
*head
= device
->ContextList
.load();
3670 ALContext
->next
.store(head
, std::memory_order_relaxed
);
3671 } while(!device
->ContextList
.compare_exchange_weak(head
, ALContext
));
3675 if(ALContext
->DefaultSlot
)
3677 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3678 UpdateEffectSlotProps(ALContext
->DefaultSlot
.get(), ALContext
);
3680 ERR("Failed to initialize the default effect\n");
3683 ALCdevice_DecRef(device
);
3685 TRACE("Created context %p\n", ALContext
);
3689 /* alcDestroyContext
3691 * Remove a context from its device
3693 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3695 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3696 ContextRef ctx
{VerifyContext(context
)};
3700 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3704 ALCdevice
* Device
{ctx
->Device
};
3707 std::lock_guard
<almtx_t
> _
{Device
->BackendLock
};
3708 if(!ReleaseContext(ctx
.get(), Device
))
3710 V0(Device
->Backend
,stop
)();
3711 Device
->Flags
&= ~DEVICE_RUNNING
;
3718 /* alcGetCurrentContext
3720 * Returns the currently active context on the calling thread
3722 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3724 ALCcontext
*Context
{LocalContext
.get()};
3725 if(!Context
) Context
= GlobalContext
.load();
3729 /* alcGetThreadContext
3731 * Returns the currently active thread-local context
3733 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3735 return LocalContext
.get();
3739 /* alcMakeContextCurrent
3741 * Makes the given context the active process-wide context, and removes the
3742 * thread-local context for the calling thread.
3744 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3746 /* context must be valid or nullptr */
3750 ctx
= VerifyContext(context
);
3753 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3757 /* Release this reference (if any) to store it in the GlobalContext
3758 * pointer. Take ownership of the reference (if any) that was previously
3761 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3763 /* Reset (decrement) the previous global reference by replacing it with the
3764 * thread-local context. Take ownership of the thread-local context
3765 * reference (if any), clearing the storage to null.
3767 ctx
= ContextRef
{LocalContext
.get()};
3768 if(ctx
) LocalContext
.set(nullptr);
3769 /* Reset (decrement) the previous thread-local reference. */
3774 /* alcSetThreadContext
3776 * Makes the given context the active context for the current thread
3778 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3780 /* context must be valid or nullptr */
3784 ctx
= VerifyContext(context
);
3787 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3791 /* context's reference count is already incremented */
3792 ContextRef old
{LocalContext
.get()};
3793 LocalContext
.set(ctx
.release());
3799 /* alcGetContextsDevice
3801 * Returns the device that a particular context is attached to
3803 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3805 ContextRef ctx
{VerifyContext(Context
)};
3808 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3817 * Opens the named device.
3819 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3823 if(!PlaybackBackend
.name
)
3825 alcSetError(nullptr, ALC_INVALID_VALUE
);
3829 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3831 /* Some old Windows apps hardcode these expecting OpenAL to use a
3832 * specific audio API, even when they're not enumerated. Creative's
3833 * router effectively ignores them too.
3835 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3836 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3839 deviceName
= nullptr;
3841 auto device
= new ALCdevice
{Playback
};
3844 device
->FmtChans
= DevFmtChannelsDefault
;
3845 device
->FmtType
= DevFmtTypeDefault
;
3846 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3847 device
->LimiterState
= ALC_TRUE
;
3848 device
->NumUpdates
= 3;
3849 device
->UpdateSize
= 1024;
3851 device
->SourcesMax
= 256;
3852 device
->AuxiliaryEffectSlotMax
= 64;
3853 device
->NumAuxSends
= DEFAULT_SENDS
;
3855 const ALCchar
*fmt
{};
3856 if(ConfigValueStr(deviceName
, nullptr, "channels", &fmt
))
3858 static constexpr struct ChannelMap
{
3859 const char name
[16];
3860 enum DevFmtChannels chans
;
3863 { "mono", DevFmtMono
, 0 },
3864 { "stereo", DevFmtStereo
, 0 },
3865 { "quad", DevFmtQuad
, 0 },
3866 { "surround51", DevFmtX51
, 0 },
3867 { "surround61", DevFmtX61
, 0 },
3868 { "surround71", DevFmtX71
, 0 },
3869 { "surround51rear", DevFmtX51Rear
, 0 },
3870 { "ambi1", DevFmtAmbi3D
, 1 },
3871 { "ambi2", DevFmtAmbi3D
, 2 },
3872 { "ambi3", DevFmtAmbi3D
, 3 },
3875 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3876 [fmt
](const ChannelMap
&entry
) -> bool
3877 { return strcasecmp(entry
.name
, fmt
) == 0; }
3879 if(iter
== std::end(chanlist
))
3880 ERR("Unsupported channels: %s\n", fmt
);
3883 device
->FmtChans
= iter
->chans
;
3884 device
->mAmbiOrder
= iter
->order
;
3885 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3888 if(ConfigValueStr(deviceName
, nullptr, "sample-type", &fmt
))
3890 static constexpr struct TypeMap
{
3891 const char name
[16];
3892 enum DevFmtType type
;
3894 { "int8", DevFmtByte
},
3895 { "uint8", DevFmtUByte
},
3896 { "int16", DevFmtShort
},
3897 { "uint16", DevFmtUShort
},
3898 { "int32", DevFmtInt
},
3899 { "uint32", DevFmtUInt
},
3900 { "float32", DevFmtFloat
},
3903 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3904 [fmt
](const TypeMap
&entry
) -> bool
3905 { return strcasecmp(entry
.name
, fmt
) == 0; }
3907 if(iter
== std::end(typelist
))
3908 ERR("Unsupported sample-type: %s\n", fmt
);
3911 device
->FmtType
= iter
->type
;
3912 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3916 if(ConfigValueUInt(deviceName
, nullptr, "frequency", &device
->Frequency
))
3918 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3919 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3920 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3921 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3924 ConfigValueUInt(deviceName
, nullptr, "periods", &device
->NumUpdates
);
3925 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3927 ConfigValueUInt(deviceName
, nullptr, "period_size", &device
->UpdateSize
);
3928 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3929 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3930 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3932 ConfigValueUInt(deviceName
, nullptr, "sources", &device
->SourcesMax
);
3933 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3935 ConfigValueUInt(deviceName
, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
3936 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3937 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
3939 if(ConfigValueInt(deviceName
, nullptr, "sends", &device
->NumAuxSends
))
3940 device
->NumAuxSends
= clampi(
3941 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3944 device
->NumStereoSources
= 1;
3945 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3947 device
->Backend
= PlaybackBackend
.getFactory().createBackend(device
, ALCbackend_Playback
);
3948 if(!device
->Backend
)
3951 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
3955 // Find a playback device to open
3956 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
3957 if(err
!= ALC_NO_ERROR
)
3960 alcSetError(nullptr, err
);
3964 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "ambi-format", &fmt
))
3966 if(strcasecmp(fmt
, "fuma") == 0)
3968 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3969 device
->mAmbiScale
= AmbiNorm::FuMa
;
3971 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3973 device
->mAmbiLayout
= AmbiLayout::ACN
;
3974 device
->mAmbiScale
= AmbiNorm::SN3D
;
3976 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3978 device
->mAmbiLayout
= AmbiLayout::ACN
;
3979 device
->mAmbiScale
= AmbiNorm::N3D
;
3982 ERR("Unsupported ambi-format: %s\n", fmt
);
3986 ALCdevice
*head
{DeviceList
.load()};
3988 device
->next
.store(head
, std::memory_order_relaxed
);
3989 } while(!DeviceList
.compare_exchange_weak(head
, device
));
3992 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
3998 * Closes the given device.
4000 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4002 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4003 ALCdevice
*iter
{DeviceList
.load()};
4007 iter
= iter
->next
.load(std::memory_order_relaxed
);
4008 } while(iter
!= nullptr);
4009 if(!iter
|| iter
->Type
== Capture
)
4011 alcSetError(iter
, ALC_INVALID_DEVICE
);
4014 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
4016 ALCdevice
*origdev
{device
};
4017 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4018 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4024 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4028 ALCcontext
*ctx
{device
->ContextList
.load()};
4029 while(ctx
!= nullptr)
4031 ALCcontext
*next
= ctx
->next
.load(std::memory_order_relaxed
);
4032 WARN("Releasing context %p\n", ctx
);
4033 ReleaseContext(ctx
, device
);
4036 if((device
->Flags
&DEVICE_RUNNING
))
4037 V0(device
->Backend
,stop
)();
4038 device
->Flags
&= ~DEVICE_RUNNING
;
4041 ALCdevice_DecRef(device
);
4047 /************************************************
4048 * ALC capture functions
4049 ************************************************/
4050 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4054 if(!CaptureBackend
.name
)
4056 alcSetError(nullptr, ALC_INVALID_VALUE
);
4062 alcSetError(nullptr, ALC_INVALID_VALUE
);
4066 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4067 deviceName
= nullptr;
4069 auto device
= new ALCdevice
{Capture
};
4071 device
->Frequency
= frequency
;
4072 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4074 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4077 alcSetError(nullptr, ALC_INVALID_ENUM
);
4080 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4082 device
->UpdateSize
= samples
;
4083 device
->NumUpdates
= 1;
4085 device
->Backend
= CaptureBackend
.getFactory().createBackend(device
, ALCbackend_Capture
);
4086 if(!device
->Backend
)
4089 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4093 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4094 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4095 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4097 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
4098 if(err
!= ALC_NO_ERROR
)
4101 alcSetError(nullptr, err
);
4106 ALCdevice
*head
{DeviceList
.load()};
4108 device
->next
.store(head
, std::memory_order_relaxed
);
4109 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4112 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
4116 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4118 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4120 ALCdevice
*iter
{DeviceList
.load()};
4124 iter
= iter
->next
.load(std::memory_order_relaxed
);
4125 } while(iter
!= nullptr);
4126 if(!iter
|| iter
->Type
!= Capture
)
4128 alcSetError(iter
, ALC_INVALID_DEVICE
);
4132 ALCdevice
*origdev
{device
};
4133 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4134 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4140 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4144 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4145 if((device
->Flags
&DEVICE_RUNNING
))
4146 V0(device
->Backend
,stop
)();
4147 device
->Flags
&= ~DEVICE_RUNNING
;
4150 ALCdevice_DecRef(device
);
4155 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4157 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4158 alcSetError(device
, ALC_INVALID_DEVICE
);
4161 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4162 if(!device
->Connected
.load(std::memory_order_acquire
))
4163 alcSetError(device
, ALC_INVALID_DEVICE
);
4164 else if(!(device
->Flags
&DEVICE_RUNNING
))
4166 if(V0(device
->Backend
,start
)())
4167 device
->Flags
|= DEVICE_RUNNING
;
4170 aluHandleDisconnect(device
, "Device start failure");
4171 alcSetError(device
, ALC_INVALID_DEVICE
);
4176 if(device
) ALCdevice_DecRef(device
);
4179 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4181 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4182 alcSetError(device
, ALC_INVALID_DEVICE
);
4185 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4186 if((device
->Flags
&DEVICE_RUNNING
))
4187 V0(device
->Backend
,stop
)();
4188 device
->Flags
&= ~DEVICE_RUNNING
;
4191 if(device
) ALCdevice_DecRef(device
);
4194 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4196 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4197 alcSetError(device
, ALC_INVALID_DEVICE
);
4200 ALCenum err
= ALC_INVALID_VALUE
;
4201 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4202 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4203 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4205 if(err
!= ALC_NO_ERROR
)
4206 alcSetError(device
, err
);
4208 if(device
) ALCdevice_DecRef(device
);
4212 /************************************************
4213 * ALC loopback functions
4214 ************************************************/
4216 /* alcLoopbackOpenDeviceSOFT
4218 * Open a loopback device, for manual rendering.
4220 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4224 /* Make sure the device name, if specified, is us. */
4225 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4227 alcSetError(nullptr, ALC_INVALID_VALUE
);
4231 auto device
= new ALCdevice
{Loopback
};
4233 device
->SourcesMax
= 256;
4234 device
->AuxiliaryEffectSlotMax
= 64;
4235 device
->NumAuxSends
= DEFAULT_SENDS
;
4238 device
->NumUpdates
= 0;
4239 device
->UpdateSize
= 0;
4241 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4242 device
->FmtChans
= DevFmtChannelsDefault
;
4243 device
->FmtType
= DevFmtTypeDefault
;
4245 ConfigValueUInt(nullptr, nullptr, "sources", &device
->SourcesMax
);
4246 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4248 ConfigValueUInt(nullptr, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4249 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4250 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4252 if(ConfigValueInt(nullptr, nullptr, "sends", &device
->NumAuxSends
))
4253 device
->NumAuxSends
= clampi(
4254 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4257 device
->NumStereoSources
= 1;
4258 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4260 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(
4261 device
, ALCbackend_Loopback
);
4262 if(!device
->Backend
)
4265 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4269 // Open the "backend"
4270 V(device
->Backend
,open
)("Loopback");
4273 ALCdevice
*head
{DeviceList
.load()};
4275 device
->next
.store(head
, std::memory_order_relaxed
);
4276 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4279 TRACE("Created device %p\n", device
);
4283 /* alcIsRenderFormatSupportedSOFT
4285 * Determines if the loopback device supports the given format for rendering.
4287 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4289 ALCboolean ret
{ALC_FALSE
};
4291 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4292 alcSetError(device
, ALC_INVALID_DEVICE
);
4294 alcSetError(device
, ALC_INVALID_VALUE
);
4297 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4300 if(device
) ALCdevice_DecRef(device
);
4305 /* alcRenderSamplesSOFT
4307 * Renders some samples into a buffer, using the format last set by the
4308 * attributes given to alcCreateContext.
4310 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4312 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4313 alcSetError(device
, ALC_INVALID_DEVICE
);
4314 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4315 alcSetError(device
, ALC_INVALID_VALUE
);
4318 V0(device
->Backend
,lock
)();
4319 aluMixData(device
, buffer
, samples
);
4320 V0(device
->Backend
,unlock
)();
4322 if(device
) ALCdevice_DecRef(device
);
4326 /************************************************
4327 * ALC DSP pause/resume functions
4328 ************************************************/
4330 /* alcDevicePauseSOFT
4332 * Pause the DSP to stop audio processing.
4334 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4336 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4337 alcSetError(device
, ALC_INVALID_DEVICE
);
4340 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4341 if((device
->Flags
&DEVICE_RUNNING
))
4342 V0(device
->Backend
,stop
)();
4343 device
->Flags
&= ~DEVICE_RUNNING
;
4344 device
->Flags
|= DEVICE_PAUSED
;
4346 if(device
) ALCdevice_DecRef(device
);
4349 /* alcDeviceResumeSOFT
4351 * Resume the DSP to restart audio processing.
4353 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4355 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4356 alcSetError(device
, ALC_INVALID_DEVICE
);
4359 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4360 if((device
->Flags
&DEVICE_PAUSED
))
4362 device
->Flags
&= ~DEVICE_PAUSED
;
4363 if(device
->ContextList
.load() != nullptr)
4365 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4366 device
->Flags
|= DEVICE_RUNNING
;
4369 V0(device
->Backend
,lock
)();
4370 aluHandleDisconnect(device
, "Device start failure");
4371 V0(device
->Backend
,unlock
)();
4372 alcSetError(device
, ALC_INVALID_DEVICE
);
4377 if(device
) ALCdevice_DecRef(device
);
4381 /************************************************
4382 * ALC HRTF functions
4383 ************************************************/
4385 /* alcGetStringiSOFT
4387 * Gets a string parameter at the given index.
4389 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4391 const ALCchar
*str
{nullptr};
4393 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4394 alcSetError(device
, ALC_INVALID_DEVICE
);
4395 else switch(paramName
)
4397 case ALC_HRTF_SPECIFIER_SOFT
:
4398 if(index
>= 0 && (size_t)index
< device
->HrtfList
.size())
4399 str
= device
->HrtfList
[index
].name
.c_str();
4401 alcSetError(device
, ALC_INVALID_VALUE
);
4405 alcSetError(device
, ALC_INVALID_ENUM
);
4408 if(device
) ALCdevice_DecRef(device
);
4413 /* alcResetDeviceSOFT
4415 * Resets the given device output, using the specified attribute list.
4417 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4419 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4420 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4421 !device
->Connected
.load(std::memory_order_relaxed
))
4424 alcSetError(device
, ALC_INVALID_DEVICE
);
4425 if(device
) ALCdevice_DecRef(device
);
4428 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
4431 ALCenum err
{UpdateDeviceParams(device
, attribs
)};
4434 if(err
!= ALC_NO_ERROR
)
4436 alcSetError(device
, err
);
4437 if(err
== ALC_INVALID_DEVICE
)
4439 V0(device
->Backend
,lock
)();
4440 aluHandleDisconnect(device
, "Device start failure");
4441 V0(device
->Backend
,unlock
)();
4443 ALCdevice_DecRef(device
);
4446 ALCdevice_DecRef(device
);