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
55 #include "al/auxeffectslot.h"
56 #include "al/effect.h"
58 #include "al/filter.h"
59 #include "al/listener.h"
60 #include "al/source.h"
64 #include "alcontext.h"
67 #include "alnumeric.h"
68 #include "aloptional.h"
74 #include "bformatdec.h"
78 #include "devformat.h"
79 #include "effects/base.h"
80 #include "filters/nfc.h"
81 #include "filters/splitter.h"
82 #include "fpu_modes.h"
84 #include "inprogext.h"
85 #include "intrusive_ptr.h"
87 #include "mastering.h"
88 #include "opthelpers.h"
89 #include "ringbuffer.h"
92 #include "uhjfilter.h"
96 #include "backends/base.h"
97 #include "backends/null.h"
98 #include "backends/loopback.h"
100 #include "backends/jack.h"
102 #ifdef HAVE_PULSEAUDIO
103 #include "backends/pulseaudio.h"
106 #include "backends/alsa.h"
109 #include "backends/wasapi.h"
111 #ifdef HAVE_COREAUDIO
112 #include "backends/coreaudio.h"
115 #include "backends/opensl.h"
118 #include "backends/solaris.h"
121 #include "backends/sndio.h"
124 #include "backends/oss.h"
127 #include "backends/qsa.h"
130 #include "backends/dsound.h"
133 #include "backends/winmm.h"
135 #ifdef HAVE_PORTAUDIO
136 #include "backends/portaudio.h"
139 #include "backends/sdl2.h"
142 #include "backends/wave.h"
148 using namespace std::placeholders
;
149 using std::chrono::seconds
;
150 using std::chrono::nanoseconds
;
153 /************************************************
155 ************************************************/
158 BackendFactory
& (*getFactory
)(void);
161 BackendInfo BackendList
[] = {
163 { "jack", JackBackendFactory::getFactory
},
165 #ifdef HAVE_PULSEAUDIO
166 { "pulse", PulseBackendFactory::getFactory
},
169 { "alsa", AlsaBackendFactory::getFactory
},
172 { "wasapi", WasapiBackendFactory::getFactory
},
174 #ifdef HAVE_COREAUDIO
175 { "core", CoreAudioBackendFactory::getFactory
},
178 { "opensl", OSLBackendFactory::getFactory
},
181 { "solaris", SolarisBackendFactory::getFactory
},
184 { "sndio", SndIOBackendFactory::getFactory
},
187 { "oss", OSSBackendFactory::getFactory
},
190 { "qsa", QSABackendFactory::getFactory
},
193 { "dsound", DSoundBackendFactory::getFactory
},
196 { "winmm", WinMMBackendFactory::getFactory
},
198 #ifdef HAVE_PORTAUDIO
199 { "port", PortBackendFactory::getFactory
},
202 { "sdl2", SDL2BackendFactory::getFactory
},
205 { "null", NullBackendFactory::getFactory
},
207 { "wave", WaveBackendFactory::getFactory
},
210 auto BackendListEnd
= std::end(BackendList
);
212 BackendFactory
*PlaybackFactory
{};
213 BackendFactory
*CaptureFactory
{};
216 /************************************************
217 * Functions, enums, and errors
218 ************************************************/
219 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
221 const ALCchar
*funcName
;
224 DECL(alcCreateContext
),
225 DECL(alcMakeContextCurrent
),
226 DECL(alcProcessContext
),
227 DECL(alcSuspendContext
),
228 DECL(alcDestroyContext
),
229 DECL(alcGetCurrentContext
),
230 DECL(alcGetContextsDevice
),
232 DECL(alcCloseDevice
),
234 DECL(alcIsExtensionPresent
),
235 DECL(alcGetProcAddress
),
236 DECL(alcGetEnumValue
),
238 DECL(alcGetIntegerv
),
239 DECL(alcCaptureOpenDevice
),
240 DECL(alcCaptureCloseDevice
),
241 DECL(alcCaptureStart
),
242 DECL(alcCaptureStop
),
243 DECL(alcCaptureSamples
),
245 DECL(alcSetThreadContext
),
246 DECL(alcGetThreadContext
),
248 DECL(alcLoopbackOpenDeviceSOFT
),
249 DECL(alcIsRenderFormatSupportedSOFT
),
250 DECL(alcRenderSamplesSOFT
),
252 DECL(alcDevicePauseSOFT
),
253 DECL(alcDeviceResumeSOFT
),
255 DECL(alcGetStringiSOFT
),
256 DECL(alcResetDeviceSOFT
),
258 DECL(alcGetInteger64vSOFT
),
273 DECL(alIsExtensionPresent
),
274 DECL(alGetProcAddress
),
275 DECL(alGetEnumValue
),
282 DECL(alGetListenerf
),
283 DECL(alGetListener3f
),
284 DECL(alGetListenerfv
),
285 DECL(alGetListeneri
),
286 DECL(alGetListener3i
),
287 DECL(alGetListeneriv
),
289 DECL(alDeleteSources
),
305 DECL(alSourceRewindv
),
306 DECL(alSourcePausev
),
309 DECL(alSourceRewind
),
311 DECL(alSourceQueueBuffers
),
312 DECL(alSourceUnqueueBuffers
),
314 DECL(alDeleteBuffers
),
329 DECL(alDopplerFactor
),
330 DECL(alDopplerVelocity
),
331 DECL(alSpeedOfSound
),
332 DECL(alDistanceModel
),
335 DECL(alDeleteFilters
),
346 DECL(alDeleteEffects
),
356 DECL(alGenAuxiliaryEffectSlots
),
357 DECL(alDeleteAuxiliaryEffectSlots
),
358 DECL(alIsAuxiliaryEffectSlot
),
359 DECL(alAuxiliaryEffectSloti
),
360 DECL(alAuxiliaryEffectSlotiv
),
361 DECL(alAuxiliaryEffectSlotf
),
362 DECL(alAuxiliaryEffectSlotfv
),
363 DECL(alGetAuxiliaryEffectSloti
),
364 DECL(alGetAuxiliaryEffectSlotiv
),
365 DECL(alGetAuxiliaryEffectSlotf
),
366 DECL(alGetAuxiliaryEffectSlotfv
),
368 DECL(alDeferUpdatesSOFT
),
369 DECL(alProcessUpdatesSOFT
),
372 DECL(alSource3dSOFT
),
373 DECL(alSourcedvSOFT
),
374 DECL(alGetSourcedSOFT
),
375 DECL(alGetSource3dSOFT
),
376 DECL(alGetSourcedvSOFT
),
377 DECL(alSourcei64SOFT
),
378 DECL(alSource3i64SOFT
),
379 DECL(alSourcei64vSOFT
),
380 DECL(alGetSourcei64SOFT
),
381 DECL(alGetSource3i64SOFT
),
382 DECL(alGetSourcei64vSOFT
),
384 DECL(alGetStringiSOFT
),
386 DECL(alBufferStorageSOFT
),
387 DECL(alMapBufferSOFT
),
388 DECL(alUnmapBufferSOFT
),
389 DECL(alFlushMappedBufferSOFT
),
391 DECL(alEventControlSOFT
),
392 DECL(alEventCallbackSOFT
),
393 DECL(alGetPointerSOFT
),
394 DECL(alGetPointervSOFT
),
398 #define DECL(x) { #x, (x) }
400 const ALCchar
*enumName
;
402 } alcEnumerations
[] = {
407 DECL(ALC_MAJOR_VERSION
),
408 DECL(ALC_MINOR_VERSION
),
409 DECL(ALC_ATTRIBUTES_SIZE
),
410 DECL(ALC_ALL_ATTRIBUTES
),
411 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
412 DECL(ALC_DEVICE_SPECIFIER
),
413 DECL(ALC_ALL_DEVICES_SPECIFIER
),
414 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
415 DECL(ALC_EXTENSIONS
),
419 DECL(ALC_MONO_SOURCES
),
420 DECL(ALC_STEREO_SOURCES
),
421 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
422 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
423 DECL(ALC_CAPTURE_SAMPLES
),
426 DECL(ALC_EFX_MAJOR_VERSION
),
427 DECL(ALC_EFX_MINOR_VERSION
),
428 DECL(ALC_MAX_AUXILIARY_SENDS
),
430 DECL(ALC_FORMAT_CHANNELS_SOFT
),
431 DECL(ALC_FORMAT_TYPE_SOFT
),
434 DECL(ALC_STEREO_SOFT
),
436 DECL(ALC_5POINT1_SOFT
),
437 DECL(ALC_6POINT1_SOFT
),
438 DECL(ALC_7POINT1_SOFT
),
439 DECL(ALC_BFORMAT3D_SOFT
),
442 DECL(ALC_UNSIGNED_BYTE_SOFT
),
443 DECL(ALC_SHORT_SOFT
),
444 DECL(ALC_UNSIGNED_SHORT_SOFT
),
446 DECL(ALC_UNSIGNED_INT_SOFT
),
447 DECL(ALC_FLOAT_SOFT
),
450 DECL(ALC_DONT_CARE_SOFT
),
451 DECL(ALC_HRTF_STATUS_SOFT
),
452 DECL(ALC_HRTF_DISABLED_SOFT
),
453 DECL(ALC_HRTF_ENABLED_SOFT
),
454 DECL(ALC_HRTF_DENIED_SOFT
),
455 DECL(ALC_HRTF_REQUIRED_SOFT
),
456 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
457 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
458 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
459 DECL(ALC_HRTF_SPECIFIER_SOFT
),
460 DECL(ALC_HRTF_ID_SOFT
),
462 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
463 DECL(ALC_AMBISONIC_SCALING_SOFT
),
464 DECL(ALC_AMBISONIC_ORDER_SOFT
),
470 DECL(ALC_OUTPUT_LIMITER_SOFT
),
473 DECL(ALC_INVALID_DEVICE
),
474 DECL(ALC_INVALID_CONTEXT
),
475 DECL(ALC_INVALID_ENUM
),
476 DECL(ALC_INVALID_VALUE
),
477 DECL(ALC_OUT_OF_MEMORY
),
485 DECL(AL_SOURCE_RELATIVE
),
486 DECL(AL_CONE_INNER_ANGLE
),
487 DECL(AL_CONE_OUTER_ANGLE
),
497 DECL(AL_ORIENTATION
),
498 DECL(AL_REFERENCE_DISTANCE
),
499 DECL(AL_ROLLOFF_FACTOR
),
500 DECL(AL_CONE_OUTER_GAIN
),
501 DECL(AL_MAX_DISTANCE
),
503 DECL(AL_SAMPLE_OFFSET
),
504 DECL(AL_BYTE_OFFSET
),
505 DECL(AL_SOURCE_TYPE
),
508 DECL(AL_UNDETERMINED
),
509 DECL(AL_METERS_PER_UNIT
),
510 DECL(AL_LOOP_POINTS_SOFT
),
511 DECL(AL_DIRECT_CHANNELS_SOFT
),
513 DECL(AL_DIRECT_FILTER
),
514 DECL(AL_AUXILIARY_SEND_FILTER
),
515 DECL(AL_AIR_ABSORPTION_FACTOR
),
516 DECL(AL_ROOM_ROLLOFF_FACTOR
),
517 DECL(AL_CONE_OUTER_GAINHF
),
518 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
519 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
520 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
522 DECL(AL_SOURCE_STATE
),
528 DECL(AL_BUFFERS_QUEUED
),
529 DECL(AL_BUFFERS_PROCESSED
),
531 DECL(AL_FORMAT_MONO8
),
532 DECL(AL_FORMAT_MONO16
),
533 DECL(AL_FORMAT_MONO_FLOAT32
),
534 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
535 DECL(AL_FORMAT_STEREO8
),
536 DECL(AL_FORMAT_STEREO16
),
537 DECL(AL_FORMAT_STEREO_FLOAT32
),
538 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
539 DECL(AL_FORMAT_MONO_IMA4
),
540 DECL(AL_FORMAT_STEREO_IMA4
),
541 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
542 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
543 DECL(AL_FORMAT_QUAD8_LOKI
),
544 DECL(AL_FORMAT_QUAD16_LOKI
),
545 DECL(AL_FORMAT_QUAD8
),
546 DECL(AL_FORMAT_QUAD16
),
547 DECL(AL_FORMAT_QUAD32
),
548 DECL(AL_FORMAT_51CHN8
),
549 DECL(AL_FORMAT_51CHN16
),
550 DECL(AL_FORMAT_51CHN32
),
551 DECL(AL_FORMAT_61CHN8
),
552 DECL(AL_FORMAT_61CHN16
),
553 DECL(AL_FORMAT_61CHN32
),
554 DECL(AL_FORMAT_71CHN8
),
555 DECL(AL_FORMAT_71CHN16
),
556 DECL(AL_FORMAT_71CHN32
),
557 DECL(AL_FORMAT_REAR8
),
558 DECL(AL_FORMAT_REAR16
),
559 DECL(AL_FORMAT_REAR32
),
560 DECL(AL_FORMAT_MONO_MULAW
),
561 DECL(AL_FORMAT_MONO_MULAW_EXT
),
562 DECL(AL_FORMAT_STEREO_MULAW
),
563 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
564 DECL(AL_FORMAT_QUAD_MULAW
),
565 DECL(AL_FORMAT_51CHN_MULAW
),
566 DECL(AL_FORMAT_61CHN_MULAW
),
567 DECL(AL_FORMAT_71CHN_MULAW
),
568 DECL(AL_FORMAT_REAR_MULAW
),
569 DECL(AL_FORMAT_MONO_ALAW_EXT
),
570 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
572 DECL(AL_FORMAT_BFORMAT2D_8
),
573 DECL(AL_FORMAT_BFORMAT2D_16
),
574 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
575 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
576 DECL(AL_FORMAT_BFORMAT3D_8
),
577 DECL(AL_FORMAT_BFORMAT3D_16
),
578 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
579 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
585 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
586 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
588 DECL(AL_SOURCE_RADIUS
),
590 DECL(AL_STEREO_ANGLES
),
597 DECL(AL_INVALID_NAME
),
598 DECL(AL_INVALID_ENUM
),
599 DECL(AL_INVALID_VALUE
),
600 DECL(AL_INVALID_OPERATION
),
601 DECL(AL_OUT_OF_MEMORY
),
608 DECL(AL_DOPPLER_FACTOR
),
609 DECL(AL_DOPPLER_VELOCITY
),
610 DECL(AL_DISTANCE_MODEL
),
611 DECL(AL_SPEED_OF_SOUND
),
612 DECL(AL_SOURCE_DISTANCE_MODEL
),
613 DECL(AL_DEFERRED_UPDATES_SOFT
),
614 DECL(AL_GAIN_LIMIT_SOFT
),
616 DECL(AL_INVERSE_DISTANCE
),
617 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
618 DECL(AL_LINEAR_DISTANCE
),
619 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
620 DECL(AL_EXPONENT_DISTANCE
),
621 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
623 DECL(AL_FILTER_TYPE
),
624 DECL(AL_FILTER_NULL
),
625 DECL(AL_FILTER_LOWPASS
),
626 DECL(AL_FILTER_HIGHPASS
),
627 DECL(AL_FILTER_BANDPASS
),
629 DECL(AL_LOWPASS_GAIN
),
630 DECL(AL_LOWPASS_GAINHF
),
632 DECL(AL_HIGHPASS_GAIN
),
633 DECL(AL_HIGHPASS_GAINLF
),
635 DECL(AL_BANDPASS_GAIN
),
636 DECL(AL_BANDPASS_GAINHF
),
637 DECL(AL_BANDPASS_GAINLF
),
639 DECL(AL_EFFECT_TYPE
),
640 DECL(AL_EFFECT_NULL
),
641 DECL(AL_EFFECT_REVERB
),
642 DECL(AL_EFFECT_EAXREVERB
),
643 DECL(AL_EFFECT_CHORUS
),
644 DECL(AL_EFFECT_DISTORTION
),
645 DECL(AL_EFFECT_ECHO
),
646 DECL(AL_EFFECT_FLANGER
),
647 DECL(AL_EFFECT_PITCH_SHIFTER
),
648 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
649 DECL(AL_EFFECT_VOCAL_MORPHER
),
650 DECL(AL_EFFECT_RING_MODULATOR
),
651 DECL(AL_EFFECT_AUTOWAH
),
652 DECL(AL_EFFECT_COMPRESSOR
),
653 DECL(AL_EFFECT_EQUALIZER
),
654 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
655 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
657 DECL(AL_EFFECTSLOT_EFFECT
),
658 DECL(AL_EFFECTSLOT_GAIN
),
659 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
660 DECL(AL_EFFECTSLOT_NULL
),
662 DECL(AL_EAXREVERB_DENSITY
),
663 DECL(AL_EAXREVERB_DIFFUSION
),
664 DECL(AL_EAXREVERB_GAIN
),
665 DECL(AL_EAXREVERB_GAINHF
),
666 DECL(AL_EAXREVERB_GAINLF
),
667 DECL(AL_EAXREVERB_DECAY_TIME
),
668 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
669 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
670 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
671 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
672 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
673 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
674 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
675 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
676 DECL(AL_EAXREVERB_ECHO_TIME
),
677 DECL(AL_EAXREVERB_ECHO_DEPTH
),
678 DECL(AL_EAXREVERB_MODULATION_TIME
),
679 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
680 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
681 DECL(AL_EAXREVERB_HFREFERENCE
),
682 DECL(AL_EAXREVERB_LFREFERENCE
),
683 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
684 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
686 DECL(AL_REVERB_DENSITY
),
687 DECL(AL_REVERB_DIFFUSION
),
688 DECL(AL_REVERB_GAIN
),
689 DECL(AL_REVERB_GAINHF
),
690 DECL(AL_REVERB_DECAY_TIME
),
691 DECL(AL_REVERB_DECAY_HFRATIO
),
692 DECL(AL_REVERB_REFLECTIONS_GAIN
),
693 DECL(AL_REVERB_REFLECTIONS_DELAY
),
694 DECL(AL_REVERB_LATE_REVERB_GAIN
),
695 DECL(AL_REVERB_LATE_REVERB_DELAY
),
696 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
697 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
698 DECL(AL_REVERB_DECAY_HFLIMIT
),
700 DECL(AL_CHORUS_WAVEFORM
),
701 DECL(AL_CHORUS_PHASE
),
702 DECL(AL_CHORUS_RATE
),
703 DECL(AL_CHORUS_DEPTH
),
704 DECL(AL_CHORUS_FEEDBACK
),
705 DECL(AL_CHORUS_DELAY
),
707 DECL(AL_DISTORTION_EDGE
),
708 DECL(AL_DISTORTION_GAIN
),
709 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
710 DECL(AL_DISTORTION_EQCENTER
),
711 DECL(AL_DISTORTION_EQBANDWIDTH
),
714 DECL(AL_ECHO_LRDELAY
),
715 DECL(AL_ECHO_DAMPING
),
716 DECL(AL_ECHO_FEEDBACK
),
717 DECL(AL_ECHO_SPREAD
),
719 DECL(AL_FLANGER_WAVEFORM
),
720 DECL(AL_FLANGER_PHASE
),
721 DECL(AL_FLANGER_RATE
),
722 DECL(AL_FLANGER_DEPTH
),
723 DECL(AL_FLANGER_FEEDBACK
),
724 DECL(AL_FLANGER_DELAY
),
726 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
727 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
728 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
730 DECL(AL_RING_MODULATOR_FREQUENCY
),
731 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
732 DECL(AL_RING_MODULATOR_WAVEFORM
),
734 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
735 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
737 DECL(AL_COMPRESSOR_ONOFF
),
739 DECL(AL_EQUALIZER_LOW_GAIN
),
740 DECL(AL_EQUALIZER_LOW_CUTOFF
),
741 DECL(AL_EQUALIZER_MID1_GAIN
),
742 DECL(AL_EQUALIZER_MID1_CENTER
),
743 DECL(AL_EQUALIZER_MID1_WIDTH
),
744 DECL(AL_EQUALIZER_MID2_GAIN
),
745 DECL(AL_EQUALIZER_MID2_CENTER
),
746 DECL(AL_EQUALIZER_MID2_WIDTH
),
747 DECL(AL_EQUALIZER_HIGH_GAIN
),
748 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
750 DECL(AL_DEDICATED_GAIN
),
752 DECL(AL_AUTOWAH_ATTACK_TIME
),
753 DECL(AL_AUTOWAH_RELEASE_TIME
),
754 DECL(AL_AUTOWAH_RESONANCE
),
755 DECL(AL_AUTOWAH_PEAK_GAIN
),
757 DECL(AL_VOCAL_MORPHER_PHONEMEA
),
758 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB
),
760 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
761 DECL(AL_VOCAL_MORPHER_WAVEFORM
),
762 DECL(AL_VOCAL_MORPHER_RATE
),
764 DECL(AL_NUM_RESAMPLERS_SOFT
),
765 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
766 DECL(AL_SOURCE_RESAMPLER_SOFT
),
767 DECL(AL_RESAMPLER_NAME_SOFT
),
769 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
772 DECL(AL_MAP_READ_BIT_SOFT
),
773 DECL(AL_MAP_WRITE_BIT_SOFT
),
774 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
775 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
777 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
778 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
779 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
780 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
781 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
782 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
783 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
787 constexpr ALCchar alcNoError
[] = "No Error";
788 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
789 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
790 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
791 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
792 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
795 /************************************************
797 ************************************************/
799 /* Enumerated device names */
800 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
802 std::string alcAllDevicesList
;
803 std::string alcCaptureDeviceList
;
805 /* Default is always the first in the list */
806 al::string alcDefaultAllDevicesSpecifier
;
807 al::string alcCaptureDefaultDeviceSpecifier
;
809 /* Default context extensions */
810 constexpr ALchar alExtList
[] =
814 "AL_EXT_EXPONENT_DISTANCE "
817 "AL_EXT_LINEAR_DISTANCE "
820 "AL_EXT_MULAW_BFORMAT "
821 "AL_EXT_MULAW_MCFORMATS "
823 "AL_EXT_source_distance_model "
824 "AL_EXT_SOURCE_RADIUS "
825 "AL_EXT_STEREO_ANGLES "
826 "AL_LOKI_quadriphonic "
827 "AL_SOFT_block_alignment "
828 "AL_SOFT_deferred_updates "
829 "AL_SOFT_direct_channels "
830 "AL_SOFTX_effect_chain "
832 "AL_SOFTX_filter_gain_ex "
833 "AL_SOFT_gain_clamp_ex "
834 "AL_SOFT_loop_points "
835 "AL_SOFTX_map_buffer "
837 "AL_SOFT_source_latency "
838 "AL_SOFT_source_length "
839 "AL_SOFT_source_resampler "
840 "AL_SOFT_source_spatialize";
842 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
844 /* Thread-local current context */
845 void ReleaseThreadCtx(ALCcontext
*context
)
847 const bool result
{context
->releaseIfNoDelete()};
848 ERR("Context %p current for thread being destroyed%s!\n",
849 decltype(std::declval
<void*>()){context
}, result
? "" : ", leak detected");
853 ALCcontext
*ctx
{nullptr};
859 ReleaseThreadCtx(ctx
);
863 ALCcontext
*get() const noexcept
{ return ctx
; }
864 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
866 thread_local ThreadCtx LocalContext
;
867 /* Process-wide current context */
868 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
870 /* Flag to trap ALC device errors */
871 bool TrapALCError
{false};
873 /* One-time configuration init control */
874 std::once_flag alc_config_once
{};
876 /* Default effect that applies to sources that don't have an effect on send 0 */
877 ALeffect DefaultEffect
;
879 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
882 bool SuspendDefers
{true};
885 /************************************************
887 ************************************************/
888 constexpr ALCchar alcNoDeviceExtList
[] =
889 "ALC_ENUMERATE_ALL_EXT "
890 "ALC_ENUMERATION_EXT "
892 "ALC_EXT_thread_local_context "
894 constexpr ALCchar alcExtensionList
[] =
895 "ALC_ENUMERATE_ALL_EXT "
896 "ALC_ENUMERATION_EXT "
899 "ALC_EXT_disconnect "
901 "ALC_EXT_thread_local_context "
902 "ALC_SOFT_device_clock "
905 "ALC_SOFT_output_limiter "
906 "ALC_SOFT_pause_device";
907 constexpr ALCint alcMajorVersion
= 1;
908 constexpr ALCint alcMinorVersion
= 1;
910 constexpr ALCint alcEFXMajorVersion
= 1;
911 constexpr ALCint alcEFXMinorVersion
= 0;
914 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
915 * globally as a sharable object. MSVC warns that a zero-sized array will have
916 * zero objects here, so silence that.
919 MVSDIAGNOSTIC(warning(disable
: 4815))
920 al::FlexArray
<ALCcontext
*> EmptyContextArray
{0u};
924 using DeviceRef
= al::intrusive_ptr
<ALCdevice
>;
927 /************************************************
929 ************************************************/
930 al::vector
<DeviceRef
> DeviceList
;
931 al::vector
<ContextRef
> ContextList
;
933 std::recursive_mutex ListLock
;
936 void alc_initconfig(void)
938 if(auto loglevel
= al::getenv("ALSOFT_LOGLEVEL"))
940 long lvl
= strtol(loglevel
->c_str(), nullptr, 0);
941 if(lvl
>= NoLog
&& lvl
<= LogRef
)
942 gLogLevel
= static_cast<LogLevel
>(lvl
);
945 if(auto logfile
= al::getenv("ALSOFT_LOGFILE"))
948 std::wstring wname
{utf8_to_wstr(logfile
->c_str())};
949 FILE *logf
{_wfopen(wname
.c_str(), L
"wt")};
951 FILE *logf
{fopen(logfile
->c_str(), "wt")};
953 if(logf
) gLogFile
= logf
;
954 else ERR("Failed to open log file '%s'\n", logfile
->c_str());
957 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
, ALSOFT_GIT_COMMIT_HASH
,
961 if(std::begin(BackendList
) == BackendListEnd
)
965 const al::span
<const BackendInfo
> infos
{std::begin(BackendList
), BackendListEnd
};
966 names
+= infos
[0].name
;
967 for(const auto &backend
: infos
.subspan(1))
970 names
+= backend
.name
;
973 TRACE("Supported backends: %s\n", names
.c_str());
977 if(auto suspendmode
= al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
979 if(al::strcasecmp(suspendmode
->c_str(), "ignore") == 0)
981 SuspendDefers
= false;
982 TRACE("Selected context suspend behavior, \"ignore\"\n");
985 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode
->c_str());
989 #if defined(HAVE_SSE4_1)
990 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
991 #elif defined(HAVE_SSE3)
992 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
993 #elif defined(HAVE_SSE2)
994 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
995 #elif defined(HAVE_SSE)
996 capfilter
|= CPU_CAP_SSE
;
999 capfilter
|= CPU_CAP_NEON
;
1001 if(auto cpuopt
= ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1003 const char *str
{cpuopt
->c_str()};
1004 if(al::strcasecmp(str
, "all") == 0)
1008 const char *next
= str
;
1011 while(isspace(str
[0]))
1013 next
= strchr(str
, ',');
1015 if(!str
[0] || str
[0] == ',')
1018 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1019 while(len
> 0 && isspace(str
[len
-1]))
1021 if(len
== 3 && al::strncasecmp(str
, "sse", len
) == 0)
1022 capfilter
&= ~CPU_CAP_SSE
;
1023 else if(len
== 4 && al::strncasecmp(str
, "sse2", len
) == 0)
1024 capfilter
&= ~CPU_CAP_SSE2
;
1025 else if(len
== 4 && al::strncasecmp(str
, "sse3", len
) == 0)
1026 capfilter
&= ~CPU_CAP_SSE3
;
1027 else if(len
== 6 && al::strncasecmp(str
, "sse4.1", len
) == 0)
1028 capfilter
&= ~CPU_CAP_SSE4_1
;
1029 else if(len
== 4 && al::strncasecmp(str
, "neon", len
) == 0)
1030 capfilter
&= ~CPU_CAP_NEON
;
1032 WARN("Invalid CPU extension \"%s\"\n", str
);
1036 FillCPUCaps(capfilter
);
1039 #define DEF_MIXER_PRIO 1
1041 #define DEF_MIXER_PRIO 0
1043 RTPrioLevel
= ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO
);
1044 #undef DEF_MIXER_PRIO
1049 auto traperr
= al::getenv("ALSOFT_TRAP_ERROR");
1050 if(traperr
&& (al::strcasecmp(traperr
->c_str(), "true") == 0
1051 || std::strtol(traperr
->c_str(), nullptr, 0) == 1))
1054 TrapALCError
= true;
1058 traperr
= al::getenv("ALSOFT_TRAP_AL_ERROR");
1060 TrapALError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1061 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1063 TrapALError
= !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1065 traperr
= al::getenv("ALSOFT_TRAP_ALC_ERROR");
1067 TrapALCError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1068 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1070 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1073 if(auto boostopt
= ConfigValueFloat(nullptr, "reverb", "boost"))
1075 const float valf
{std::isfinite(*boostopt
) ? clampf(*boostopt
, -24.0f
, 24.0f
) : 0.0f
};
1076 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1079 auto devopt
= al::getenv("ALSOFT_DRIVERS");
1080 if(devopt
|| (devopt
=ConfigValueStr(nullptr, nullptr, "drivers")))
1082 auto backendlist_cur
= std::begin(BackendList
);
1085 const char *next
{devopt
->c_str()};
1087 const char *devs
{next
};
1088 while(isspace(devs
[0]))
1090 next
= strchr(devs
, ',');
1092 const bool delitem
{devs
[0] == '-'};
1093 if(devs
[0] == '-') devs
++;
1095 if(!devs
[0] || devs
[0] == ',')
1102 size_t len
{next
? (static_cast<size_t>(next
-devs
)) : strlen(devs
)};
1103 while(len
> 0 && isspace(devs
[len
-1])) --len
;
1105 /* HACK: For backwards compatibility, convert backend references of
1106 * mmdevapi to wasapi. This should eventually be removed.
1108 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1115 auto find_backend
= [devs
,len
](const BackendInfo
&backend
) -> bool
1116 { return len
== strlen(backend
.name
) && strncmp(backend
.name
, devs
, len
) == 0; };
1117 auto this_backend
= std::find_if(std::begin(BackendList
), BackendListEnd
,
1120 if(this_backend
== BackendListEnd
)
1124 BackendListEnd
= std::move(this_backend
+1, BackendListEnd
, this_backend
);
1126 backendlist_cur
= std::rotate(backendlist_cur
, this_backend
, this_backend
+1);
1130 BackendListEnd
= backendlist_cur
;
1133 auto init_backend
= [](BackendInfo
&backend
) -> bool
1135 if(PlaybackFactory
&& CaptureFactory
)
1138 BackendFactory
&factory
= backend
.getFactory();
1141 WARN("Failed to initialize backend \"%s\"\n", backend
.name
);
1145 TRACE("Initialized backend \"%s\"\n", backend
.name
);
1146 if(!PlaybackFactory
&& factory
.querySupport(BackendType::Playback
))
1148 PlaybackFactory
= &factory
;
1149 TRACE("Added \"%s\" for playback\n", backend
.name
);
1151 if(!CaptureFactory
&& factory
.querySupport(BackendType::Capture
))
1153 CaptureFactory
= &factory
;
1154 TRACE("Added \"%s\" for capture\n", backend
.name
);
1158 BackendListEnd
= std::remove_if(std::begin(BackendList
), BackendListEnd
, init_backend
);
1160 LoopbackBackendFactory::getFactory().init();
1162 if(!PlaybackFactory
)
1163 WARN("No playback backend available!\n");
1165 WARN("No capture backend available!\n");
1167 if(auto exclopt
= ConfigValueStr(nullptr, nullptr, "excludefx"))
1169 const char *next
{exclopt
->c_str()};
1171 const char *str
{next
};
1172 next
= strchr(str
, ',');
1174 if(!str
[0] || next
== str
)
1177 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1178 for(const EffectList
&effectitem
: gEffectList
)
1180 if(len
== strlen(effectitem
.name
) &&
1181 strncmp(effectitem
.name
, str
, len
) == 0)
1182 DisabledEffects
[effectitem
.type
] = AL_TRUE
;
1187 InitEffect(&DefaultEffect
);
1188 auto defrevopt
= al::getenv("ALSOFT_DEFAULT_REVERB");
1189 if(defrevopt
|| (defrevopt
=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1190 LoadReverbPreset(defrevopt
->c_str(), &DefaultEffect
);
1192 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1195 /************************************************
1196 * Device enumeration
1197 ************************************************/
1198 void ProbeAllDevicesList()
1202 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1203 alcAllDevicesList
.clear();
1205 PlaybackFactory
->probe(DevProbe::Playback
, &alcAllDevicesList
);
1207 void ProbeCaptureDeviceList()
1211 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1212 alcCaptureDeviceList
.clear();
1214 CaptureFactory
->probe(DevProbe::Capture
, &alcCaptureDeviceList
);
1219 /* Mixing thread piority level */
1222 FILE *gLogFile
{stderr
};
1224 LogLevel gLogLevel
{LogWarning
};
1226 LogLevel gLogLevel
{LogError
};
1229 /************************************************
1230 * Library initialization
1231 ************************************************/
1232 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1233 BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID
/*reserved*/)
1237 case DLL_PROCESS_ATTACH
:
1238 /* Pin the DLL so we won't get unloaded until the process terminates */
1239 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
1240 reinterpret_cast<WCHAR
*>(module
), &module
);
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar
*DevFmtTypeString(DevFmtType type
) noexcept
1254 case DevFmtByte
: return "Signed Byte";
1255 case DevFmtUByte
: return "Unsigned Byte";
1256 case DevFmtShort
: return "Signed Short";
1257 case DevFmtUShort
: return "Unsigned Short";
1258 case DevFmtInt
: return "Signed Int";
1259 case DevFmtUInt
: return "Unsigned Int";
1260 case DevFmtFloat
: return "Float";
1262 return "(unknown type)";
1264 const ALCchar
*DevFmtChannelsString(DevFmtChannels chans
) noexcept
1268 case DevFmtMono
: return "Mono";
1269 case DevFmtStereo
: return "Stereo";
1270 case DevFmtQuad
: return "Quadraphonic";
1271 case DevFmtX51
: return "5.1 Surround";
1272 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1273 case DevFmtX61
: return "6.1 Surround";
1274 case DevFmtX71
: return "7.1 Surround";
1275 case DevFmtAmbi3D
: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALuint
BytesFromDevFmt(DevFmtType type
) noexcept
1284 case DevFmtByte
: return sizeof(ALbyte
);
1285 case DevFmtUByte
: return sizeof(ALubyte
);
1286 case DevFmtShort
: return sizeof(ALshort
);
1287 case DevFmtUShort
: return sizeof(ALushort
);
1288 case DevFmtInt
: return sizeof(ALint
);
1289 case DevFmtUInt
: return sizeof(ALuint
);
1290 case DevFmtFloat
: return sizeof(ALfloat
);
1294 ALuint
ChannelsFromDevFmt(DevFmtChannels chans
, ALuint ambiorder
) noexcept
1298 case DevFmtMono
: return 1;
1299 case DevFmtStereo
: return 2;
1300 case DevFmtQuad
: return 4;
1301 case DevFmtX51
: return 6;
1302 case DevFmtX51Rear
: return 6;
1303 case DevFmtX61
: return 7;
1304 case DevFmtX71
: return 8;
1305 case DevFmtAmbi3D
: return (ambiorder
+1) * (ambiorder
+1);
1310 struct DevFmtPair
{ DevFmtChannels chans
; DevFmtType type
; };
1311 static al::optional
<DevFmtPair
> DecomposeDevFormat(ALenum format
)
1313 static const struct {
1315 DevFmtChannels channels
;
1318 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1319 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1320 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1322 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1323 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1324 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1326 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1327 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1328 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1330 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1331 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1332 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1334 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1335 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1336 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1338 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1339 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1340 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1343 for(const auto &item
: list
)
1345 if(item
.format
== format
)
1346 return al::make_optional(DevFmtPair
{item
.channels
, item
.type
});
1352 static ALCboolean
IsValidALCType(ALCenum type
)
1357 case ALC_UNSIGNED_BYTE_SOFT
:
1358 case ALC_SHORT_SOFT
:
1359 case ALC_UNSIGNED_SHORT_SOFT
:
1361 case ALC_UNSIGNED_INT_SOFT
:
1362 case ALC_FLOAT_SOFT
:
1368 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1373 case ALC_STEREO_SOFT
:
1375 case ALC_5POINT1_SOFT
:
1376 case ALC_6POINT1_SOFT
:
1377 case ALC_7POINT1_SOFT
:
1378 case ALC_BFORMAT3D_SOFT
:
1384 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1395 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1407 /************************************************
1408 * Miscellaneous ALC helpers
1409 ************************************************/
1411 /* SetDefaultWFXChannelOrder
1413 * Sets the default channel order used by WaveFormatEx.
1415 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1417 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1419 switch(device
->FmtChans
)
1422 device
->RealOut
.ChannelIndex
[FrontCenter
] = 0;
1425 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1426 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1429 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1430 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1431 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1432 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1435 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1436 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1437 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1438 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1439 device
->RealOut
.ChannelIndex
[SideLeft
] = 4;
1440 device
->RealOut
.ChannelIndex
[SideRight
] = 5;
1443 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1444 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1445 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1446 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1447 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1448 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1451 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1452 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1453 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1454 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1455 device
->RealOut
.ChannelIndex
[BackCenter
] = 4;
1456 device
->RealOut
.ChannelIndex
[SideLeft
] = 5;
1457 device
->RealOut
.ChannelIndex
[SideRight
] = 6;
1460 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1461 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1462 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1463 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1464 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1465 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1466 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1467 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1470 device
->RealOut
.ChannelIndex
[Aux0
] = 0;
1471 if(device
->mAmbiOrder
> 0)
1473 device
->RealOut
.ChannelIndex
[Aux1
] = 1;
1474 device
->RealOut
.ChannelIndex
[Aux2
] = 2;
1475 device
->RealOut
.ChannelIndex
[Aux3
] = 3;
1477 if(device
->mAmbiOrder
> 1)
1479 device
->RealOut
.ChannelIndex
[Aux4
] = 4;
1480 device
->RealOut
.ChannelIndex
[Aux5
] = 5;
1481 device
->RealOut
.ChannelIndex
[Aux6
] = 6;
1482 device
->RealOut
.ChannelIndex
[Aux7
] = 7;
1483 device
->RealOut
.ChannelIndex
[Aux8
] = 8;
1485 if(device
->mAmbiOrder
> 2)
1487 device
->RealOut
.ChannelIndex
[Aux9
] = 9;
1488 device
->RealOut
.ChannelIndex
[Aux10
] = 10;
1489 device
->RealOut
.ChannelIndex
[Aux11
] = 11;
1490 device
->RealOut
.ChannelIndex
[Aux12
] = 12;
1491 device
->RealOut
.ChannelIndex
[Aux13
] = 13;
1492 device
->RealOut
.ChannelIndex
[Aux14
] = 14;
1493 device
->RealOut
.ChannelIndex
[Aux15
] = 15;
1499 /* SetDefaultChannelOrder
1501 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1503 void SetDefaultChannelOrder(ALCdevice
*device
)
1505 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1507 switch(device
->FmtChans
)
1510 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1511 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1512 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1513 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1514 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1515 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1518 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1519 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1520 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1521 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1522 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1523 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1524 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1525 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1528 /* Same as WFX order */
1535 SetDefaultWFXChannelOrder(device
);
1541 void ALCcontext::processUpdates()
1543 std::lock_guard
<std::mutex
> _
{mPropLock
};
1544 if(mDeferUpdates
.exchange(false))
1546 /* Tell the mixer to stop applying updates, then wait for any active
1547 * updating to finish, before providing updates.
1549 mHoldUpdates
.store(true, std::memory_order_release
);
1550 while((mUpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1551 std::this_thread::yield();
1553 if(!mPropsClean
.test_and_set(std::memory_order_acq_rel
))
1554 UpdateContextProps(this);
1555 if(!mListener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1556 UpdateListenerProps(this);
1557 UpdateAllEffectSlotProps(this);
1558 UpdateAllSourceProps(this);
1560 /* Now with all updates declared, let the mixer continue applying them
1561 * so they all happen at once.
1563 mHoldUpdates
.store(false, std::memory_order_release
);
1570 * Stores the latest ALC device error
1572 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1574 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval
<void*>()){device
},
1579 /* DebugBreak() will cause an exception if there is no debugger */
1580 if(IsDebuggerPresent())
1582 #elif defined(SIGTRAP)
1588 device
->LastError
.store(errorCode
);
1590 LastNullDeviceError
.store(errorCode
);
1594 static std::unique_ptr
<Compressor
> CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1596 return CompressorInit(static_cast<ALuint
>(device
->RealOut
.Buffer
.size()),
1597 static_cast<float>(device
->Frequency
), AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
,
1598 0.002f
, 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1603 * Updates the device's base clock time with however many samples have been
1604 * done. This is used so frequency changes on the device don't cause the time
1605 * to jump forward or back. Must not be called while the device is running/
1608 static inline void UpdateClockBase(ALCdevice
*device
)
1610 IncrementRef(device
->MixCount
);
1611 device
->ClockBase
+= nanoseconds
{seconds
{device
->SamplesDone
}} / device
->Frequency
;
1612 device
->SamplesDone
= 0;
1613 IncrementRef(device
->MixCount
);
1616 /* UpdateDeviceParams
1618 * Updates device parameters according to the attribute list (caller is
1619 * responsible for holding the list lock).
1621 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1623 HrtfRequestMode hrtf_userreq
{Hrtf_Default
};
1624 HrtfRequestMode hrtf_appreq
{Hrtf_Default
};
1625 ALCenum gainLimiter
{device
->LimiterState
};
1626 const ALCuint old_sends
{device
->NumAuxSends
};
1627 ALCuint new_sends
{device
->NumAuxSends
};
1628 DevFmtChannels oldChans
;
1630 ALboolean update_failed
;
1631 ALCsizei hrtf_id
{-1};
1634 if((!attrList
|| !attrList
[0]) && device
->Type
== Loopback
)
1636 WARN("Missing attributes for loopback device\n");
1637 return ALC_INVALID_VALUE
;
1640 // Check for attributes
1641 if(attrList
&& attrList
[0])
1643 ALCenum alayout
{AL_NONE
};
1644 ALCenum ascale
{AL_NONE
};
1645 ALCenum schans
{AL_NONE
};
1646 ALCenum stype
{AL_NONE
};
1647 ALCsizei attrIdx
{0};
1651 ALuint numMono
{device
->NumMonoSources
};
1652 ALuint numStereo
{device
->NumStereoSources
};
1653 ALuint numSends
{old_sends
};
1655 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1656 while(attrList
[attrIdx
])
1658 switch(attrList
[attrIdx
])
1660 case ALC_FORMAT_CHANNELS_SOFT
:
1661 schans
= attrList
[attrIdx
+ 1];
1662 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1665 case ALC_FORMAT_TYPE_SOFT
:
1666 stype
= attrList
[attrIdx
+ 1];
1667 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1671 freq
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1672 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1675 case ALC_AMBISONIC_LAYOUT_SOFT
:
1676 alayout
= attrList
[attrIdx
+ 1];
1677 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1680 case ALC_AMBISONIC_SCALING_SOFT
:
1681 ascale
= attrList
[attrIdx
+ 1];
1682 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1685 case ALC_AMBISONIC_ORDER_SOFT
:
1686 aorder
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1687 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1690 case ALC_MONO_SOURCES
:
1691 numMono
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1692 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1693 if(numMono
> INT_MAX
) numMono
= 0;
1696 case ALC_STEREO_SOURCES
:
1697 numStereo
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1698 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1699 if(numStereo
> INT_MAX
) numStereo
= 0;
1702 case ALC_MAX_AUXILIARY_SENDS
:
1703 numSends
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1704 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1705 if(numSends
> INT_MAX
) numSends
= 0;
1706 else numSends
= minu(numSends
, MAX_SENDS
);
1710 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1711 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1712 hrtf_appreq
= Hrtf_Disable
;
1713 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1714 hrtf_appreq
= Hrtf_Enable
;
1716 hrtf_appreq
= Hrtf_Default
;
1719 case ALC_HRTF_ID_SOFT
:
1720 hrtf_id
= attrList
[attrIdx
+ 1];
1721 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1724 case ALC_OUTPUT_LIMITER_SOFT
:
1725 gainLimiter
= attrList
[attrIdx
+ 1];
1726 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1730 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1731 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1739 const bool loopback
{device
->Type
== Loopback
};
1742 if(!schans
|| !stype
|| !freq
)
1744 WARN("Missing format for loopback device\n");
1745 return ALC_INVALID_VALUE
;
1747 if(!IsValidALCChannels(schans
) || !IsValidALCType(stype
) || freq
< MIN_OUTPUT_RATE
)
1748 return ALC_INVALID_VALUE
;
1749 if(schans
== ALC_BFORMAT3D_SOFT
)
1751 if(!alayout
|| !ascale
|| !aorder
)
1753 WARN("Missing ambisonic info for loopback device\n");
1754 return ALC_INVALID_VALUE
;
1756 if(!IsValidAmbiLayout(alayout
) || !IsValidAmbiScaling(ascale
))
1757 return ALC_INVALID_VALUE
;
1758 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1759 return ALC_INVALID_VALUE
;
1760 if((alayout
== ALC_FUMA_SOFT
|| ascale
== ALC_FUMA_SOFT
) && aorder
> 3)
1761 return ALC_INVALID_VALUE
;
1765 /* If a context is already running on the device, stop playback so the
1766 * device attributes can be updated.
1768 if(device
->Flags
.get
<DeviceRunning
>())
1769 device
->Backend
->stop();
1770 device
->Flags
.unset
<DeviceRunning
>();
1772 UpdateClockBase(device
);
1774 const char *devname
{nullptr};
1777 devname
= device
->DeviceName
.c_str();
1779 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
1780 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
1781 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
1783 freq
= ConfigValueUInt(devname
, nullptr, "frequency").value_or(freq
);
1785 device
->Flags
.unset
<FrequencyRequest
>();
1788 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1790 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) /
1792 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) /
1795 device
->Frequency
= freq
;
1796 device
->Flags
.set
<FrequencyRequest
>();
1799 if(auto persizeopt
= ConfigValueUInt(devname
, nullptr, "period_size"))
1800 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
1802 if(auto peropt
= ConfigValueUInt(devname
, nullptr, "periods"))
1803 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
1805 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
1809 device
->Frequency
= freq
;
1810 device
->FmtChans
= static_cast<DevFmtChannels
>(schans
);
1811 device
->FmtType
= static_cast<DevFmtType
>(stype
);
1812 if(schans
== ALC_BFORMAT3D_SOFT
)
1814 device
->mAmbiOrder
= aorder
;
1815 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1816 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1820 if(numMono
> INT_MAX
-numStereo
)
1821 numMono
= INT_MAX
-numStereo
;
1822 numMono
+= numStereo
;
1823 if(auto srcsopt
= ConfigValueUInt(devname
, nullptr, "sources"))
1825 if(*srcsopt
<= 0) numMono
= 256;
1826 else numMono
= *srcsopt
;
1829 numMono
= maxu(numMono
, 256);
1830 numStereo
= minu(numStereo
, numMono
);
1831 numMono
-= numStereo
;
1832 device
->SourcesMax
= numMono
+ numStereo
;
1834 device
->NumMonoSources
= numMono
;
1835 device
->NumStereoSources
= numStereo
;
1837 if(auto sendsopt
= ConfigValueInt(devname
, nullptr, "sends"))
1838 new_sends
= minu(numSends
, static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
1840 new_sends
= numSends
;
1843 if(device
->Flags
.get
<DeviceRunning
>())
1844 return ALC_NO_ERROR
;
1846 device
->AvgSpeakerDist
= 0.0f
;
1847 device
->Uhj_Encoder
= nullptr;
1848 device
->AmbiDecoder
= nullptr;
1849 device
->Bs2b
= nullptr;
1850 device
->PostProcess
= nullptr;
1852 device
->Stablizer
= nullptr;
1853 device
->Limiter
= nullptr;
1854 device
->ChannelDelay
.clear();
1856 device
->Dry
.AmbiMap
.fill(BFChannelConfig
{});
1857 device
->Dry
.Buffer
= {};
1858 std::fill(std::begin(device
->NumChannelsPerOrder
), std::end(device
->NumChannelsPerOrder
), 0u);
1859 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1860 device
->RealOut
.Buffer
= {};
1861 device
->MixBuffer
.clear();
1862 device
->MixBuffer
.shrink_to_fit();
1864 UpdateClockBase(device
);
1865 device
->FixedLatency
= nanoseconds::zero();
1867 device
->DitherDepth
= 0.0f
;
1868 device
->DitherSeed
= DITHER_RNG_SEED
;
1870 /*************************************************************************
1871 * Update device format request if HRTF is requested
1873 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1874 if(device
->Type
!= Loopback
)
1876 if(auto hrtfopt
= ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf"))
1878 const char *hrtf
{hrtfopt
->c_str()};
1879 if(al::strcasecmp(hrtf
, "true") == 0)
1880 hrtf_userreq
= Hrtf_Enable
;
1881 else if(al::strcasecmp(hrtf
, "false") == 0)
1882 hrtf_userreq
= Hrtf_Disable
;
1883 else if(al::strcasecmp(hrtf
, "auto") != 0)
1884 ERR("Unexpected hrtf value: %s\n", hrtf
);
1887 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1889 HrtfEntry
*hrtf
{nullptr};
1890 if(device
->HrtfList
.empty())
1891 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
1892 if(!device
->HrtfList
.empty())
1894 if(hrtf_id
>= 0 && static_cast<ALuint
>(hrtf_id
) < device
->HrtfList
.size())
1895 hrtf
= GetLoadedHrtf(device
->HrtfList
[static_cast<ALuint
>(hrtf_id
)].hrtf
);
1897 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
1902 device
->FmtChans
= DevFmtStereo
;
1903 device
->Frequency
= hrtf
->sampleRate
;
1904 device
->Flags
.set
<ChannelsRequest
, FrequencyRequest
>();
1905 if(HrtfEntry
*oldhrtf
{device
->mHrtf
})
1907 device
->mHrtf
= hrtf
;
1911 hrtf_userreq
= Hrtf_Default
;
1912 hrtf_appreq
= Hrtf_Disable
;
1913 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
1918 oldFreq
= device
->Frequency
;
1919 oldChans
= device
->FmtChans
;
1920 oldType
= device
->FmtType
;
1922 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1923 device
->Flags
.get
<ChannelsRequest
>()?"*":"", DevFmtChannelsString(device
->FmtChans
),
1924 device
->Flags
.get
<SampleTypeRequest
>()?"*":"", DevFmtTypeString(device
->FmtType
),
1925 device
->Flags
.get
<FrequencyRequest
>()?"*":"", device
->Frequency
,
1926 device
->UpdateSize
, device
->BufferSize
);
1929 if(device
->Backend
->reset() == false)
1930 return ALC_INVALID_DEVICE
;
1932 catch(std::exception
&e
) {
1933 ERR("Device reset failed: %s\n", e
.what());
1934 return ALC_INVALID_DEVICE
;
1937 if(device
->FmtChans
!= oldChans
&& device
->Flags
.get
<ChannelsRequest
>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1940 DevFmtChannelsString(device
->FmtChans
));
1941 device
->Flags
.unset
<ChannelsRequest
>();
1943 if(device
->FmtType
!= oldType
&& device
->Flags
.get
<SampleTypeRequest
>())
1945 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1946 DevFmtTypeString(device
->FmtType
));
1947 device
->Flags
.unset
<SampleTypeRequest
>();
1949 if(device
->Frequency
!= oldFreq
&& device
->Flags
.get
<FrequencyRequest
>())
1951 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1952 device
->Flags
.unset
<FrequencyRequest
>();
1955 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1956 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
1957 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
1959 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
1961 device
->NumAuxSends
= new_sends
;
1962 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1963 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
1964 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
1966 /* Enable the stablizer only for formats that have front-left, front-right,
1967 * and front-center outputs.
1969 switch(device
->FmtChans
)
1975 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "front-stablizer", 0))
1977 auto stablizer
= al::make_unique
<FrontStablizer
>();
1978 /* Initialize band-splitting filters for the front-left and front-
1979 * right channels, with a crossover at 5khz (could be higher).
1981 const ALfloat scale
{5000.0f
/ static_cast<ALfloat
>(device
->Frequency
)};
1983 stablizer
->LFilter
.init(scale
);
1984 stablizer
->RFilter
= stablizer
->LFilter
;
1986 device
->Stablizer
= std::move(stablizer
);
1987 /* NOTE: Don't know why this has to be "copied" into a local static
1988 * constexpr variable to avoid a reference on
1989 * FrontStablizer::DelayLength...
1991 static constexpr size_t StablizerDelay
{FrontStablizer::DelayLength
};
1992 device
->FixedLatency
+= nanoseconds
{seconds
{StablizerDelay
}} / device
->Frequency
;
2001 TRACE("Front stablizer %s\n", device
->Stablizer
? "enabled" : "disabled");
2003 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2006 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth").value_or(0)};
2009 switch(device
->FmtType
)
2028 depth
= clampi(depth
, 2, 24);
2029 device
->DitherDepth
= std::pow(2.0f
, static_cast<ALfloat
>(depth
-1));
2032 if(!(device
->DitherDepth
> 0.0f
))
2033 TRACE("Dithering disabled\n");
2035 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2036 device
->DitherDepth
);
2038 device
->LimiterState
= gainLimiter
;
2039 if(auto limopt
= ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter"))
2040 gainLimiter
= *limopt
? ALC_TRUE
: ALC_FALSE
;
2042 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2043 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2044 * output (where samples must be clamped), and don't for floating-point
2045 * (which can take unclamped samples).
2047 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2049 switch(device
->FmtType
)
2057 gainLimiter
= ALC_TRUE
;
2060 gainLimiter
= ALC_FALSE
;
2064 if(gainLimiter
== ALC_FALSE
)
2065 TRACE("Output limiter disabled\n");
2068 ALfloat thrshld
= 1.0f
;
2069 switch(device
->FmtType
)
2073 thrshld
= 127.0f
/ 128.0f
;
2077 thrshld
= 32767.0f
/ 32768.0f
;
2084 if(device
->DitherDepth
> 0.0f
)
2085 thrshld
-= 1.0f
/ device
->DitherDepth
;
2087 const float thrshld_dB
{std::log10(thrshld
) * 20.0f
};
2088 auto limiter
= CreateDeviceLimiter(device
, thrshld_dB
);
2089 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2090 device
->FixedLatency
+= nanoseconds
{seconds
{limiter
->getLookAhead()}} / device
->Frequency
;
2091 device
->Limiter
= std::move(limiter
);
2092 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB
);
2095 TRACE("Fixed device latency: %" PRId64
"ns\n", int64_t{device
->FixedLatency
.count()});
2097 /* Need to delay returning failure until replacement Send arrays have been
2098 * allocated with the appropriate size.
2100 update_failed
= AL_FALSE
;
2101 FPUCtl mixer_mode
{};
2102 for(ALCcontext
*context
: *device
->mContexts
.load())
2104 if(context
->mDefaultSlot
)
2106 ALeffectslot
*slot
= context
->mDefaultSlot
.get();
2107 aluInitEffectPanning(slot
, device
);
2109 EffectState
*state
{slot
->Effect
.State
};
2110 state
->mOutTarget
= device
->Dry
.Buffer
;
2111 if(state
->deviceUpdate(device
) == AL_FALSE
)
2112 update_failed
= AL_TRUE
;
2114 UpdateEffectSlotProps(slot
, context
);
2117 std::unique_lock
<std::mutex
> proplock
{context
->mPropLock
};
2118 std::unique_lock
<std::mutex
> slotlock
{context
->mEffectSlotLock
};
2119 for(auto &sublist
: context
->mEffectSlotList
)
2121 uint64_t usemask
= ~sublist
.FreeMask
;
2124 ALsizei idx
= CTZ64(usemask
);
2125 ALeffectslot
*slot
= sublist
.EffectSlots
+ idx
;
2127 usemask
&= ~(1_u64
<< idx
);
2129 aluInitEffectPanning(slot
, device
);
2131 EffectState
*state
{slot
->Effect
.State
};
2132 state
->mOutTarget
= device
->Dry
.Buffer
;
2133 if(state
->deviceUpdate(device
) == AL_FALSE
)
2134 update_failed
= AL_TRUE
;
2136 UpdateEffectSlotProps(slot
, context
);
2141 std::unique_lock
<std::mutex
> srclock
{context
->mSourceLock
};
2142 for(auto &sublist
: context
->mSourceList
)
2144 uint64_t usemask
= ~sublist
.FreeMask
;
2147 ALsizei idx
= CTZ64(usemask
);
2148 ALsource
*source
= sublist
.Sources
+ idx
;
2150 usemask
&= ~(1_u64
<< idx
);
2152 if(old_sends
!= device
->NumAuxSends
)
2154 if(source
->Send
.size() > device
->NumAuxSends
)
2156 auto clear_send
= [](ALsource::SendData
&send
) -> void
2159 DecrementRef(send
.Slot
->ref
);
2160 send
.Slot
= nullptr;
2162 auto send_begin
= source
->Send
.begin() +
2163 static_cast<ptrdiff_t>(device
->NumAuxSends
);
2164 std::for_each(send_begin
, source
->Send
.end(), clear_send
);
2167 source
->Send
.resize(device
->NumAuxSends
,
2168 {nullptr, 1.0f
, 1.0f
, LOWPASSFREQREF
, 1.0f
, HIGHPASSFREQREF
});
2169 source
->Send
.shrink_to_fit();
2172 source
->PropsClean
.clear(std::memory_order_release
);
2176 /* Clear any pre-existing voice property structs, in case the number of
2177 * auxiliary sends is changing. Active sources will have updates
2178 * respecified in UpdateAllSourceProps.
2180 ALvoiceProps
*vprops
{context
->mFreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2183 ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2188 if(device
->NumAuxSends
< old_sends
)
2190 const ALuint num_sends
{device
->NumAuxSends
};
2191 /* Clear extraneous property set sends. */
2192 auto clear_sends
= [num_sends
](ALvoice
&voice
) -> void
2194 std::fill(std::begin(voice
.mProps
.Send
)+num_sends
, std::end(voice
.mProps
.Send
),
2195 ALvoiceProps::SendData
{});
2197 std::fill(voice
.mSend
.begin()+num_sends
, voice
.mSend
.end(), ALvoice::SendData
{});
2198 auto clear_chan_sends
= [num_sends
](ALvoice::ChannelData
&chandata
) -> void
2200 std::fill(chandata
.mWetParams
.begin()+num_sends
, chandata
.mWetParams
.end(),
2203 std::for_each(voice
.mChans
.begin(), voice
.mChans
.end(), clear_chan_sends
);
2205 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), clear_sends
);
2207 auto reset_voice
= [device
](ALvoice
&voice
) -> void
2209 delete voice
.mUpdate
.exchange(nullptr, std::memory_order_acq_rel
);
2211 /* Force the voice to stopped if it was stopping. */
2212 ALvoice::State vstate
{ALvoice::Stopping
};
2213 voice
.mPlayState
.compare_exchange_strong(vstate
, ALvoice::Stopped
,
2214 std::memory_order_acquire
, std::memory_order_acquire
);
2215 if(voice
.mSourceID
.load(std::memory_order_relaxed
) == 0u)
2218 if(device
->AvgSpeakerDist
> 0.0f
)
2220 /* Reinitialize the NFC filters for new parameters. */
2221 const ALfloat w1
{SPEEDOFSOUNDMETRESPERSEC
/
2222 (device
->AvgSpeakerDist
* static_cast<float>(device
->Frequency
))};
2223 auto init_nfc
= [w1
](ALvoice::ChannelData
&chandata
) -> void
2224 { chandata
.mDryParams
.NFCtrlFilter
.init(w1
); };
2225 std::for_each(voice
.mChans
.begin(), voice
.mChans
.begin()+voice
.mNumChannels
,
2229 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), reset_voice
);
2232 context
->mPropsClean
.test_and_set(std::memory_order_release
);
2233 UpdateContextProps(context
);
2234 context
->mListener
.PropsClean
.test_and_set(std::memory_order_release
);
2235 UpdateListenerProps(context
);
2236 UpdateAllSourceProps(context
);
2240 return ALC_INVALID_DEVICE
;
2242 if(!device
->Flags
.get
<DevicePaused
>())
2244 if(device
->Backend
->start() == false)
2245 return ALC_INVALID_DEVICE
;
2246 device
->Flags
.set
<DeviceRunning
>();
2249 return ALC_NO_ERROR
;
2253 ALCdevice::ALCdevice(DeviceType type
) : Type
{type
}, mContexts
{&EmptyContextArray
}
2257 /* ALCdevice::~ALCdevice
2259 * Frees the device structure, and destroys any objects the app failed to
2260 * delete. Called once there's no more references on the device.
2262 ALCdevice::~ALCdevice()
2264 TRACE("Freeing device %p\n", decltype(std::declval
<void*>()){this});
2268 size_t count
{std::accumulate(BufferList
.cbegin(), BufferList
.cend(), size_t{0u},
2269 [](size_t cur
, const BufferSubList
&sublist
) noexcept
-> size_t
2270 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2273 WARN("%zu Buffer%s not deleted\n", count
, (count
==1)?"":"s");
2275 count
= std::accumulate(EffectList
.cbegin(), EffectList
.cend(), size_t{0u},
2276 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
2277 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2280 WARN("%zu Effect%s not deleted\n", count
, (count
==1)?"":"s");
2282 count
= std::accumulate(FilterList
.cbegin(), FilterList
.cend(), size_t{0u},
2283 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
2284 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2287 WARN("%zu Filter%s not deleted\n", count
, (count
==1)?"":"s");
2293 auto *oldarray
= mContexts
.exchange(nullptr, std::memory_order_relaxed
);
2294 if(oldarray
!= &EmptyContextArray
) delete oldarray
;
2300 * Checks if the device handle is valid, and returns a new reference if so.
2302 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2304 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2305 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
);
2306 if(iter
!= DeviceList
.cend() && *iter
== device
)
2312 ALCcontext::ALCcontext(al::intrusive_ptr
<ALCdevice
> device
) : mDevice
{std::move(device
)}
2314 mPropsClean
.test_and_set(std::memory_order_relaxed
);
2317 ALCcontext::~ALCcontext()
2319 TRACE("Freeing context %p\n", decltype(std::declval
<void*>()){this});
2322 ALcontextProps
*cprops
{mUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
2328 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
2331 ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2336 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
2338 count
= std::accumulate(mSourceList
.cbegin(), mSourceList
.cend(), size_t{0u},
2339 [](size_t cur
, const SourceSubList
&sublist
) noexcept
-> size_t
2340 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2343 WARN("%zu Source%s not deleted\n", count
, (count
==1)?"":"s");
2344 mSourceList
.clear();
2348 ALeffectslotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
2351 ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2352 if(eprops
->State
) eprops
->State
->release();
2357 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2359 delete mActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
);
2360 mDefaultSlot
= nullptr;
2362 count
= std::accumulate(mEffectSlotList
.cbegin(), mEffectSlotList
.cend(), size_t{0u},
2363 [](size_t cur
, const EffectSlotSubList
&sublist
) noexcept
-> size_t
2364 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2367 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count
, (count
==1)?"":"s");
2368 mEffectSlotList
.clear();
2369 mNumEffectSlots
= 0;
2372 ALvoiceProps
*vprops
{mFreeVoiceProps
.exchange(nullptr, std::memory_order_acquire
)};
2375 ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2380 TRACE("Freed %zu voice property object%s\n", count
, (count
==1)?"":"s");
2385 ALlistenerProps
*lprops
{mListener
.Params
.Update
.exchange(nullptr, std::memory_order_relaxed
)};
2391 lprops
= mFreeListenerProps
.exchange(nullptr, std::memory_order_acquire
);
2394 ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2399 TRACE("Freed %zu listener property object%s\n", count
, (count
==1)?"":"s");
2404 auto evt_vec
= mAsyncEvents
->getReadVector();
2405 if(evt_vec
.first
.len
> 0)
2407 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.first
.buf
), evt_vec
.first
.len
);
2408 count
+= evt_vec
.first
.len
;
2410 if(evt_vec
.second
.len
> 0)
2412 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.second
.buf
), evt_vec
.second
.len
);
2413 count
+= evt_vec
.second
.len
;
2416 TRACE("Destructed %zu orphaned event%s\n", count
, (count
==1)?"":"s");
2417 mAsyncEvents
->readAdvance(count
);
2421 void ALCcontext::init()
2423 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& mDevice
->Type
== Playback
)
2425 mDefaultSlot
= std::unique_ptr
<ALeffectslot
>{new ALeffectslot
{}};
2426 if(InitEffectSlot(mDefaultSlot
.get()) == AL_NO_ERROR
)
2427 aluInitEffectPanning(mDefaultSlot
.get(), mDevice
.get());
2430 mDefaultSlot
= nullptr;
2431 ERR("Failed to initialize the default effect slot\n");
2435 ALeffectslotArray
*auxslots
;
2437 auxslots
= ALeffectslot::CreatePtrArray(0);
2440 auxslots
= ALeffectslot::CreatePtrArray(1);
2441 (*auxslots
)[0] = mDefaultSlot
.get();
2443 mActiveAuxSlots
.store(auxslots
, std::memory_order_relaxed
);
2445 mExtensionList
= alExtList
;
2448 mListener
.Params
.Matrix
= alu::Matrix::Identity();
2449 mListener
.Params
.Velocity
= alu::Vector
{};
2450 mListener
.Params
.Gain
= mListener
.Gain
;
2451 mListener
.Params
.MetersPerUnit
= mListener
.mMetersPerUnit
;
2452 mListener
.Params
.DopplerFactor
= mDopplerFactor
;
2453 mListener
.Params
.SpeedOfSound
= mSpeedOfSound
* mDopplerVelocity
;
2454 mListener
.Params
.SourceDistanceModel
= mSourceDistanceModel
;
2455 mListener
.Params
.mDistanceModel
= mDistanceModel
;
2458 mAsyncEvents
= CreateRingBuffer(511, sizeof(AsyncEvent
), false);
2459 StartEventThrd(this);
2462 mVoices
.reserve(256);
2466 bool ALCcontext::deinit()
2468 if(LocalContext
.get() == this)
2470 WARN("%p released while current on thread\n", decltype(std::declval
<void*>()){this});
2471 LocalContext
.set(nullptr);
2475 ALCcontext
*origctx
{this};
2476 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2480 /* First make sure this context exists in the device's list. */
2481 auto *oldarray
= mDevice
->mContexts
.load(std::memory_order_acquire
);
2482 if(auto toremove
= static_cast<size_t>(std::count(oldarray
->begin(), oldarray
->end(), this)))
2484 using ContextArray
= al::FlexArray
<ALCcontext
*>;
2485 auto alloc_ctx_array
= [](const size_t count
) -> ContextArray
*
2487 if(count
== 0) return &EmptyContextArray
;
2488 return ContextArray::Create(count
).release();
2490 auto *newarray
= alloc_ctx_array(oldarray
->size() - toremove
);
2492 /* Copy the current/old context handles to the new array, excluding the
2495 std::copy_if(oldarray
->begin(), oldarray
->end(), newarray
->begin(),
2496 std::bind(std::not_equal_to
<ALCcontext
*>{}, _1
, this));
2498 /* Store the new context array in the device. Wait for any current mix
2499 * to finish before deleting the old array.
2501 mDevice
->mContexts
.store(newarray
);
2502 if(oldarray
!= &EmptyContextArray
)
2504 while((mDevice
->MixCount
.load(std::memory_order_acquire
)&1))
2505 std::this_thread::yield();
2509 ret
= !newarray
->empty();
2512 ret
= !oldarray
->empty();
2514 StopEventThrd(this);
2522 * Checks if the given context is valid, returning a new reference to it if so.
2524 static ContextRef
VerifyContext(ALCcontext
*context
)
2526 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2527 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
);
2528 if(iter
!= ContextList
.cend() && *iter
== context
)
2535 * Returns a new reference to the currently active context for this thread.
2537 ContextRef
GetContextRef(void)
2539 ALCcontext
*context
{LocalContext
.get()};
2544 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2545 context
= GlobalContext
.load(std::memory_order_acquire
);
2546 if(context
) context
->add_ref();
2548 return ContextRef
{context
};
2552 /************************************************
2553 * Standard ALC functions
2554 ************************************************/
2558 * Return last ALC generated error code for the given device
2560 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2563 DeviceRef dev
{VerifyDevice(device
)};
2564 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2565 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2570 /* alcSuspendContext
2572 * Suspends updates for the given context
2574 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2580 ContextRef ctx
{VerifyContext(context
)};
2582 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2584 ctx
->deferUpdates();
2588 /* alcProcessContext
2590 * Resumes processing updates for the given context
2592 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2598 ContextRef ctx
{VerifyContext(context
)};
2600 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2602 ctx
->processUpdates();
2609 * Returns information about the device, and error strings
2611 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2614 const ALCchar
*value
= nullptr;
2622 case ALC_INVALID_ENUM
:
2623 value
= alcErrInvalidEnum
;
2626 case ALC_INVALID_VALUE
:
2627 value
= alcErrInvalidValue
;
2630 case ALC_INVALID_DEVICE
:
2631 value
= alcErrInvalidDevice
;
2634 case ALC_INVALID_CONTEXT
:
2635 value
= alcErrInvalidContext
;
2638 case ALC_OUT_OF_MEMORY
:
2639 value
= alcErrOutOfMemory
;
2642 case ALC_DEVICE_SPECIFIER
:
2643 value
= alcDefaultName
;
2646 case ALC_ALL_DEVICES_SPECIFIER
:
2647 if(DeviceRef dev
{VerifyDevice(Device
)})
2648 value
= dev
->DeviceName
.c_str();
2651 ProbeAllDevicesList();
2652 value
= alcAllDevicesList
.c_str();
2656 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2657 if(DeviceRef dev
{VerifyDevice(Device
)})
2658 value
= dev
->DeviceName
.c_str();
2661 ProbeCaptureDeviceList();
2662 value
= alcCaptureDeviceList
.c_str();
2666 /* Default devices are always first in the list */
2667 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2668 value
= alcDefaultName
;
2671 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2672 if(alcAllDevicesList
.empty())
2673 ProbeAllDevicesList();
2675 /* Copy first entry as default. */
2676 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2677 value
= alcDefaultAllDevicesSpecifier
.c_str();
2680 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2681 if(alcCaptureDeviceList
.empty())
2682 ProbeCaptureDeviceList();
2684 /* Copy first entry as default. */
2685 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2686 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2689 case ALC_EXTENSIONS
:
2690 if(VerifyDevice(Device
))
2691 value
= alcExtensionList
;
2693 value
= alcNoDeviceExtList
;
2696 case ALC_HRTF_SPECIFIER_SOFT
:
2697 if(DeviceRef dev
{VerifyDevice(Device
)})
2699 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
2700 value
= (dev
->mHrtf
? dev
->HrtfName
.c_str() : "");
2703 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2707 alcSetError(VerifyDevice(Device
).get(), ALC_INVALID_ENUM
);
2716 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2718 if(device
->Type
== Capture
) return 9;
2719 if(device
->Type
!= Loopback
) return 29;
2720 if(device
->FmtChans
== DevFmtAmbi3D
)
2725 static size_t GetIntegerv(ALCdevice
*device
, ALCenum param
, const al::span
<ALCint
> values
)
2731 alcSetError(device
, ALC_INVALID_VALUE
);
2739 case ALC_MAJOR_VERSION
:
2740 values
[0] = alcMajorVersion
;
2742 case ALC_MINOR_VERSION
:
2743 values
[0] = alcMinorVersion
;
2746 case ALC_ATTRIBUTES_SIZE
:
2747 case ALC_ALL_ATTRIBUTES
:
2751 case ALC_MONO_SOURCES
:
2752 case ALC_STEREO_SOURCES
:
2753 case ALC_CAPTURE_SAMPLES
:
2754 case ALC_FORMAT_CHANNELS_SOFT
:
2755 case ALC_FORMAT_TYPE_SOFT
:
2756 case ALC_AMBISONIC_LAYOUT_SOFT
:
2757 case ALC_AMBISONIC_SCALING_SOFT
:
2758 case ALC_AMBISONIC_ORDER_SOFT
:
2759 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
2760 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2764 alcSetError(nullptr, ALC_INVALID_ENUM
);
2770 if(device
->Type
== Capture
)
2774 case ALC_ATTRIBUTES_SIZE
:
2775 values
[0] = NumAttrsForDevice(device
);
2778 case ALC_ALL_ATTRIBUTES
:
2780 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2781 alcSetError(device
, ALC_INVALID_VALUE
);
2784 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2785 values
[i
++] = ALC_MAJOR_VERSION
;
2786 values
[i
++] = alcMajorVersion
;
2787 values
[i
++] = ALC_MINOR_VERSION
;
2788 values
[i
++] = alcMinorVersion
;
2789 values
[i
++] = ALC_CAPTURE_SAMPLES
;
2790 values
[i
++] = static_cast<int>(device
->Backend
->availableSamples());
2791 values
[i
++] = ALC_CONNECTED
;
2792 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
2797 case ALC_MAJOR_VERSION
:
2798 values
[0] = alcMajorVersion
;
2800 case ALC_MINOR_VERSION
:
2801 values
[0] = alcMinorVersion
;
2804 case ALC_CAPTURE_SAMPLES
:
2806 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2807 values
[0] = static_cast<int>(device
->Backend
->availableSamples());
2813 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2814 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2819 alcSetError(device
, ALC_INVALID_ENUM
);
2827 case ALC_ATTRIBUTES_SIZE
:
2828 values
[0] = NumAttrsForDevice(device
);
2831 case ALC_ALL_ATTRIBUTES
:
2833 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2834 alcSetError(device
, ALC_INVALID_VALUE
);
2837 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2838 values
[i
++] = ALC_MAJOR_VERSION
;
2839 values
[i
++] = alcMajorVersion
;
2840 values
[i
++] = ALC_MINOR_VERSION
;
2841 values
[i
++] = alcMinorVersion
;
2842 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
2843 values
[i
++] = alcEFXMajorVersion
;
2844 values
[i
++] = ALC_EFX_MINOR_VERSION
;
2845 values
[i
++] = alcEFXMinorVersion
;
2847 values
[i
++] = ALC_FREQUENCY
;
2848 values
[i
++] = static_cast<int>(device
->Frequency
);
2849 if(device
->Type
!= Loopback
)
2851 values
[i
++] = ALC_REFRESH
;
2852 values
[i
++] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2854 values
[i
++] = ALC_SYNC
;
2855 values
[i
++] = ALC_FALSE
;
2859 if(device
->FmtChans
== DevFmtAmbi3D
)
2861 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
2862 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
2864 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
2865 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
2867 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
2868 values
[i
++] = static_cast<ALCint
>(device
->mAmbiOrder
);
2871 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2872 values
[i
++] = device
->FmtChans
;
2874 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2875 values
[i
++] = device
->FmtType
;
2878 values
[i
++] = ALC_MONO_SOURCES
;
2879 values
[i
++] = static_cast<int>(device
->NumMonoSources
);
2881 values
[i
++] = ALC_STEREO_SOURCES
;
2882 values
[i
++] = static_cast<int>(device
->NumStereoSources
);
2884 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2885 values
[i
++] = static_cast<ALCint
>(device
->NumAuxSends
);
2887 values
[i
++] = ALC_HRTF_SOFT
;
2888 values
[i
++] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
2890 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
2891 values
[i
++] = device
->HrtfStatus
;
2893 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
2894 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
2896 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
2897 values
[i
++] = MAX_AMBI_ORDER
;
2903 case ALC_MAJOR_VERSION
:
2904 values
[0] = alcMajorVersion
;
2907 case ALC_MINOR_VERSION
:
2908 values
[0] = alcMinorVersion
;
2911 case ALC_EFX_MAJOR_VERSION
:
2912 values
[0] = alcEFXMajorVersion
;
2915 case ALC_EFX_MINOR_VERSION
:
2916 values
[0] = alcEFXMinorVersion
;
2920 values
[0] = static_cast<int>(device
->Frequency
);
2924 if(device
->Type
== Loopback
)
2926 alcSetError(device
, ALC_INVALID_DEVICE
);
2930 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2931 values
[0] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2936 if(device
->Type
== Loopback
)
2938 alcSetError(device
, ALC_INVALID_DEVICE
);
2941 values
[0] = ALC_FALSE
;
2944 case ALC_FORMAT_CHANNELS_SOFT
:
2945 if(device
->Type
!= Loopback
)
2947 alcSetError(device
, ALC_INVALID_DEVICE
);
2950 values
[0] = device
->FmtChans
;
2953 case ALC_FORMAT_TYPE_SOFT
:
2954 if(device
->Type
!= Loopback
)
2956 alcSetError(device
, ALC_INVALID_DEVICE
);
2959 values
[0] = device
->FmtType
;
2962 case ALC_AMBISONIC_LAYOUT_SOFT
:
2963 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2965 alcSetError(device
, ALC_INVALID_DEVICE
);
2968 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
2971 case ALC_AMBISONIC_SCALING_SOFT
:
2972 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2974 alcSetError(device
, ALC_INVALID_DEVICE
);
2977 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
2980 case ALC_AMBISONIC_ORDER_SOFT
:
2981 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2983 alcSetError(device
, ALC_INVALID_DEVICE
);
2986 values
[0] = static_cast<int>(device
->mAmbiOrder
);
2989 case ALC_MONO_SOURCES
:
2990 values
[0] = static_cast<int>(device
->NumMonoSources
);
2993 case ALC_STEREO_SOURCES
:
2994 values
[0] = static_cast<int>(device
->NumStereoSources
);
2997 case ALC_MAX_AUXILIARY_SENDS
:
2998 values
[0] = static_cast<ALCint
>(device
->NumAuxSends
);
3003 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3004 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3009 values
[0] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3012 case ALC_HRTF_STATUS_SOFT
:
3013 values
[0] = device
->HrtfStatus
;
3016 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3018 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3019 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3020 values
[0] = static_cast<ALCint
>(minz(device
->HrtfList
.size(),
3021 std::numeric_limits
<ALCint
>::max()));
3025 case ALC_OUTPUT_LIMITER_SOFT
:
3026 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3029 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3030 values
[0] = MAX_AMBI_ORDER
;
3034 alcSetError(device
, ALC_INVALID_ENUM
);
3041 * Returns information about the device and the version of OpenAL
3043 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3046 DeviceRef dev
{VerifyDevice(device
)};
3047 if(size
<= 0 || values
== nullptr)
3048 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3050 GetIntegerv(dev
.get(), param
, {values
, values
+size
});
3054 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3057 DeviceRef dev
{VerifyDevice(device
)};
3058 if(size
<= 0 || values
== nullptr)
3059 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3060 else if(!dev
|| dev
->Type
== Capture
)
3062 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3063 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3064 std::copy_n(ivals
.begin(), got
, values
);
3070 case ALC_ATTRIBUTES_SIZE
:
3071 *values
= NumAttrsForDevice(dev
.get())+4;
3074 case ALC_ALL_ATTRIBUTES
:
3075 if(size
< NumAttrsForDevice(dev
.get())+4)
3076 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3080 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3081 values
[i
++] = ALC_FREQUENCY
;
3082 values
[i
++] = dev
->Frequency
;
3084 if(dev
->Type
!= Loopback
)
3086 values
[i
++] = ALC_REFRESH
;
3087 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3089 values
[i
++] = ALC_SYNC
;
3090 values
[i
++] = ALC_FALSE
;
3094 if(dev
->FmtChans
== DevFmtAmbi3D
)
3096 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3097 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiLayout
);
3099 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3100 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiScale
);
3102 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3103 values
[i
++] = dev
->mAmbiOrder
;
3106 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3107 values
[i
++] = dev
->FmtChans
;
3109 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3110 values
[i
++] = dev
->FmtType
;
3113 values
[i
++] = ALC_MONO_SOURCES
;
3114 values
[i
++] = dev
->NumMonoSources
;
3116 values
[i
++] = ALC_STEREO_SOURCES
;
3117 values
[i
++] = dev
->NumStereoSources
;
3119 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3120 values
[i
++] = dev
->NumAuxSends
;
3122 values
[i
++] = ALC_HRTF_SOFT
;
3123 values
[i
++] = (dev
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3125 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3126 values
[i
++] = dev
->HrtfStatus
;
3128 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3129 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3131 ClockLatency clock
{GetClockLatency(dev
.get())};
3132 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3133 values
[i
++] = clock
.ClockTime
.count();
3135 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3136 values
[i
++] = clock
.Latency
.count();
3142 case ALC_DEVICE_CLOCK_SOFT
:
3143 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3144 nanoseconds basecount
;
3148 while(((refcount
=ReadRef(dev
->MixCount
))&1) != 0)
3149 std::this_thread::yield();
3150 basecount
= dev
->ClockBase
;
3151 samplecount
= dev
->SamplesDone
;
3152 } while(refcount
!= ReadRef(dev
->MixCount
));
3153 basecount
+= nanoseconds
{seconds
{samplecount
}} / dev
->Frequency
;
3154 *values
= basecount
.count();
3158 case ALC_DEVICE_LATENCY_SOFT
:
3159 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3160 ClockLatency clock
{GetClockLatency(dev
.get())};
3161 *values
= clock
.Latency
.count();
3165 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3167 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3170 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3171 ClockLatency clock
{GetClockLatency(dev
.get())};
3172 values
[0] = clock
.ClockTime
.count();
3173 values
[1] = clock
.Latency
.count();
3178 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3179 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3180 std::copy_n(ivals
.begin(), got
, values
);
3187 /* alcIsExtensionPresent
3189 * Determines if there is support for a particular extension
3191 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3194 DeviceRef dev
{VerifyDevice(device
)};
3196 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3199 size_t len
= strlen(extName
);
3200 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3203 if(al::strncasecmp(ptr
, extName
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3206 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3210 } while(isspace(*ptr
));
3219 /* alcGetProcAddress
3221 * Retrieves the function address for a particular extension function
3223 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3228 DeviceRef dev
{VerifyDevice(device
)};
3229 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3233 for(const auto &func
: alcFunctions
)
3235 if(strcmp(func
.funcName
, funcName
) == 0)
3236 return func
.address
;
3246 * Get the value for a particular ALC enumeration name
3248 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3253 DeviceRef dev
{VerifyDevice(device
)};
3254 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3258 for(const auto &enm
: alcEnumerations
)
3260 if(strcmp(enm
.enumName
, enumName
) == 0)
3271 * Create and attach a context to the given device.
3273 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3276 /* Explicitly hold the list lock while taking the StateLock in case the
3277 * device is asynchronously destroyed, to ensure this new context is
3278 * properly cleaned up after being made.
3280 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3281 DeviceRef dev
{VerifyDevice(device
)};
3282 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3285 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3288 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3291 dev
->LastError
.store(ALC_NO_ERROR
);
3293 ALCenum err
{UpdateDeviceParams(dev
.get(), attrList
)};
3294 if(err
!= ALC_NO_ERROR
)
3296 alcSetError(dev
.get(), err
);
3297 if(err
== ALC_INVALID_DEVICE
)
3298 aluHandleDisconnect(dev
.get(), "Device update failure");
3302 ContextRef context
{new ALCcontext
{dev
}};
3305 if(auto volopt
= ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust"))
3307 const ALfloat valf
{*volopt
};
3308 if(!std::isfinite(valf
))
3309 ERR("volume-adjust must be finite: %f\n", valf
);
3312 const ALfloat db
{clampf(valf
, -24.0f
, 24.0f
)};
3314 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3315 context
->mGainBoost
= std::pow(10.0f
, db
/20.0f
);
3316 TRACE("volume-adjust gain: %f\n", context
->mGainBoost
);
3319 UpdateListenerProps(context
.get());
3322 using ContextArray
= al::FlexArray
<ALCcontext
*>;
3324 /* Allocate a new context array, which holds 1 more than the current/
3327 auto *oldarray
= device
->mContexts
.load();
3328 const size_t newcount
{oldarray
->size()+1};
3329 std::unique_ptr
<ContextArray
> newarray
{ContextArray::Create(newcount
)};
3331 /* Copy the current/old context handles to the new array, appending the
3334 auto iter
= std::copy(oldarray
->begin(), oldarray
->end(), newarray
->begin());
3335 *iter
= context
.get();
3337 /* Store the new context array in the device. Wait for any current mix
3338 * to finish before deleting the old array.
3340 dev
->mContexts
.store(newarray
.release());
3341 if(oldarray
!= &EmptyContextArray
)
3343 while((dev
->MixCount
.load(std::memory_order_acquire
)&1))
3344 std::this_thread::yield();
3351 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3352 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
.get());
3353 ContextList
.emplace(iter
, context
);
3356 if(context
->mDefaultSlot
)
3358 if(InitializeEffect(context
.get(), context
->mDefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3359 UpdateEffectSlotProps(context
->mDefaultSlot
.get(), context
.get());
3361 ERR("Failed to initialize the default effect\n");
3364 TRACE("Created context %p\n", decltype(std::declval
<void*>()){context
.get()});
3365 return context
.get();
3369 /* alcDestroyContext
3371 * Remove a context from its device
3373 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3376 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3377 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
3378 if(iter
== ContextList
.end() || *iter
!= context
)
3381 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3384 /* Hold an extra reference to this context so it remains valid until the
3385 * ListLock is released.
3387 ContextRef ctx
{std::move(*iter
)};
3388 ContextList
.erase(iter
);
3390 ALCdevice
*Device
{ctx
->mDevice
.get()};
3392 std::lock_guard
<std::mutex
> _
{Device
->StateLock
};
3393 if(!ctx
->deinit() && Device
->Flags
.get
<DeviceRunning
>())
3395 Device
->Backend
->stop();
3396 Device
->Flags
.unset
<DeviceRunning
>();
3402 /* alcGetCurrentContext
3404 * Returns the currently active context on the calling thread
3406 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3409 ALCcontext
*Context
{LocalContext
.get()};
3410 if(!Context
) Context
= GlobalContext
.load();
3415 /* alcGetThreadContext
3417 * Returns the currently active thread-local context
3419 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3421 { return LocalContext
.get(); }
3424 /* alcMakeContextCurrent
3426 * Makes the given context the active process-wide context, and removes the
3427 * thread-local context for the calling thread.
3429 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3432 /* context must be valid or nullptr */
3436 ctx
= VerifyContext(context
);
3439 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3443 /* Release this reference (if any) to store it in the GlobalContext
3444 * pointer. Take ownership of the reference (if any) that was previously
3447 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3449 /* Reset (decrement) the previous global reference by replacing it with the
3450 * thread-local context. Take ownership of the thread-local context
3451 * reference (if any), clearing the storage to null.
3453 ctx
= ContextRef
{LocalContext
.get()};
3454 if(ctx
) LocalContext
.set(nullptr);
3455 /* Reset (decrement) the previous thread-local reference. */
3461 /* alcSetThreadContext
3463 * Makes the given context the active context for the current thread
3465 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3468 /* context must be valid or nullptr */
3472 ctx
= VerifyContext(context
);
3475 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3479 /* context's reference count is already incremented */
3480 ContextRef old
{LocalContext
.get()};
3481 LocalContext
.set(ctx
.release());
3488 /* alcGetContextsDevice
3490 * Returns the device that a particular context is attached to
3492 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3495 ContextRef ctx
{VerifyContext(Context
)};
3498 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3501 return ctx
->mDevice
.get();
3508 * Opens the named device.
3510 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3515 if(!PlaybackFactory
)
3517 alcSetError(nullptr, ALC_INVALID_VALUE
);
3523 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3525 /* Some old Windows apps hardcode these expecting OpenAL to use a
3526 * specific audio API, even when they're not enumerated. Creative's
3527 * router effectively ignores them too.
3529 || al::strcasecmp(deviceName
, "DirectSound3D") == 0
3530 || al::strcasecmp(deviceName
, "DirectSound") == 0
3531 || al::strcasecmp(deviceName
, "MMSYSTEM") == 0
3533 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3534 deviceName
= nullptr;
3537 DeviceRef device
{new ALCdevice
{Playback
}};
3539 /* Set output format */
3540 device
->FmtChans
= DevFmtChannelsDefault
;
3541 device
->FmtType
= DevFmtTypeDefault
;
3542 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3543 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
3544 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
3546 device
->SourcesMax
= 256;
3547 device
->AuxiliaryEffectSlotMax
= 64;
3548 device
->NumAuxSends
= DEFAULT_SENDS
;
3551 /* Create the device backend. */
3552 device
->Backend
= PlaybackFactory
->createBackend(device
.get(), BackendType::Playback
);
3554 /* Find a playback device to open */
3555 ALCenum err
{device
->Backend
->open(deviceName
)};
3556 if(err
!= ALC_NO_ERROR
)
3558 alcSetError(nullptr, err
);
3562 catch(al::backend_exception
&e
) {
3563 WARN("Failed to open playback device: %s\n", e
.what());
3564 alcSetError(nullptr, e
.errorCode());
3568 deviceName
= device
->DeviceName
.c_str();
3569 if(auto chanopt
= ConfigValueStr(deviceName
, nullptr, "channels"))
3571 static constexpr struct ChannelMap
{
3572 const char name
[16];
3573 DevFmtChannels chans
;
3576 { "mono", DevFmtMono
, 0 },
3577 { "stereo", DevFmtStereo
, 0 },
3578 { "quad", DevFmtQuad
, 0 },
3579 { "surround51", DevFmtX51
, 0 },
3580 { "surround61", DevFmtX61
, 0 },
3581 { "surround71", DevFmtX71
, 0 },
3582 { "surround51rear", DevFmtX51Rear
, 0 },
3583 { "ambi1", DevFmtAmbi3D
, 1 },
3584 { "ambi2", DevFmtAmbi3D
, 2 },
3585 { "ambi3", DevFmtAmbi3D
, 3 },
3588 const ALCchar
*fmt
{chanopt
->c_str()};
3589 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3590 [fmt
](const ChannelMap
&entry
) -> bool
3591 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3593 if(iter
== std::end(chanlist
))
3594 ERR("Unsupported channels: %s\n", fmt
);
3597 device
->FmtChans
= iter
->chans
;
3598 device
->mAmbiOrder
= iter
->order
;
3599 device
->Flags
.set
<ChannelsRequest
>();
3602 if(auto typeopt
= ConfigValueStr(deviceName
, nullptr, "sample-type"))
3604 static constexpr struct TypeMap
{
3605 const char name
[16];
3608 { "int8", DevFmtByte
},
3609 { "uint8", DevFmtUByte
},
3610 { "int16", DevFmtShort
},
3611 { "uint16", DevFmtUShort
},
3612 { "int32", DevFmtInt
},
3613 { "uint32", DevFmtUInt
},
3614 { "float32", DevFmtFloat
},
3617 const ALCchar
*fmt
{typeopt
->c_str()};
3618 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3619 [fmt
](const TypeMap
&entry
) -> bool
3620 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3622 if(iter
== std::end(typelist
))
3623 ERR("Unsupported sample-type: %s\n", fmt
);
3626 device
->FmtType
= iter
->type
;
3627 device
->Flags
.set
<SampleTypeRequest
>();
3631 if(ALuint freq
{ConfigValueUInt(deviceName
, nullptr, "frequency").value_or(0)})
3633 if(freq
< MIN_OUTPUT_RATE
)
3635 ERR("%uhz request clamped to %uhz minimum\n", freq
, MIN_OUTPUT_RATE
);
3636 freq
= MIN_OUTPUT_RATE
;
3638 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3639 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3640 device
->Frequency
= freq
;
3641 device
->Flags
.set
<FrequencyRequest
>();
3644 if(auto persizeopt
= ConfigValueUInt(deviceName
, nullptr, "period_size"))
3645 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
3647 if(auto peropt
= ConfigValueUInt(deviceName
, nullptr, "periods"))
3648 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
3650 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
3652 if(auto srcsopt
= ConfigValueUInt(deviceName
, nullptr, "sources"))
3654 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3657 if(auto slotsopt
= ConfigValueUInt(deviceName
, nullptr, "slots"))
3660 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3663 if(auto sendsopt
= ConfigValueInt(deviceName
, nullptr, "sends"))
3664 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3665 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3667 device
->NumStereoSources
= 1;
3668 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3670 if(auto ambiopt
= ConfigValueStr(deviceName
, nullptr, "ambi-format"))
3672 const ALCchar
*fmt
{ambiopt
->c_str()};
3673 if(al::strcasecmp(fmt
, "fuma") == 0)
3675 if(device
->mAmbiOrder
> 3)
3676 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3678 (((device
->mAmbiOrder
%100)/10) == 1) ? "th" :
3679 ((device
->mAmbiOrder
%10) == 1) ? "st" :
3680 ((device
->mAmbiOrder
%10) == 2) ? "nd" :
3681 ((device
->mAmbiOrder
%10) == 3) ? "rd" : "th");
3684 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3685 device
->mAmbiScale
= AmbiNorm::FuMa
;
3688 else if(al::strcasecmp(fmt
, "ambix") == 0 || al::strcasecmp(fmt
, "acn+sn3d") == 0)
3690 device
->mAmbiLayout
= AmbiLayout::ACN
;
3691 device
->mAmbiScale
= AmbiNorm::SN3D
;
3693 else if(al::strcasecmp(fmt
, "acn+n3d") == 0)
3695 device
->mAmbiLayout
= AmbiLayout::ACN
;
3696 device
->mAmbiScale
= AmbiNorm::N3D
;
3699 ERR("Unsupported ambi-format: %s\n", fmt
);
3703 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3704 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3705 DeviceList
.emplace(iter
, device
);
3708 TRACE("Created device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3709 device
->DeviceName
.c_str());
3710 return device
.get();
3716 * Closes the given device.
3718 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3721 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3722 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3723 if(iter
== DeviceList
.end() || *iter
!= device
)
3725 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3728 if((*iter
)->Type
== Capture
)
3730 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3734 /* Erase the device, and any remaining contexts left on it, from their
3737 DeviceRef dev
{std::move(*iter
)};
3738 DeviceList
.erase(iter
);
3740 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3741 al::vector
<ContextRef
> orphanctxs
;
3742 for(ALCcontext
*ctx
: *dev
->mContexts
.load())
3744 auto ctxiter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), ctx
);
3745 if(ctxiter
!= ContextList
.end() && *ctxiter
== ctx
)
3747 orphanctxs
.emplace_back(std::move(*ctxiter
));
3748 ContextList
.erase(ctxiter
);
3753 for(ContextRef
&context
: orphanctxs
)
3755 WARN("Releasing orphaned context %p\n", decltype(std::declval
<void*>()){context
.get()});
3760 if(dev
->Flags
.get
<DeviceRunning
>())
3761 dev
->Backend
->stop();
3762 dev
->Flags
.unset
<DeviceRunning
>();
3769 /************************************************
3770 * ALC capture functions
3771 ************************************************/
3772 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3779 alcSetError(nullptr, ALC_INVALID_VALUE
);
3785 alcSetError(nullptr, ALC_INVALID_VALUE
);
3791 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3792 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3793 deviceName
= nullptr;
3796 DeviceRef device
{new ALCdevice
{Capture
}};
3798 auto decompfmt
= DecomposeDevFormat(format
);
3801 alcSetError(nullptr, ALC_INVALID_ENUM
);
3805 device
->Frequency
= frequency
;
3806 device
->FmtChans
= decompfmt
->chans
;
3807 device
->FmtType
= decompfmt
->type
;
3808 device
->Flags
.set
<FrequencyRequest
, ChannelsRequest
, SampleTypeRequest
>();
3810 device
->UpdateSize
= static_cast<ALuint
>(samples
);
3811 device
->BufferSize
= static_cast<ALuint
>(samples
);
3814 device
->Backend
= CaptureFactory
->createBackend(device
.get(), BackendType::Capture
);
3816 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3817 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
3818 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
3819 ALCenum err
{device
->Backend
->open(deviceName
)};
3820 if(err
!= ALC_NO_ERROR
)
3822 alcSetError(nullptr, err
);
3826 catch(al::backend_exception
&e
) {
3827 WARN("Failed to open capture device: %s\n", e
.what());
3828 alcSetError(nullptr, e
.errorCode());
3833 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3834 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3835 DeviceList
.emplace(iter
, device
);
3838 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3839 device
->DeviceName
.c_str());
3840 return device
.get();
3844 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3847 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3848 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3849 if(iter
== DeviceList
.end() || *iter
!= device
)
3851 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3854 if((*iter
)->Type
!= Capture
)
3856 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3860 DeviceRef dev
{std::move(*iter
)};
3861 DeviceList
.erase(iter
);
3864 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3865 if(dev
->Flags
.get
<DeviceRunning
>())
3866 dev
->Backend
->stop();
3867 dev
->Flags
.unset
<DeviceRunning
>();
3873 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3876 DeviceRef dev
{VerifyDevice(device
)};
3877 if(!dev
|| dev
->Type
!= Capture
)
3879 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3883 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3884 if(!dev
->Connected
.load(std::memory_order_acquire
))
3885 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3886 else if(!dev
->Flags
.get
<DeviceRunning
>())
3888 if(dev
->Backend
->start())
3889 dev
->Flags
.set
<DeviceRunning
>();
3892 aluHandleDisconnect(dev
.get(), "Device start failure");
3893 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3899 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3902 DeviceRef dev
{VerifyDevice(device
)};
3903 if(!dev
|| dev
->Type
!= Capture
)
3904 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3907 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3908 if(dev
->Flags
.get
<DeviceRunning
>())
3909 dev
->Backend
->stop();
3910 dev
->Flags
.unset
<DeviceRunning
>();
3915 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3918 DeviceRef dev
{VerifyDevice(device
)};
3919 if(!dev
|| dev
->Type
!= Capture
)
3921 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3925 if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
3927 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3933 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3934 BackendBase
*backend
{dev
->Backend
.get()};
3936 const auto usamples
= static_cast<ALCuint
>(samples
);
3937 if(usamples
> backend
->availableSamples())
3939 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3943 auto *bbuffer
= static_cast<al::byte
*>(buffer
);
3944 if(ALCenum err
{backend
->captureSamples(bbuffer
, usamples
)})
3945 alcSetError(dev
.get(), err
);
3950 /************************************************
3951 * ALC loopback functions
3952 ************************************************/
3954 /* alcLoopbackOpenDeviceSOFT
3956 * Open a loopback device, for manual rendering.
3958 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3963 /* Make sure the device name, if specified, is us. */
3964 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3966 alcSetError(nullptr, ALC_INVALID_VALUE
);
3970 DeviceRef device
{new ALCdevice
{Loopback
}};
3972 device
->SourcesMax
= 256;
3973 device
->AuxiliaryEffectSlotMax
= 64;
3974 device
->NumAuxSends
= DEFAULT_SENDS
;
3977 device
->BufferSize
= 0;
3978 device
->UpdateSize
= 0;
3980 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3981 device
->FmtChans
= DevFmtChannelsDefault
;
3982 device
->FmtType
= DevFmtTypeDefault
;
3984 if(auto srcsopt
= ConfigValueUInt(nullptr, nullptr, "sources"))
3986 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3989 if(auto slotsopt
= ConfigValueUInt(nullptr, nullptr, "slots"))
3992 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3995 if(auto sendsopt
= ConfigValueInt(nullptr, nullptr, "sends"))
3996 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3997 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3999 device
->NumStereoSources
= 1;
4000 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4003 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(device
.get(),
4004 BackendType::Playback
);
4006 // Open the "backend"
4007 device
->Backend
->open("Loopback");
4009 catch(al::backend_exception
&e
) {
4010 WARN("Failed to open loopback device: %s\n", e
.what());
4011 alcSetError(nullptr, e
.errorCode());
4016 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
4017 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
4018 DeviceList
.emplace(iter
, device
);
4021 TRACE("Created loopback device %p\n", decltype(std::declval
<void*>()){device
.get()});
4022 return device
.get();
4026 /* alcIsRenderFormatSupportedSOFT
4028 * Determines if the loopback device supports the given format for rendering.
4030 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4033 DeviceRef dev
{VerifyDevice(device
)};
4034 if(!dev
|| dev
->Type
!= Loopback
)
4035 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4037 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4040 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4048 /* alcRenderSamplesSOFT
4050 * Renders some samples into a buffer, using the format last set by the
4051 * attributes given to alcCreateContext.
4053 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4056 DeviceRef dev
{VerifyDevice(device
)};
4057 if(!dev
|| dev
->Type
!= Loopback
)
4058 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4059 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4060 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4063 BackendLockGuard _
{*dev
->Backend
};
4064 aluMixData(dev
.get(), buffer
, static_cast<ALuint
>(samples
));
4070 /************************************************
4071 * ALC DSP pause/resume functions
4072 ************************************************/
4074 /* alcDevicePauseSOFT
4076 * Pause the DSP to stop audio processing.
4078 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4081 DeviceRef dev
{VerifyDevice(device
)};
4082 if(!dev
|| dev
->Type
!= Playback
)
4083 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4086 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4087 if(dev
->Flags
.get
<DeviceRunning
>())
4088 dev
->Backend
->stop();
4089 dev
->Flags
.unset
<DeviceRunning
>();
4090 dev
->Flags
.set
<DevicePaused
>();
4095 /* alcDeviceResumeSOFT
4097 * Resume the DSP to restart audio processing.
4099 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4102 DeviceRef dev
{VerifyDevice(device
)};
4103 if(!dev
|| dev
->Type
!= Playback
)
4105 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4109 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4110 if(!dev
->Flags
.get
<DevicePaused
>())
4112 dev
->Flags
.unset
<DevicePaused
>();
4113 if(dev
->mContexts
.load()->empty())
4116 if(dev
->Backend
->start() == false)
4118 aluHandleDisconnect(dev
.get(), "Device start failure");
4119 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4122 dev
->Flags
.set
<DeviceRunning
>();
4127 /************************************************
4128 * ALC HRTF functions
4129 ************************************************/
4131 /* alcGetStringiSOFT
4133 * Gets a string parameter at the given index.
4135 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4138 DeviceRef dev
{VerifyDevice(device
)};
4139 if(!dev
|| dev
->Type
== Capture
)
4140 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4141 else switch(paramName
)
4143 case ALC_HRTF_SPECIFIER_SOFT
:
4144 if(index
>= 0 && static_cast<size_t>(index
) < dev
->HrtfList
.size())
4145 return dev
->HrtfList
[static_cast<ALuint
>(index
)].name
.c_str();
4146 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4150 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4158 /* alcResetDeviceSOFT
4160 * Resets the given device output, using the specified attribute list.
4162 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4165 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4166 DeviceRef dev
{VerifyDevice(device
)};
4167 if(!dev
|| dev
->Type
== Capture
)
4170 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4173 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4176 /* Force the backend to stop mixing first since we're resetting. Also reset
4177 * the connected state so lost devices can attempt recover.
4179 if(dev
->Flags
.get
<DeviceRunning
>())
4180 dev
->Backend
->stop();
4181 dev
->Flags
.unset
<DeviceRunning
>();
4182 device
->Connected
.store(true);
4184 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4185 if LIKELY(err
== ALC_NO_ERROR
) return ALC_TRUE
;
4187 alcSetError(dev
.get(), err
);
4188 if(err
== ALC_INVALID_DEVICE
)
4189 aluHandleDisconnect(dev
.get(), "Device start failure");