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
26 #define WIN32_LEAN_AND_MEAN
60 #include "al/auxeffectslot.h"
61 #include "al/effect.h"
63 #include "al/filter.h"
64 #include "al/listener.h"
65 #include "al/source.h"
69 #include "alcontext.h"
72 #include "alnumeric.h"
73 #include "aloptional.h"
79 #include "bformatdec.h"
83 #include "devformat.h"
84 #include "effects/base.h"
85 #include "filters/nfc.h"
86 #include "filters/splitter.h"
88 #include "front_stablizer.h"
90 #include "inprogext.h"
91 #include "intrusive_ptr.h"
93 #include "mastering.h"
94 #include "opthelpers.h"
95 #include "pragmadefs.h"
96 #include "ringbuffer.h"
99 #include "uhjfilter.h"
103 #include "backends/base.h"
104 #include "backends/null.h"
105 #include "backends/loopback.h"
107 #include "backends/jack.h"
109 #ifdef HAVE_PULSEAUDIO
110 #include "backends/pulseaudio.h"
113 #include "backends/alsa.h"
116 #include "backends/wasapi.h"
118 #ifdef HAVE_COREAUDIO
119 #include "backends/coreaudio.h"
122 #include "backends/opensl.h"
125 #include "backends/oboe.h"
128 #include "backends/solaris.h"
131 #include "backends/sndio.h"
134 #include "backends/oss.h"
137 #include "backends/dsound.h"
140 #include "backends/winmm.h"
142 #ifdef HAVE_PORTAUDIO
143 #include "backends/portaudio.h"
146 #include "backends/sdl2.h"
149 #include "backends/wave.h"
155 using namespace std::placeholders
;
156 using std::chrono::seconds
;
157 using std::chrono::nanoseconds
;
160 /************************************************
162 ************************************************/
165 BackendFactory
& (*getFactory
)(void);
168 BackendInfo BackendList
[] = {
170 { "jack", JackBackendFactory::getFactory
},
172 #ifdef HAVE_PULSEAUDIO
173 { "pulse", PulseBackendFactory::getFactory
},
176 { "alsa", AlsaBackendFactory::getFactory
},
179 { "wasapi", WasapiBackendFactory::getFactory
},
181 #ifdef HAVE_COREAUDIO
182 { "core", CoreAudioBackendFactory::getFactory
},
185 { "oboe", OboeBackendFactory::getFactory
},
188 { "opensl", OSLBackendFactory::getFactory
},
191 { "solaris", SolarisBackendFactory::getFactory
},
194 { "sndio", SndIOBackendFactory::getFactory
},
197 { "oss", OSSBackendFactory::getFactory
},
200 { "dsound", DSoundBackendFactory::getFactory
},
203 { "winmm", WinMMBackendFactory::getFactory
},
205 #ifdef HAVE_PORTAUDIO
206 { "port", PortBackendFactory::getFactory
},
209 { "sdl2", SDL2BackendFactory::getFactory
},
212 { "null", NullBackendFactory::getFactory
},
214 { "wave", WaveBackendFactory::getFactory
},
218 BackendFactory
*PlaybackFactory
{};
219 BackendFactory
*CaptureFactory
{};
222 /************************************************
223 * Functions, enums, and errors
224 ************************************************/
225 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
227 const char *funcName
;
230 DECL(alcCreateContext
),
231 DECL(alcMakeContextCurrent
),
232 DECL(alcProcessContext
),
233 DECL(alcSuspendContext
),
234 DECL(alcDestroyContext
),
235 DECL(alcGetCurrentContext
),
236 DECL(alcGetContextsDevice
),
238 DECL(alcCloseDevice
),
240 DECL(alcIsExtensionPresent
),
241 DECL(alcGetProcAddress
),
242 DECL(alcGetEnumValue
),
244 DECL(alcGetIntegerv
),
245 DECL(alcCaptureOpenDevice
),
246 DECL(alcCaptureCloseDevice
),
247 DECL(alcCaptureStart
),
248 DECL(alcCaptureStop
),
249 DECL(alcCaptureSamples
),
251 DECL(alcSetThreadContext
),
252 DECL(alcGetThreadContext
),
254 DECL(alcLoopbackOpenDeviceSOFT
),
255 DECL(alcIsRenderFormatSupportedSOFT
),
256 DECL(alcRenderSamplesSOFT
),
258 DECL(alcDevicePauseSOFT
),
259 DECL(alcDeviceResumeSOFT
),
261 DECL(alcGetStringiSOFT
),
262 DECL(alcResetDeviceSOFT
),
264 DECL(alcGetInteger64vSOFT
),
279 DECL(alIsExtensionPresent
),
280 DECL(alGetProcAddress
),
281 DECL(alGetEnumValue
),
288 DECL(alGetListenerf
),
289 DECL(alGetListener3f
),
290 DECL(alGetListenerfv
),
291 DECL(alGetListeneri
),
292 DECL(alGetListener3i
),
293 DECL(alGetListeneriv
),
295 DECL(alDeleteSources
),
311 DECL(alSourceRewindv
),
312 DECL(alSourcePausev
),
315 DECL(alSourceRewind
),
317 DECL(alSourceQueueBuffers
),
318 DECL(alSourceUnqueueBuffers
),
320 DECL(alDeleteBuffers
),
335 DECL(alDopplerFactor
),
336 DECL(alDopplerVelocity
),
337 DECL(alSpeedOfSound
),
338 DECL(alDistanceModel
),
341 DECL(alDeleteFilters
),
352 DECL(alDeleteEffects
),
362 DECL(alGenAuxiliaryEffectSlots
),
363 DECL(alDeleteAuxiliaryEffectSlots
),
364 DECL(alIsAuxiliaryEffectSlot
),
365 DECL(alAuxiliaryEffectSloti
),
366 DECL(alAuxiliaryEffectSlotiv
),
367 DECL(alAuxiliaryEffectSlotf
),
368 DECL(alAuxiliaryEffectSlotfv
),
369 DECL(alGetAuxiliaryEffectSloti
),
370 DECL(alGetAuxiliaryEffectSlotiv
),
371 DECL(alGetAuxiliaryEffectSlotf
),
372 DECL(alGetAuxiliaryEffectSlotfv
),
374 DECL(alDeferUpdatesSOFT
),
375 DECL(alProcessUpdatesSOFT
),
378 DECL(alSource3dSOFT
),
379 DECL(alSourcedvSOFT
),
380 DECL(alGetSourcedSOFT
),
381 DECL(alGetSource3dSOFT
),
382 DECL(alGetSourcedvSOFT
),
383 DECL(alSourcei64SOFT
),
384 DECL(alSource3i64SOFT
),
385 DECL(alSourcei64vSOFT
),
386 DECL(alGetSourcei64SOFT
),
387 DECL(alGetSource3i64SOFT
),
388 DECL(alGetSourcei64vSOFT
),
390 DECL(alGetStringiSOFT
),
392 DECL(alBufferStorageSOFT
),
393 DECL(alMapBufferSOFT
),
394 DECL(alUnmapBufferSOFT
),
395 DECL(alFlushMappedBufferSOFT
),
397 DECL(alEventControlSOFT
),
398 DECL(alEventCallbackSOFT
),
399 DECL(alGetPointerSOFT
),
400 DECL(alGetPointervSOFT
),
402 DECL(alBufferCallbackSOFT
),
403 DECL(alGetBufferPtrSOFT
),
404 DECL(alGetBuffer3PtrSOFT
),
405 DECL(alGetBufferPtrvSOFT
),
409 #define DECL(x) { #x, (x) }
411 const ALCchar
*enumName
;
413 } alcEnumerations
[] = {
418 DECL(ALC_MAJOR_VERSION
),
419 DECL(ALC_MINOR_VERSION
),
420 DECL(ALC_ATTRIBUTES_SIZE
),
421 DECL(ALC_ALL_ATTRIBUTES
),
422 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
423 DECL(ALC_DEVICE_SPECIFIER
),
424 DECL(ALC_ALL_DEVICES_SPECIFIER
),
425 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
426 DECL(ALC_EXTENSIONS
),
430 DECL(ALC_MONO_SOURCES
),
431 DECL(ALC_STEREO_SOURCES
),
432 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
433 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
434 DECL(ALC_CAPTURE_SAMPLES
),
437 DECL(ALC_EFX_MAJOR_VERSION
),
438 DECL(ALC_EFX_MINOR_VERSION
),
439 DECL(ALC_MAX_AUXILIARY_SENDS
),
441 DECL(ALC_FORMAT_CHANNELS_SOFT
),
442 DECL(ALC_FORMAT_TYPE_SOFT
),
445 DECL(ALC_STEREO_SOFT
),
447 DECL(ALC_5POINT1_SOFT
),
448 DECL(ALC_6POINT1_SOFT
),
449 DECL(ALC_7POINT1_SOFT
),
450 DECL(ALC_BFORMAT3D_SOFT
),
453 DECL(ALC_UNSIGNED_BYTE_SOFT
),
454 DECL(ALC_SHORT_SOFT
),
455 DECL(ALC_UNSIGNED_SHORT_SOFT
),
457 DECL(ALC_UNSIGNED_INT_SOFT
),
458 DECL(ALC_FLOAT_SOFT
),
461 DECL(ALC_DONT_CARE_SOFT
),
462 DECL(ALC_HRTF_STATUS_SOFT
),
463 DECL(ALC_HRTF_DISABLED_SOFT
),
464 DECL(ALC_HRTF_ENABLED_SOFT
),
465 DECL(ALC_HRTF_DENIED_SOFT
),
466 DECL(ALC_HRTF_REQUIRED_SOFT
),
467 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
468 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
469 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
470 DECL(ALC_HRTF_SPECIFIER_SOFT
),
471 DECL(ALC_HRTF_ID_SOFT
),
473 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
474 DECL(ALC_AMBISONIC_SCALING_SOFT
),
475 DECL(ALC_AMBISONIC_ORDER_SOFT
),
481 DECL(ALC_OUTPUT_LIMITER_SOFT
),
484 DECL(ALC_INVALID_DEVICE
),
485 DECL(ALC_INVALID_CONTEXT
),
486 DECL(ALC_INVALID_ENUM
),
487 DECL(ALC_INVALID_VALUE
),
488 DECL(ALC_OUT_OF_MEMORY
),
496 DECL(AL_SOURCE_RELATIVE
),
497 DECL(AL_CONE_INNER_ANGLE
),
498 DECL(AL_CONE_OUTER_ANGLE
),
508 DECL(AL_ORIENTATION
),
509 DECL(AL_REFERENCE_DISTANCE
),
510 DECL(AL_ROLLOFF_FACTOR
),
511 DECL(AL_CONE_OUTER_GAIN
),
512 DECL(AL_MAX_DISTANCE
),
514 DECL(AL_SAMPLE_OFFSET
),
515 DECL(AL_BYTE_OFFSET
),
516 DECL(AL_SOURCE_TYPE
),
519 DECL(AL_UNDETERMINED
),
520 DECL(AL_METERS_PER_UNIT
),
521 DECL(AL_LOOP_POINTS_SOFT
),
522 DECL(AL_DIRECT_CHANNELS_SOFT
),
524 DECL(AL_DIRECT_FILTER
),
525 DECL(AL_AUXILIARY_SEND_FILTER
),
526 DECL(AL_AIR_ABSORPTION_FACTOR
),
527 DECL(AL_ROOM_ROLLOFF_FACTOR
),
528 DECL(AL_CONE_OUTER_GAINHF
),
529 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
530 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
531 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
533 DECL(AL_SOURCE_STATE
),
539 DECL(AL_BUFFERS_QUEUED
),
540 DECL(AL_BUFFERS_PROCESSED
),
542 DECL(AL_FORMAT_MONO8
),
543 DECL(AL_FORMAT_MONO16
),
544 DECL(AL_FORMAT_MONO_FLOAT32
),
545 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
546 DECL(AL_FORMAT_STEREO8
),
547 DECL(AL_FORMAT_STEREO16
),
548 DECL(AL_FORMAT_STEREO_FLOAT32
),
549 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
550 DECL(AL_FORMAT_MONO_IMA4
),
551 DECL(AL_FORMAT_STEREO_IMA4
),
552 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
553 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
554 DECL(AL_FORMAT_QUAD8_LOKI
),
555 DECL(AL_FORMAT_QUAD16_LOKI
),
556 DECL(AL_FORMAT_QUAD8
),
557 DECL(AL_FORMAT_QUAD16
),
558 DECL(AL_FORMAT_QUAD32
),
559 DECL(AL_FORMAT_51CHN8
),
560 DECL(AL_FORMAT_51CHN16
),
561 DECL(AL_FORMAT_51CHN32
),
562 DECL(AL_FORMAT_61CHN8
),
563 DECL(AL_FORMAT_61CHN16
),
564 DECL(AL_FORMAT_61CHN32
),
565 DECL(AL_FORMAT_71CHN8
),
566 DECL(AL_FORMAT_71CHN16
),
567 DECL(AL_FORMAT_71CHN32
),
568 DECL(AL_FORMAT_REAR8
),
569 DECL(AL_FORMAT_REAR16
),
570 DECL(AL_FORMAT_REAR32
),
571 DECL(AL_FORMAT_MONO_MULAW
),
572 DECL(AL_FORMAT_MONO_MULAW_EXT
),
573 DECL(AL_FORMAT_STEREO_MULAW
),
574 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
575 DECL(AL_FORMAT_QUAD_MULAW
),
576 DECL(AL_FORMAT_51CHN_MULAW
),
577 DECL(AL_FORMAT_61CHN_MULAW
),
578 DECL(AL_FORMAT_71CHN_MULAW
),
579 DECL(AL_FORMAT_REAR_MULAW
),
580 DECL(AL_FORMAT_MONO_ALAW_EXT
),
581 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
583 DECL(AL_FORMAT_BFORMAT2D_8
),
584 DECL(AL_FORMAT_BFORMAT2D_16
),
585 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
586 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
587 DECL(AL_FORMAT_BFORMAT3D_8
),
588 DECL(AL_FORMAT_BFORMAT3D_16
),
589 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
590 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
596 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
597 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
599 DECL(AL_SOURCE_RADIUS
),
601 DECL(AL_STEREO_ANGLES
),
608 DECL(AL_INVALID_NAME
),
609 DECL(AL_INVALID_ENUM
),
610 DECL(AL_INVALID_VALUE
),
611 DECL(AL_INVALID_OPERATION
),
612 DECL(AL_OUT_OF_MEMORY
),
619 DECL(AL_DOPPLER_FACTOR
),
620 DECL(AL_DOPPLER_VELOCITY
),
621 DECL(AL_DISTANCE_MODEL
),
622 DECL(AL_SPEED_OF_SOUND
),
623 DECL(AL_SOURCE_DISTANCE_MODEL
),
624 DECL(AL_DEFERRED_UPDATES_SOFT
),
625 DECL(AL_GAIN_LIMIT_SOFT
),
627 DECL(AL_INVERSE_DISTANCE
),
628 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
629 DECL(AL_LINEAR_DISTANCE
),
630 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
631 DECL(AL_EXPONENT_DISTANCE
),
632 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
634 DECL(AL_FILTER_TYPE
),
635 DECL(AL_FILTER_NULL
),
636 DECL(AL_FILTER_LOWPASS
),
637 DECL(AL_FILTER_HIGHPASS
),
638 DECL(AL_FILTER_BANDPASS
),
640 DECL(AL_LOWPASS_GAIN
),
641 DECL(AL_LOWPASS_GAINHF
),
643 DECL(AL_HIGHPASS_GAIN
),
644 DECL(AL_HIGHPASS_GAINLF
),
646 DECL(AL_BANDPASS_GAIN
),
647 DECL(AL_BANDPASS_GAINHF
),
648 DECL(AL_BANDPASS_GAINLF
),
650 DECL(AL_EFFECT_TYPE
),
651 DECL(AL_EFFECT_NULL
),
652 DECL(AL_EFFECT_REVERB
),
653 DECL(AL_EFFECT_EAXREVERB
),
654 DECL(AL_EFFECT_CHORUS
),
655 DECL(AL_EFFECT_DISTORTION
),
656 DECL(AL_EFFECT_ECHO
),
657 DECL(AL_EFFECT_FLANGER
),
658 DECL(AL_EFFECT_PITCH_SHIFTER
),
659 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
660 DECL(AL_EFFECT_VOCAL_MORPHER
),
661 DECL(AL_EFFECT_RING_MODULATOR
),
662 DECL(AL_EFFECT_AUTOWAH
),
663 DECL(AL_EFFECT_COMPRESSOR
),
664 DECL(AL_EFFECT_EQUALIZER
),
665 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
666 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
668 DECL(AL_EFFECTSLOT_EFFECT
),
669 DECL(AL_EFFECTSLOT_GAIN
),
670 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
671 DECL(AL_EFFECTSLOT_NULL
),
673 DECL(AL_EAXREVERB_DENSITY
),
674 DECL(AL_EAXREVERB_DIFFUSION
),
675 DECL(AL_EAXREVERB_GAIN
),
676 DECL(AL_EAXREVERB_GAINHF
),
677 DECL(AL_EAXREVERB_GAINLF
),
678 DECL(AL_EAXREVERB_DECAY_TIME
),
679 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
680 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
681 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
682 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
683 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
684 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
685 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
686 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
687 DECL(AL_EAXREVERB_ECHO_TIME
),
688 DECL(AL_EAXREVERB_ECHO_DEPTH
),
689 DECL(AL_EAXREVERB_MODULATION_TIME
),
690 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
691 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
692 DECL(AL_EAXREVERB_HFREFERENCE
),
693 DECL(AL_EAXREVERB_LFREFERENCE
),
694 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
695 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
697 DECL(AL_REVERB_DENSITY
),
698 DECL(AL_REVERB_DIFFUSION
),
699 DECL(AL_REVERB_GAIN
),
700 DECL(AL_REVERB_GAINHF
),
701 DECL(AL_REVERB_DECAY_TIME
),
702 DECL(AL_REVERB_DECAY_HFRATIO
),
703 DECL(AL_REVERB_REFLECTIONS_GAIN
),
704 DECL(AL_REVERB_REFLECTIONS_DELAY
),
705 DECL(AL_REVERB_LATE_REVERB_GAIN
),
706 DECL(AL_REVERB_LATE_REVERB_DELAY
),
707 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
708 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
709 DECL(AL_REVERB_DECAY_HFLIMIT
),
711 DECL(AL_CHORUS_WAVEFORM
),
712 DECL(AL_CHORUS_PHASE
),
713 DECL(AL_CHORUS_RATE
),
714 DECL(AL_CHORUS_DEPTH
),
715 DECL(AL_CHORUS_FEEDBACK
),
716 DECL(AL_CHORUS_DELAY
),
718 DECL(AL_DISTORTION_EDGE
),
719 DECL(AL_DISTORTION_GAIN
),
720 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
721 DECL(AL_DISTORTION_EQCENTER
),
722 DECL(AL_DISTORTION_EQBANDWIDTH
),
725 DECL(AL_ECHO_LRDELAY
),
726 DECL(AL_ECHO_DAMPING
),
727 DECL(AL_ECHO_FEEDBACK
),
728 DECL(AL_ECHO_SPREAD
),
730 DECL(AL_FLANGER_WAVEFORM
),
731 DECL(AL_FLANGER_PHASE
),
732 DECL(AL_FLANGER_RATE
),
733 DECL(AL_FLANGER_DEPTH
),
734 DECL(AL_FLANGER_FEEDBACK
),
735 DECL(AL_FLANGER_DELAY
),
737 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
738 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
739 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
741 DECL(AL_RING_MODULATOR_FREQUENCY
),
742 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
743 DECL(AL_RING_MODULATOR_WAVEFORM
),
745 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
746 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
748 DECL(AL_COMPRESSOR_ONOFF
),
750 DECL(AL_EQUALIZER_LOW_GAIN
),
751 DECL(AL_EQUALIZER_LOW_CUTOFF
),
752 DECL(AL_EQUALIZER_MID1_GAIN
),
753 DECL(AL_EQUALIZER_MID1_CENTER
),
754 DECL(AL_EQUALIZER_MID1_WIDTH
),
755 DECL(AL_EQUALIZER_MID2_GAIN
),
756 DECL(AL_EQUALIZER_MID2_CENTER
),
757 DECL(AL_EQUALIZER_MID2_WIDTH
),
758 DECL(AL_EQUALIZER_HIGH_GAIN
),
759 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
761 DECL(AL_DEDICATED_GAIN
),
763 DECL(AL_AUTOWAH_ATTACK_TIME
),
764 DECL(AL_AUTOWAH_RELEASE_TIME
),
765 DECL(AL_AUTOWAH_RESONANCE
),
766 DECL(AL_AUTOWAH_PEAK_GAIN
),
768 DECL(AL_VOCAL_MORPHER_PHONEMEA
),
769 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
770 DECL(AL_VOCAL_MORPHER_PHONEMEB
),
771 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
772 DECL(AL_VOCAL_MORPHER_WAVEFORM
),
773 DECL(AL_VOCAL_MORPHER_RATE
),
775 DECL(AL_NUM_RESAMPLERS_SOFT
),
776 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
777 DECL(AL_SOURCE_RESAMPLER_SOFT
),
778 DECL(AL_RESAMPLER_NAME_SOFT
),
780 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
783 DECL(AL_MAP_READ_BIT_SOFT
),
784 DECL(AL_MAP_WRITE_BIT_SOFT
),
785 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
786 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
788 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
789 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
790 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
791 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
792 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
793 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
794 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
796 DECL(AL_DROP_UNMATCHED_SOFT
),
797 DECL(AL_REMIX_UNMATCHED_SOFT
),
799 DECL(AL_AMBISONIC_LAYOUT_SOFT
),
800 DECL(AL_AMBISONIC_SCALING_SOFT
),
806 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT
),
807 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT
),
809 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT
),
813 constexpr ALCchar alcNoError
[] = "No Error";
814 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
815 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
816 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
817 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
818 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
821 /************************************************
823 ************************************************/
825 /* Enumerated device names */
826 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
828 std::string alcAllDevicesList
;
829 std::string alcCaptureDeviceList
;
831 /* Default is always the first in the list */
832 al::string alcDefaultAllDevicesSpecifier
;
833 al::string alcCaptureDefaultDeviceSpecifier
;
835 /* Default context extensions */
836 constexpr ALchar alExtList
[] =
840 "AL_EXT_EXPONENT_DISTANCE "
843 "AL_EXT_LINEAR_DISTANCE "
846 "AL_EXT_MULAW_BFORMAT "
847 "AL_EXT_MULAW_MCFORMATS "
849 "AL_EXT_source_distance_model "
850 "AL_EXT_SOURCE_RADIUS "
851 "AL_EXT_STEREO_ANGLES "
852 "AL_LOKI_quadriphonic "
853 "AL_SOFT_bformat_ex "
854 "AL_SOFTX_bformat_hoa "
855 "AL_SOFT_block_alignment "
856 "AL_SOFTX_callback_buffer "
857 "AL_SOFT_deferred_updates "
858 "AL_SOFT_direct_channels "
859 "AL_SOFT_direct_channels_remix "
860 "AL_SOFTX_effect_target "
862 "AL_SOFTX_filter_gain_ex "
863 "AL_SOFT_gain_clamp_ex "
864 "AL_SOFT_loop_points "
865 "AL_SOFTX_map_buffer "
867 "AL_SOFT_source_latency "
868 "AL_SOFT_source_length "
869 "AL_SOFT_source_resampler "
870 "AL_SOFT_source_spatialize";
872 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
874 /* Thread-local current context. The handling may look a little obtuse, but
875 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
876 * thread-local object destructors to get a junk 'this' pointer. This method
877 * has the benefit of making LocalContext access more efficient since it's a
878 * a plain pointer, with the ThreadContext object used to check it at thread
879 * exit (and given no data fields, 'this' being junk is inconsequential since
880 * it's never accessed).
882 thread_local ALCcontext
*LocalContext
{nullptr};
887 if(ALCcontext
*ctx
{LocalContext
})
889 const bool result
{ctx
->releaseIfNoDelete()};
890 ERR("Context %p current for thread being destroyed%s!\n",
891 decltype(std::declval
<void*>()){ctx
}, result
? "" : ", leak detected");
895 void set(ALCcontext
*ctx
) const noexcept
{ LocalContext
= ctx
; }
897 thread_local ThreadCtx ThreadContext
;
899 /* Process-wide current context */
900 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
902 /* Flag to trap ALC device errors */
903 bool TrapALCError
{false};
905 /* One-time configuration init control */
906 std::once_flag alc_config_once
{};
908 /* Default effect that applies to sources that don't have an effect on send 0 */
909 ALeffect DefaultEffect
;
911 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
914 bool SuspendDefers
{true};
916 /* Initial seed for dithering. */
917 constexpr ALuint DitherRNGSeed
{22222u};
920 /************************************************
922 ************************************************/
923 constexpr ALCchar alcNoDeviceExtList
[] =
924 "ALC_ENUMERATE_ALL_EXT "
925 "ALC_ENUMERATION_EXT "
927 "ALC_EXT_thread_local_context "
929 constexpr ALCchar alcExtensionList
[] =
930 "ALC_ENUMERATE_ALL_EXT "
931 "ALC_ENUMERATION_EXT "
934 "ALC_EXT_disconnect "
936 "ALC_EXT_thread_local_context "
937 "ALC_SOFT_device_clock "
940 "ALC_SOFT_output_limiter "
941 "ALC_SOFT_pause_device";
942 constexpr int alcMajorVersion
{1};
943 constexpr int alcMinorVersion
{1};
945 constexpr int alcEFXMajorVersion
{1};
946 constexpr int alcEFXMinorVersion
{0};
949 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
950 * globally as a sharable object.
952 al::FlexArray
<ALCcontext
*> EmptyContextArray
{0u};
955 using DeviceRef
= al::intrusive_ptr
<ALCdevice
>;
958 /************************************************
960 ************************************************/
961 al::vector
<ALCdevice
*> DeviceList
;
962 al::vector
<ALCcontext
*> ContextList
;
964 std::recursive_mutex ListLock
;
967 void alc_initconfig(void)
969 if(auto loglevel
= al::getenv("ALSOFT_LOGLEVEL"))
971 long lvl
= strtol(loglevel
->c_str(), nullptr, 0);
972 if(lvl
>= NoLog
&& lvl
<= LogRef
)
973 gLogLevel
= static_cast<LogLevel
>(lvl
);
977 if(const auto logfile
= al::getenv(L
"ALSOFT_LOGFILE"))
979 FILE *logf
{_wfopen(logfile
->c_str(), L
"wt")};
980 if(logf
) gLogFile
= logf
;
983 auto u8name
= wstr_to_utf8(logfile
->c_str());
984 ERR("Failed to open log file '%s'\n", u8name
.c_str());
988 if(const auto logfile
= al::getenv("ALSOFT_LOGFILE"))
990 FILE *logf
{fopen(logfile
->c_str(), "wt")};
991 if(logf
) gLogFile
= logf
;
992 else ERR("Failed to open log file '%s'\n", logfile
->c_str());
996 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
, ALSOFT_GIT_COMMIT_HASH
,
1000 if(al::size(BackendList
) < 1)
1004 const al::span
<const BackendInfo
> infos
{BackendList
};
1005 names
= infos
[0].name
;
1006 for(const auto &backend
: infos
.subspan
<1>())
1009 names
+= backend
.name
;
1012 TRACE("Supported backends: %s\n", names
.c_str());
1016 if(auto suspendmode
= al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1018 if(al::strcasecmp(suspendmode
->c_str(), "ignore") == 0)
1020 SuspendDefers
= false;
1021 TRACE("Selected context suspend behavior, \"ignore\"\n");
1024 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode
->c_str());
1028 #if defined(HAVE_SSE4_1)
1029 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1030 #elif defined(HAVE_SSE3)
1031 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1032 #elif defined(HAVE_SSE2)
1033 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1034 #elif defined(HAVE_SSE)
1035 capfilter
|= CPU_CAP_SSE
;
1038 capfilter
|= CPU_CAP_NEON
;
1040 if(auto cpuopt
= ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1042 const char *str
{cpuopt
->c_str()};
1043 if(al::strcasecmp(str
, "all") == 0)
1047 const char *next
= str
;
1050 while(isspace(str
[0]))
1052 next
= strchr(str
, ',');
1054 if(!str
[0] || str
[0] == ',')
1057 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1058 while(len
> 0 && isspace(str
[len
-1]))
1060 if(len
== 3 && al::strncasecmp(str
, "sse", len
) == 0)
1061 capfilter
&= ~CPU_CAP_SSE
;
1062 else if(len
== 4 && al::strncasecmp(str
, "sse2", len
) == 0)
1063 capfilter
&= ~CPU_CAP_SSE2
;
1064 else if(len
== 4 && al::strncasecmp(str
, "sse3", len
) == 0)
1065 capfilter
&= ~CPU_CAP_SSE3
;
1066 else if(len
== 6 && al::strncasecmp(str
, "sse4.1", len
) == 0)
1067 capfilter
&= ~CPU_CAP_SSE4_1
;
1068 else if(len
== 4 && al::strncasecmp(str
, "neon", len
) == 0)
1069 capfilter
&= ~CPU_CAP_NEON
;
1071 WARN("Invalid CPU extension \"%s\"\n", str
);
1075 FillCPUCaps(capfilter
);
1077 if(auto priopt
= ConfigValueInt(nullptr, nullptr, "rt-prio"))
1078 RTPrioLevel
= *priopt
;
1083 auto traperr
= al::getenv("ALSOFT_TRAP_ERROR");
1084 if(traperr
&& (al::strcasecmp(traperr
->c_str(), "true") == 0
1085 || std::strtol(traperr
->c_str(), nullptr, 0) == 1))
1088 TrapALCError
= true;
1092 traperr
= al::getenv("ALSOFT_TRAP_AL_ERROR");
1094 TrapALError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1095 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1097 TrapALError
= !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1099 traperr
= al::getenv("ALSOFT_TRAP_ALC_ERROR");
1101 TrapALCError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1102 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1104 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1107 if(auto boostopt
= ConfigValueFloat(nullptr, "reverb", "boost"))
1109 const float valf
{std::isfinite(*boostopt
) ? clampf(*boostopt
, -24.0f
, 24.0f
) : 0.0f
};
1110 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1113 auto BackendListEnd
= std::end(BackendList
);
1114 auto devopt
= al::getenv("ALSOFT_DRIVERS");
1115 if(devopt
|| (devopt
=ConfigValueStr(nullptr, nullptr, "drivers")))
1117 auto backendlist_cur
= std::begin(BackendList
);
1120 const char *next
{devopt
->c_str()};
1122 const char *devs
{next
};
1123 while(isspace(devs
[0]))
1125 next
= strchr(devs
, ',');
1127 const bool delitem
{devs
[0] == '-'};
1128 if(devs
[0] == '-') devs
++;
1130 if(!devs
[0] || devs
[0] == ',')
1137 size_t len
{next
? (static_cast<size_t>(next
-devs
)) : strlen(devs
)};
1138 while(len
> 0 && isspace(devs
[len
-1])) --len
;
1140 /* HACK: For backwards compatibility, convert backend references of
1141 * mmdevapi to wasapi. This should eventually be removed.
1143 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1150 auto find_backend
= [devs
,len
](const BackendInfo
&backend
) -> bool
1151 { return len
== strlen(backend
.name
) && strncmp(backend
.name
, devs
, len
) == 0; };
1152 auto this_backend
= std::find_if(std::begin(BackendList
), BackendListEnd
,
1155 if(this_backend
== BackendListEnd
)
1159 BackendListEnd
= std::move(this_backend
+1, BackendListEnd
, this_backend
);
1161 backendlist_cur
= std::rotate(backendlist_cur
, this_backend
, this_backend
+1);
1165 BackendListEnd
= backendlist_cur
;
1168 auto init_backend
= [](BackendInfo
&backend
) -> void
1170 if(PlaybackFactory
&& CaptureFactory
)
1173 BackendFactory
&factory
= backend
.getFactory();
1176 WARN("Failed to initialize backend \"%s\"\n", backend
.name
);
1180 TRACE("Initialized backend \"%s\"\n", backend
.name
);
1181 if(!PlaybackFactory
&& factory
.querySupport(BackendType::Playback
))
1183 PlaybackFactory
= &factory
;
1184 TRACE("Added \"%s\" for playback\n", backend
.name
);
1186 if(!CaptureFactory
&& factory
.querySupport(BackendType::Capture
))
1188 CaptureFactory
= &factory
;
1189 TRACE("Added \"%s\" for capture\n", backend
.name
);
1192 std::for_each(std::begin(BackendList
), BackendListEnd
, init_backend
);
1194 LoopbackBackendFactory::getFactory().init();
1196 if(!PlaybackFactory
)
1197 WARN("No playback backend available!\n");
1199 WARN("No capture backend available!\n");
1201 if(auto exclopt
= ConfigValueStr(nullptr, nullptr, "excludefx"))
1203 const char *next
{exclopt
->c_str()};
1205 const char *str
{next
};
1206 next
= strchr(str
, ',');
1208 if(!str
[0] || next
== str
)
1211 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1212 for(const EffectList
&effectitem
: gEffectList
)
1214 if(len
== strlen(effectitem
.name
) &&
1215 strncmp(effectitem
.name
, str
, len
) == 0)
1216 DisabledEffects
[effectitem
.type
] = true;
1221 InitEffect(&DefaultEffect
);
1222 auto defrevopt
= al::getenv("ALSOFT_DEFAULT_REVERB");
1223 if(defrevopt
|| (defrevopt
=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1224 LoadReverbPreset(defrevopt
->c_str(), &DefaultEffect
);
1226 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1229 /************************************************
1230 * Device enumeration
1231 ************************************************/
1232 void ProbeAllDevicesList()
1236 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1237 if(!PlaybackFactory
)
1238 decltype(alcAllDevicesList
){}.swap(alcAllDevicesList
);
1241 std::string names
{PlaybackFactory
->probe(BackendType::Playback
)};
1242 if(names
.empty()) names
+= '\0';
1243 names
.swap(alcAllDevicesList
);
1246 void ProbeCaptureDeviceList()
1250 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1252 decltype(alcCaptureDeviceList
){}.swap(alcCaptureDeviceList
);
1255 std::string names
{CaptureFactory
->probe(BackendType::Capture
)};
1256 if(names
.empty()) names
+= '\0';
1257 names
.swap(alcCaptureDeviceList
);
1263 /* Mixing thread piority level */
1266 FILE *gLogFile
{stderr
};
1268 LogLevel gLogLevel
{LogWarning
};
1270 LogLevel gLogLevel
{LogError
};
1273 /************************************************
1274 * Library initialization
1275 ************************************************/
1276 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1277 BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID
/*reserved*/)
1281 case DLL_PROCESS_ATTACH
:
1282 /* Pin the DLL so we won't get unloaded until the process terminates */
1283 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
1284 reinterpret_cast<WCHAR
*>(module
), &module
);
1291 /************************************************
1292 * Device format information
1293 ************************************************/
1294 const ALCchar
*DevFmtTypeString(DevFmtType type
) noexcept
1298 case DevFmtByte
: return "Int8";
1299 case DevFmtUByte
: return "UInt8";
1300 case DevFmtShort
: return "Int16";
1301 case DevFmtUShort
: return "UInt16";
1302 case DevFmtInt
: return "Int32";
1303 case DevFmtUInt
: return "UInt32";
1304 case DevFmtFloat
: return "Float32";
1306 return "(unknown type)";
1308 const ALCchar
*DevFmtChannelsString(DevFmtChannels chans
) noexcept
1312 case DevFmtMono
: return "Mono";
1313 case DevFmtStereo
: return "Stereo";
1314 case DevFmtQuad
: return "Quadraphonic";
1315 case DevFmtX51
: return "5.1 Surround";
1316 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1317 case DevFmtX61
: return "6.1 Surround";
1318 case DevFmtX71
: return "7.1 Surround";
1319 case DevFmtAmbi3D
: return "Ambisonic 3D";
1321 return "(unknown channels)";
1324 ALuint
BytesFromDevFmt(DevFmtType type
) noexcept
1328 case DevFmtByte
: return sizeof(int8_t);
1329 case DevFmtUByte
: return sizeof(uint8_t);
1330 case DevFmtShort
: return sizeof(int16_t);
1331 case DevFmtUShort
: return sizeof(uint16_t);
1332 case DevFmtInt
: return sizeof(int32_t);
1333 case DevFmtUInt
: return sizeof(uint32_t);
1334 case DevFmtFloat
: return sizeof(float);
1338 ALuint
ChannelsFromDevFmt(DevFmtChannels chans
, ALuint ambiorder
) noexcept
1342 case DevFmtMono
: return 1;
1343 case DevFmtStereo
: return 2;
1344 case DevFmtQuad
: return 4;
1345 case DevFmtX51
: return 6;
1346 case DevFmtX51Rear
: return 6;
1347 case DevFmtX61
: return 7;
1348 case DevFmtX71
: return 8;
1349 case DevFmtAmbi3D
: return (ambiorder
+1) * (ambiorder
+1);
1356 struct DevFmtPair
{ DevFmtChannels chans
; DevFmtType type
; };
1357 al::optional
<DevFmtPair
> DecomposeDevFormat(ALenum format
)
1359 static const struct {
1361 DevFmtChannels channels
;
1364 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1365 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1366 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1368 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1369 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1370 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1372 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1373 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1374 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1376 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1377 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1378 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1380 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1381 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1382 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1384 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1385 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1386 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1389 for(const auto &item
: list
)
1391 if(item
.format
== format
)
1392 return al::make_optional(DevFmtPair
{item
.channels
, item
.type
});
1398 bool IsValidALCType(ALCenum type
)
1403 case ALC_UNSIGNED_BYTE_SOFT
:
1404 case ALC_SHORT_SOFT
:
1405 case ALC_UNSIGNED_SHORT_SOFT
:
1407 case ALC_UNSIGNED_INT_SOFT
:
1408 case ALC_FLOAT_SOFT
:
1414 bool IsValidALCChannels(ALCenum channels
)
1419 case ALC_STEREO_SOFT
:
1421 case ALC_5POINT1_SOFT
:
1422 case ALC_6POINT1_SOFT
:
1423 case ALC_7POINT1_SOFT
:
1424 case ALC_BFORMAT3D_SOFT
:
1430 bool IsValidAmbiLayout(ALCenum layout
)
1441 bool IsValidAmbiScaling(ALCenum scaling
)
1454 /* Downmixing channel arrays, to map the given format's missing channels to
1455 * existing ones. Based on Wine's DSound downmix values, which are based on
1458 const std::array
<InputRemixMap
,7> MonoDownmix
{{
1459 { FrontLeft
, {{{FrontCenter
, 0.5f
}, {LFE
, 0.0f
}}} },
1460 { FrontRight
, {{{FrontCenter
, 0.5f
}, {LFE
, 0.0f
}}} },
1461 { SideLeft
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1462 { SideRight
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1463 { BackLeft
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1464 { BackRight
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1465 { BackCenter
, {{{FrontCenter
, 1.0f
/9.0f
}, {LFE
, 0.0f
}}} },
1467 const std::array
<InputRemixMap
,6> StereoDownmix
{{
1468 { FrontCenter
, {{{FrontLeft
, 0.5f
}, {FrontRight
, 0.5f
}}} },
1469 { SideLeft
, {{{FrontLeft
, 1.0f
/9.0f
}, {FrontRight
, 0.0f
}}} },
1470 { SideRight
, {{{FrontLeft
, 0.0f
}, {FrontRight
, 1.0f
/9.0f
}}} },
1471 { BackLeft
, {{{FrontLeft
, 1.0f
/9.0f
}, {FrontRight
, 0.0f
}}} },
1472 { BackRight
, {{{FrontLeft
, 0.0f
}, {FrontRight
, 1.0f
/9.0f
}}} },
1473 { BackCenter
, {{{FrontLeft
, 0.5f
/9.0f
}, {FrontRight
, 0.5f
/9.0f
}}} },
1475 const std::array
<InputRemixMap
,4> QuadDownmix
{{
1476 { FrontCenter
, {{{FrontLeft
, 0.5f
}, {FrontRight
, 0.5f
}}} },
1477 { SideLeft
, {{{FrontLeft
, 0.5f
}, {BackLeft
, 0.5f
}}} },
1478 { SideRight
, {{{FrontRight
, 0.5f
}, {BackRight
, 0.5f
}}} },
1479 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1481 const std::array
<InputRemixMap
,3> X51Downmix
{{
1482 { BackLeft
, {{{SideLeft
, 1.0f
}, {SideRight
, 0.0f
}}} },
1483 { BackRight
, {{{SideLeft
, 0.0f
}, {SideRight
, 1.0f
}}} },
1484 { BackCenter
, {{{SideLeft
, 0.5f
}, {SideRight
, 0.5f
}}} },
1486 const std::array
<InputRemixMap
,3> X51RearDownmix
{{
1487 { SideLeft
, {{{BackLeft
, 1.0f
}, {BackRight
, 0.0f
}}} },
1488 { SideRight
, {{{BackLeft
, 0.0f
}, {BackRight
, 1.0f
}}} },
1489 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1491 const std::array
<InputRemixMap
,2> X61Downmix
{{
1492 { BackLeft
, {{{BackCenter
, 0.5f
}, {SideLeft
, 0.5f
}}} },
1493 { BackRight
, {{{BackCenter
, 0.5f
}, {SideRight
, 0.5f
}}} },
1495 const std::array
<InputRemixMap
,1> X71Downmix
{{
1496 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1501 /************************************************
1502 * Miscellaneous ALC helpers
1503 ************************************************/
1505 void ALCcontext::processUpdates()
1507 std::lock_guard
<std::mutex
> _
{mPropLock
};
1508 if(mDeferUpdates
.exchange(false, std::memory_order_acq_rel
))
1510 /* Tell the mixer to stop applying updates, then wait for any active
1511 * updating to finish, before providing updates.
1513 mHoldUpdates
.store(true, std::memory_order_release
);
1514 while((mUpdateCount
.load(std::memory_order_acquire
)&1) != 0) {
1518 if(!mPropsClean
.test_and_set(std::memory_order_acq_rel
))
1519 UpdateContextProps(this);
1520 if(!mListener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1521 UpdateListenerProps(this);
1522 UpdateAllEffectSlotProps(this);
1523 UpdateAllSourceProps(this);
1525 /* Now with all updates declared, let the mixer continue applying them
1526 * so they all happen at once.
1528 mHoldUpdates
.store(false, std::memory_order_release
);
1533 void ALCcontext::allocVoiceChanges(size_t addcount
)
1535 constexpr size_t clustersize
{128};
1536 /* Convert element count to cluster count. */
1537 addcount
= (addcount
+(clustersize
-1)) / clustersize
;
1540 VoiceChangeCluster cluster
{std::make_unique
<VoiceChange
[]>(clustersize
)};
1541 for(size_t i
{1};i
< clustersize
;++i
)
1542 cluster
[i
-1].mNext
.store(std::addressof(cluster
[i
]), std::memory_order_relaxed
);
1543 cluster
[clustersize
-1].mNext
.store(mVoiceChangeTail
, std::memory_order_relaxed
);
1544 mVoiceChangeClusters
.emplace_back(std::move(cluster
));
1545 mVoiceChangeTail
= mVoiceChangeClusters
.back().get();
1550 void ALCcontext::allocVoices(size_t addcount
)
1552 constexpr size_t clustersize
{32};
1553 /* Convert element count to cluster count. */
1554 addcount
= (addcount
+(clustersize
-1)) / clustersize
;
1556 if(addcount
>= std::numeric_limits
<int>::max()/clustersize
- mVoiceClusters
.size())
1557 throw std::runtime_error
{"Allocating too many voices"};
1558 const size_t totalcount
{(mVoiceClusters
.size()+addcount
) * clustersize
};
1559 TRACE("Increasing allocated voices to %zu\n", totalcount
);
1561 auto newarray
= VoiceArray::Create(totalcount
);
1564 mVoiceClusters
.emplace_back(std::make_unique
<Voice
[]>(clustersize
));
1568 auto voice_iter
= newarray
->begin();
1569 for(VoiceCluster
&cluster
: mVoiceClusters
)
1571 for(size_t i
{0};i
< clustersize
;++i
)
1572 *(voice_iter
++) = &cluster
[i
];
1575 if(auto *oldvoices
= mVoices
.exchange(newarray
.release(), std::memory_order_acq_rel
))
1577 mDevice
->waitForMix();
1583 /** Stores the latest ALC device error. */
1584 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1586 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval
<void*>()){device
},
1591 /* DebugBreak() will cause an exception if there is no debugger */
1592 if(IsDebuggerPresent())
1594 #elif defined(SIGTRAP)
1600 device
->LastError
.store(errorCode
);
1602 LastNullDeviceError
.store(errorCode
);
1606 static std::unique_ptr
<Compressor
> CreateDeviceLimiter(const ALCdevice
*device
, const float threshold
)
1608 constexpr bool AutoKnee
{true};
1609 constexpr bool AutoAttack
{true};
1610 constexpr bool AutoRelease
{true};
1611 constexpr bool AutoPostGain
{true};
1612 constexpr bool AutoDeclip
{true};
1613 constexpr float LookAheadTime
{0.001f
};
1614 constexpr float HoldTime
{0.002f
};
1615 constexpr float PreGainDb
{0.0f
};
1616 constexpr float PostGainDb
{0.0f
};
1617 constexpr float Ratio
{std::numeric_limits
<float>::infinity()};
1618 constexpr float KneeDb
{0.0f
};
1619 constexpr float AttackTime
{0.02f
};
1620 constexpr float ReleaseTime
{0.2f
};
1622 return Compressor::Create(device
->RealOut
.Buffer
.size(), static_cast<float>(device
->Frequency
),
1623 AutoKnee
, AutoAttack
, AutoRelease
, AutoPostGain
, AutoDeclip
, LookAheadTime
, HoldTime
,
1624 PreGainDb
, PostGainDb
, threshold
, Ratio
, KneeDb
, AttackTime
, ReleaseTime
);
1628 * Updates the device's base clock time with however many samples have been
1629 * done. This is used so frequency changes on the device don't cause the time
1630 * to jump forward or back. Must not be called while the device is running/
1633 static inline void UpdateClockBase(ALCdevice
*device
)
1635 IncrementRef(device
->MixCount
);
1636 device
->ClockBase
+= nanoseconds
{seconds
{device
->SamplesDone
}} / device
->Frequency
;
1637 device
->SamplesDone
= 0;
1638 IncrementRef(device
->MixCount
);
1642 * Updates device parameters according to the attribute list (caller is
1643 * responsible for holding the list lock).
1645 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const int *attrList
)
1647 HrtfRequestMode hrtf_userreq
{Hrtf_Default
};
1648 HrtfRequestMode hrtf_appreq
{Hrtf_Default
};
1649 ALCenum gainLimiter
{device
->LimiterState
};
1650 ALCuint new_sends
{device
->NumAuxSends
};
1651 DevFmtChannels oldChans
;
1653 ALCsizei hrtf_id
{-1};
1656 if((!attrList
|| !attrList
[0]) && device
->Type
== Loopback
)
1658 WARN("Missing attributes for loopback device\n");
1659 return ALC_INVALID_VALUE
;
1662 // Check for attributes
1663 if(attrList
&& attrList
[0])
1665 ALCenum alayout
{AL_NONE
};
1666 ALCenum ascale
{AL_NONE
};
1667 ALCenum schans
{AL_NONE
};
1668 ALCenum stype
{AL_NONE
};
1669 ALCsizei attrIdx
{0};
1673 ALuint numMono
{device
->NumMonoSources
};
1674 ALuint numStereo
{device
->NumStereoSources
};
1675 ALuint numSends
{device
->NumAuxSends
};
1677 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1678 while(attrList
[attrIdx
])
1680 switch(attrList
[attrIdx
])
1682 case ALC_FORMAT_CHANNELS_SOFT
:
1683 schans
= attrList
[attrIdx
+ 1];
1684 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1687 case ALC_FORMAT_TYPE_SOFT
:
1688 stype
= attrList
[attrIdx
+ 1];
1689 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1693 freq
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1694 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1697 case ALC_AMBISONIC_LAYOUT_SOFT
:
1698 alayout
= attrList
[attrIdx
+ 1];
1699 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1702 case ALC_AMBISONIC_SCALING_SOFT
:
1703 ascale
= attrList
[attrIdx
+ 1];
1704 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1707 case ALC_AMBISONIC_ORDER_SOFT
:
1708 aorder
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1709 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1712 case ALC_MONO_SOURCES
:
1713 numMono
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1714 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1715 if(numMono
> INT_MAX
) numMono
= 0;
1718 case ALC_STEREO_SOURCES
:
1719 numStereo
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1720 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1721 if(numStereo
> INT_MAX
) numStereo
= 0;
1724 case ALC_MAX_AUXILIARY_SENDS
:
1725 numSends
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1726 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1727 if(numSends
> INT_MAX
) numSends
= 0;
1728 else numSends
= minu(numSends
, MAX_SENDS
);
1732 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1733 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1734 hrtf_appreq
= Hrtf_Disable
;
1735 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1736 hrtf_appreq
= Hrtf_Enable
;
1738 hrtf_appreq
= Hrtf_Default
;
1741 case ALC_HRTF_ID_SOFT
:
1742 hrtf_id
= attrList
[attrIdx
+ 1];
1743 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1746 case ALC_OUTPUT_LIMITER_SOFT
:
1747 gainLimiter
= attrList
[attrIdx
+ 1];
1748 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1752 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1753 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1761 const bool loopback
{device
->Type
== Loopback
};
1764 if(!schans
|| !stype
|| !freq
)
1766 WARN("Missing format for loopback device\n");
1767 return ALC_INVALID_VALUE
;
1769 if(!IsValidALCChannels(schans
) || !IsValidALCType(stype
) || freq
< MIN_OUTPUT_RATE
1770 || freq
> MAX_OUTPUT_RATE
)
1771 return ALC_INVALID_VALUE
;
1772 if(schans
== ALC_BFORMAT3D_SOFT
)
1774 if(!alayout
|| !ascale
|| !aorder
)
1776 WARN("Missing ambisonic info for loopback device\n");
1777 return ALC_INVALID_VALUE
;
1779 if(!IsValidAmbiLayout(alayout
) || !IsValidAmbiScaling(ascale
))
1780 return ALC_INVALID_VALUE
;
1781 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1782 return ALC_INVALID_VALUE
;
1783 if((alayout
== ALC_FUMA_SOFT
|| ascale
== ALC_FUMA_SOFT
) && aorder
> 3)
1784 return ALC_INVALID_VALUE
;
1788 /* If a context is already running on the device, stop playback so the
1789 * device attributes can be updated.
1791 if(device
->Flags
.get
<DeviceRunning
>())
1792 device
->Backend
->stop();
1793 device
->Flags
.unset
<DeviceRunning
>();
1795 UpdateClockBase(device
);
1797 const char *devname
{nullptr};
1800 devname
= device
->DeviceName
.c_str();
1802 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
1803 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
1804 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
1806 freq
= ConfigValueUInt(devname
, nullptr, "frequency").value_or(freq
);
1808 device
->Flags
.unset
<FrequencyRequest
>();
1811 freq
= clampu(freq
, MIN_OUTPUT_RATE
, MAX_OUTPUT_RATE
);
1813 const double scale
{static_cast<double>(freq
) / device
->Frequency
};
1814 device
->UpdateSize
= static_cast<ALuint
>(device
->UpdateSize
*scale
+ 0.5);
1815 device
->BufferSize
= static_cast<ALuint
>(device
->BufferSize
*scale
+ 0.5);
1817 device
->Frequency
= freq
;
1818 device
->Flags
.set
<FrequencyRequest
>();
1821 if(auto persizeopt
= ConfigValueUInt(devname
, nullptr, "period_size"))
1822 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
1824 if(auto peropt
= ConfigValueUInt(devname
, nullptr, "periods"))
1825 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
1827 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
1831 device
->Frequency
= freq
;
1832 device
->FmtChans
= static_cast<DevFmtChannels
>(schans
);
1833 device
->FmtType
= static_cast<DevFmtType
>(stype
);
1834 if(schans
== ALC_BFORMAT3D_SOFT
)
1836 device
->mAmbiOrder
= aorder
;
1837 device
->mAmbiLayout
= static_cast<DevAmbiLayout
>(alayout
);
1838 device
->mAmbiScale
= static_cast<DevAmbiScaling
>(ascale
);
1842 if(numMono
> INT_MAX
-numStereo
)
1843 numMono
= INT_MAX
-numStereo
;
1844 numMono
+= numStereo
;
1845 if(auto srcsopt
= ConfigValueUInt(devname
, nullptr, "sources"))
1847 if(*srcsopt
<= 0) numMono
= 256;
1848 else numMono
= *srcsopt
;
1851 numMono
= maxu(numMono
, 256);
1852 numStereo
= minu(numStereo
, numMono
);
1853 numMono
-= numStereo
;
1854 device
->SourcesMax
= numMono
+ numStereo
;
1856 device
->NumMonoSources
= numMono
;
1857 device
->NumStereoSources
= numStereo
;
1859 if(auto sendsopt
= ConfigValueInt(devname
, nullptr, "sends"))
1860 new_sends
= minu(numSends
, static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
1862 new_sends
= numSends
;
1865 if(device
->Flags
.get
<DeviceRunning
>())
1866 return ALC_NO_ERROR
;
1868 device
->AvgSpeakerDist
= 0.0f
;
1869 device
->Uhj_Encoder
= nullptr;
1870 device
->AmbiDecoder
= nullptr;
1871 device
->Bs2b
= nullptr;
1872 device
->PostProcess
= nullptr;
1874 device
->Limiter
= nullptr;
1875 device
->ChannelDelay
.clear();
1877 std::fill(std::begin(device
->HrtfAccumData
), std::end(device
->HrtfAccumData
), float2
{});
1879 device
->Dry
.AmbiMap
.fill(BFChannelConfig
{});
1880 device
->Dry
.Buffer
= {};
1881 std::fill(std::begin(device
->NumChannelsPerOrder
), std::end(device
->NumChannelsPerOrder
), 0u);
1882 device
->RealOut
.RemixMap
= {};
1883 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1884 device
->RealOut
.Buffer
= {};
1885 device
->MixBuffer
.clear();
1886 device
->MixBuffer
.shrink_to_fit();
1888 UpdateClockBase(device
);
1889 device
->FixedLatency
= nanoseconds::zero();
1891 device
->DitherDepth
= 0.0f
;
1892 device
->DitherSeed
= DitherRNGSeed
;
1894 /*************************************************************************
1895 * Update device format request if HRTF is requested
1897 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1898 if(device
->Type
!= Loopback
)
1900 if(auto hrtfopt
= ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf"))
1902 const char *hrtf
{hrtfopt
->c_str()};
1903 if(al::strcasecmp(hrtf
, "true") == 0)
1904 hrtf_userreq
= Hrtf_Enable
;
1905 else if(al::strcasecmp(hrtf
, "false") == 0)
1906 hrtf_userreq
= Hrtf_Disable
;
1907 else if(al::strcasecmp(hrtf
, "auto") != 0)
1908 ERR("Unexpected hrtf value: %s\n", hrtf
);
1911 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1913 device
->FmtChans
= DevFmtStereo
;
1914 device
->Flags
.set
<ChannelsRequest
>();
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 auto backend
= device
->Backend
.get();
1930 if(!backend
->reset())
1931 throw al::backend_exception
{ALC_INVALID_DEVICE
, "Device reset failure"};
1933 catch(std::exception
&e
) {
1934 device
->handleDisconnect("%s", e
.what());
1935 return ALC_INVALID_DEVICE
;
1938 if(device
->FmtChans
!= oldChans
&& device
->Flags
.get
<ChannelsRequest
>())
1940 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1941 DevFmtChannelsString(device
->FmtChans
));
1942 device
->Flags
.unset
<ChannelsRequest
>();
1944 if(device
->FmtType
!= oldType
&& device
->Flags
.get
<SampleTypeRequest
>())
1946 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1947 DevFmtTypeString(device
->FmtType
));
1948 device
->Flags
.unset
<SampleTypeRequest
>();
1950 if(device
->Frequency
!= oldFreq
&& device
->Flags
.get
<FrequencyRequest
>())
1952 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1953 device
->Flags
.unset
<FrequencyRequest
>();
1956 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1957 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
1958 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
1960 switch(device
->FmtChans
)
1962 case DevFmtMono
: device
->RealOut
.RemixMap
= MonoDownmix
; break;
1963 case DevFmtStereo
: device
->RealOut
.RemixMap
= StereoDownmix
; break;
1964 case DevFmtQuad
: device
->RealOut
.RemixMap
= QuadDownmix
; break;
1965 case DevFmtX51
: device
->RealOut
.RemixMap
= X51Downmix
; break;
1966 case DevFmtX51Rear
: device
->RealOut
.RemixMap
= X51RearDownmix
; break;
1967 case DevFmtX61
: device
->RealOut
.RemixMap
= X61Downmix
; break;
1968 case DevFmtX71
: device
->RealOut
.RemixMap
= X71Downmix
; break;
1969 case DevFmtAmbi3D
: break;
1972 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
1974 device
->NumAuxSends
= new_sends
;
1975 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1976 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
1977 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
1979 if(device
->Uhj_Encoder
)
1981 /* NOTE: Don't know why this has to be "copied" into a local constexpr
1982 * variable to avoid a reference on Uhj2Encoder::sFilterSize...
1984 constexpr size_t filter_len
{Uhj2Encoder::sFilterSize
};
1985 device
->FixedLatency
+= nanoseconds
{seconds
{filter_len
}} / device
->Frequency
;
1987 if(device
->mHrtfState
)
1988 device
->FixedLatency
+= nanoseconds
{seconds
{HRTF_DIRECT_DELAY
}} / device
->Frequency
;
1989 if(auto *ambidec
= device
->AmbiDecoder
.get())
1991 if(ambidec
->hasStablizer())
1993 constexpr size_t StablizerDelay
{FrontStablizer::DelayLength
};
1994 device
->FixedLatency
+= nanoseconds
{seconds
{StablizerDelay
}} / device
->Frequency
;
1998 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2000 int depth
{ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth").value_or(0)};
2003 switch(device
->FmtType
)
2022 depth
= clampi(depth
, 2, 24);
2023 device
->DitherDepth
= std::pow(2.0f
, static_cast<float>(depth
-1));
2026 if(!(device
->DitherDepth
> 0.0f
))
2027 TRACE("Dithering disabled\n");
2029 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2030 device
->DitherDepth
);
2032 device
->LimiterState
= gainLimiter
;
2033 if(auto limopt
= ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter"))
2034 gainLimiter
= *limopt
? ALC_TRUE
: ALC_FALSE
;
2036 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2037 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2038 * output (where samples must be clamped), and don't for floating-point
2039 * (which can take unclamped samples).
2041 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2043 switch(device
->FmtType
)
2051 gainLimiter
= ALC_TRUE
;
2054 gainLimiter
= ALC_FALSE
;
2058 if(gainLimiter
== ALC_FALSE
)
2059 TRACE("Output limiter disabled\n");
2062 float thrshld
{1.0f
};
2063 switch(device
->FmtType
)
2067 thrshld
= 127.0f
/ 128.0f
;
2071 thrshld
= 32767.0f
/ 32768.0f
;
2078 if(device
->DitherDepth
> 0.0f
)
2079 thrshld
-= 1.0f
/ device
->DitherDepth
;
2081 const float thrshld_dB
{std::log10(thrshld
) * 20.0f
};
2082 auto limiter
= CreateDeviceLimiter(device
, thrshld_dB
);
2083 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2084 device
->FixedLatency
+= nanoseconds
{seconds
{limiter
->getLookAhead()}} / device
->Frequency
;
2085 device
->Limiter
= std::move(limiter
);
2086 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB
);
2089 TRACE("Fixed device latency: %" PRId64
"ns\n", int64_t{device
->FixedLatency
.count()});
2091 FPUCtl mixer_mode
{};
2092 for(ALCcontext
*context
: *device
->mContexts
.load())
2094 if(ALeffectslot
*slot
{context
->mDefaultSlot
.get()})
2096 aluInitEffectPanning(slot
, device
);
2098 EffectState
*state
{slot
->Effect
.State
.get()};
2099 state
->mOutTarget
= device
->Dry
.Buffer
;
2100 state
->deviceUpdate(device
);
2101 if(ALbuffer
*buffer
{slot
->Buffer
})
2103 slot
->Effect
.Buffer
= nullptr;
2104 slot
->Effect
.Buffer
.reset(state
->createBuffer(device
, buffer
->mBuffer
));
2106 slot
->updateProps(context
);
2109 std::unique_lock
<std::mutex
> proplock
{context
->mPropLock
};
2110 std::unique_lock
<std::mutex
> slotlock
{context
->mEffectSlotLock
};
2111 if(ALeffectslotArray
*curarray
{context
->mActiveAuxSlots
.load(std::memory_order_relaxed
)})
2112 std::fill_n(curarray
->end(), curarray
->size(), nullptr);
2113 for(auto &sublist
: context
->mEffectSlotList
)
2115 uint64_t usemask
{~sublist
.FreeMask
};
2118 ALsizei idx
{CTZ64(usemask
)};
2119 ALeffectslot
*slot
{sublist
.EffectSlots
+ idx
};
2120 usemask
&= ~(1_u64
<< idx
);
2122 aluInitEffectPanning(slot
, device
);
2124 EffectState
*state
{slot
->Effect
.State
.get()};
2125 state
->mOutTarget
= device
->Dry
.Buffer
;
2126 state
->deviceUpdate(device
);
2127 if(ALbuffer
*buffer
{slot
->Buffer
})
2129 slot
->Effect
.Buffer
= nullptr;
2130 slot
->Effect
.Buffer
.reset(state
->createBuffer(device
, buffer
->mBuffer
));
2132 slot
->updateProps(context
);
2137 const ALuint num_sends
{device
->NumAuxSends
};
2138 std::unique_lock
<std::mutex
> srclock
{context
->mSourceLock
};
2139 for(auto &sublist
: context
->mSourceList
)
2141 uint64_t usemask
{~sublist
.FreeMask
};
2144 ALsizei idx
{CTZ64(usemask
)};
2145 ALsource
*source
{sublist
.Sources
+ idx
};
2146 usemask
&= ~(1_u64
<< idx
);
2148 auto clear_send
= [](ALsource::SendData
&send
) -> void
2151 DecrementRef(send
.Slot
->ref
);
2152 send
.Slot
= nullptr;
2155 send
.HFReference
= LOWPASSFREQREF
;
2157 send
.LFReference
= HIGHPASSFREQREF
;
2159 auto send_begin
= source
->Send
.begin() + static_cast<ptrdiff_t>(num_sends
);
2160 std::for_each(send_begin
, source
->Send
.end(), clear_send
);
2162 source
->PropsClean
.clear(std::memory_order_release
);
2166 /* Clear any pre-existing voice property structs, in case the number of
2167 * auxiliary sends is changing. Active sources will have updates
2168 * respecified in UpdateAllSourceProps.
2170 VoicePropsItem
*vprops
{context
->mFreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2173 VoicePropsItem
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2178 auto voicelist
= context
->getVoicesSpan();
2179 for(Voice
*voice
: voicelist
)
2181 /* Clear extraneous property set sends. */
2182 std::fill(std::begin(voice
->mProps
.Send
)+num_sends
, std::end(voice
->mProps
.Send
),
2183 VoiceProps::SendData
{});
2185 std::fill(voice
->mSend
.begin()+num_sends
, voice
->mSend
.end(), Voice::TargetData
{});
2186 for(auto &chandata
: voice
->mChans
)
2188 std::fill(chandata
.mWetParams
.begin()+num_sends
, chandata
.mWetParams
.end(),
2192 delete voice
->mUpdate
.exchange(nullptr, std::memory_order_acq_rel
);
2194 /* Force the voice to stopped if it was stopping. */
2195 Voice::State vstate
{Voice::Stopping
};
2196 voice
->mPlayState
.compare_exchange_strong(vstate
, Voice::Stopped
,
2197 std::memory_order_acquire
, std::memory_order_acquire
);
2198 if(voice
->mSourceID
.load(std::memory_order_relaxed
) == 0u)
2202 voice
->mFlags
|= VOICE_IS_FADING
;
2204 if(voice
->mAmbiOrder
&& device
->mAmbiOrder
> voice
->mAmbiOrder
)
2206 const uint8_t *OrderFromChan
{(voice
->mFmtChannels
== FmtBFormat2D
) ?
2207 AmbiIndex::OrderFrom2DChannel
.data() :
2208 AmbiIndex::OrderFromChannel
.data()};
2210 const BandSplitter splitter
{400.0f
/ static_cast<float>(device
->Frequency
)};
2212 const auto scales
= BFormatDec::GetHFOrderScales(voice
->mAmbiOrder
,
2213 device
->mAmbiOrder
);
2214 for(auto &chandata
: voice
->mChans
)
2216 chandata
.mPrevSamples
.fill(0.0f
);
2217 chandata
.mAmbiScale
= scales
[*(OrderFromChan
++)];
2218 chandata
.mAmbiSplitter
= splitter
;
2219 chandata
.mDryParams
= DirectParams
{};
2220 std::fill_n(chandata
.mWetParams
.begin(), num_sends
, SendParams
{});
2223 voice
->mFlags
|= VOICE_IS_AMBISONIC
;
2227 /* Clear previous samples. */
2228 for(auto &chandata
: voice
->mChans
)
2230 chandata
.mPrevSamples
.fill(0.0f
);
2231 chandata
.mDryParams
= DirectParams
{};
2232 std::fill_n(chandata
.mWetParams
.begin(), num_sends
, SendParams
{});
2235 voice
->mFlags
&= ~VOICE_IS_AMBISONIC
;
2238 if(device
->AvgSpeakerDist
> 0.0f
)
2240 /* Reinitialize the NFC filters for new parameters. */
2241 const float w1
{SPEEDOFSOUNDMETRESPERSEC
/
2242 (device
->AvgSpeakerDist
* static_cast<float>(device
->Frequency
))};
2243 for(auto &chandata
: voice
->mChans
)
2244 chandata
.mDryParams
.NFCtrlFilter
.init(w1
);
2249 context
->mPropsClean
.test_and_set(std::memory_order_release
);
2250 UpdateContextProps(context
);
2251 context
->mListener
.PropsClean
.test_and_set(std::memory_order_release
);
2252 UpdateListenerProps(context
);
2253 UpdateAllSourceProps(context
);
2257 if(!device
->Flags
.get
<DevicePaused
>())
2260 auto backend
= device
->Backend
.get();
2262 device
->Flags
.set
<DeviceRunning
>();
2264 catch(al::backend_exception
& e
) {
2265 device
->handleDisconnect("%s", e
.what());
2266 return ALC_INVALID_DEVICE
;
2270 return ALC_NO_ERROR
;
2274 ALCdevice::ALCdevice(DeviceType type
) : Type
{type
}, mContexts
{&EmptyContextArray
}
2278 ALCdevice::~ALCdevice()
2280 TRACE("Freeing device %p\n", decltype(std::declval
<void*>()){this});
2284 size_t count
{std::accumulate(BufferList
.cbegin(), BufferList
.cend(), size_t{0u},
2285 [](size_t cur
, const BufferSubList
&sublist
) noexcept
-> size_t
2286 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2289 WARN("%zu Buffer%s not deleted\n", count
, (count
==1)?"":"s");
2291 count
= std::accumulate(EffectList
.cbegin(), EffectList
.cend(), size_t{0u},
2292 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
2293 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2296 WARN("%zu Effect%s not deleted\n", count
, (count
==1)?"":"s");
2298 count
= std::accumulate(FilterList
.cbegin(), FilterList
.cend(), size_t{0u},
2299 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
2300 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2303 WARN("%zu Filter%s not deleted\n", count
, (count
==1)?"":"s");
2307 auto *oldarray
= mContexts
.exchange(nullptr, std::memory_order_relaxed
);
2308 if(oldarray
!= &EmptyContextArray
) delete oldarray
;
2312 /** Checks if the device handle is valid, and returns a new reference if so. */
2313 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2315 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2316 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
2317 if(iter
!= DeviceList
.end() && *iter
== device
)
2320 return DeviceRef
{*iter
};
2326 ALCcontext::ALCcontext(al::intrusive_ptr
<ALCdevice
> device
) : mDevice
{std::move(device
)}
2328 mPropsClean
.test_and_set(std::memory_order_relaxed
);
2331 ALCcontext::~ALCcontext()
2333 TRACE("Freeing context %p\n", decltype(std::declval
<void*>()){this});
2336 ALcontextProps
*cprops
{mUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
2342 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
2345 ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2350 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
2352 count
= std::accumulate(mSourceList
.cbegin(), mSourceList
.cend(), size_t{0u},
2353 [](size_t cur
, const SourceSubList
&sublist
) noexcept
-> size_t
2354 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2357 WARN("%zu Source%s not deleted\n", count
, (count
==1)?"":"s");
2358 mSourceList
.clear();
2362 ALeffectslotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
2365 ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2370 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2372 if(ALeffectslotArray
*curarray
{mActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
)})
2374 al::destroy_n(curarray
->end(), curarray
->size());
2377 mDefaultSlot
= nullptr;
2379 count
= std::accumulate(mEffectSlotList
.cbegin(), mEffectSlotList
.cend(), size_t{0u},
2380 [](size_t cur
, const EffectSlotSubList
&sublist
) noexcept
-> size_t
2381 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2384 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count
, (count
==1)?"":"s");
2385 mEffectSlotList
.clear();
2386 mNumEffectSlots
= 0;
2389 VoicePropsItem
*vprops
{mFreeVoiceProps
.exchange(nullptr, std::memory_order_acquire
)};
2392 VoicePropsItem
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2397 TRACE("Freed %zu voice property object%s\n", count
, (count
==1)?"":"s");
2399 delete mVoices
.exchange(nullptr, std::memory_order_relaxed
);
2402 ALlistenerProps
*lprops
{mListener
.Params
.Update
.exchange(nullptr, std::memory_order_relaxed
)};
2408 lprops
= mFreeListenerProps
.exchange(nullptr, std::memory_order_acquire
);
2411 ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2416 TRACE("Freed %zu listener property object%s\n", count
, (count
==1)?"":"s");
2421 auto evt_vec
= mAsyncEvents
->getReadVector();
2422 if(evt_vec
.first
.len
> 0)
2424 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.first
.buf
), evt_vec
.first
.len
);
2425 count
+= evt_vec
.first
.len
;
2427 if(evt_vec
.second
.len
> 0)
2429 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.second
.buf
), evt_vec
.second
.len
);
2430 count
+= evt_vec
.second
.len
;
2433 TRACE("Destructed %zu orphaned event%s\n", count
, (count
==1)?"":"s");
2434 mAsyncEvents
->readAdvance(count
);
2438 void ALCcontext::init()
2440 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& mDevice
->Type
== Playback
)
2442 mDefaultSlot
= std::unique_ptr
<ALeffectslot
>{new ALeffectslot
{}};
2443 if(mDefaultSlot
->init() == AL_NO_ERROR
)
2444 aluInitEffectPanning(mDefaultSlot
.get(), mDevice
.get());
2447 mDefaultSlot
= nullptr;
2448 ERR("Failed to initialize the default effect slot\n");
2452 ALeffectslotArray
*auxslots
;
2454 auxslots
= ALeffectslot::CreatePtrArray(0);
2457 auxslots
= ALeffectslot::CreatePtrArray(1);
2458 (*auxslots
)[0] = mDefaultSlot
.get();
2460 mActiveAuxSlots
.store(auxslots
, std::memory_order_relaxed
);
2462 allocVoiceChanges(1);
2464 VoiceChange
*cur
{mVoiceChangeTail
};
2465 while(VoiceChange
*next
{cur
->mNext
.load(std::memory_order_relaxed
)})
2467 mCurrentVoiceChange
.store(cur
, std::memory_order_relaxed
);
2470 mExtensionList
= alExtList
;
2473 mListener
.Params
.Matrix
= alu::Matrix::Identity();
2474 mListener
.Params
.Velocity
= alu::Vector
{};
2475 mListener
.Params
.Gain
= mListener
.Gain
;
2476 mListener
.Params
.MetersPerUnit
= mListener
.mMetersPerUnit
;
2477 mListener
.Params
.DopplerFactor
= mDopplerFactor
;
2478 mListener
.Params
.SpeedOfSound
= mSpeedOfSound
* mDopplerVelocity
;
2479 mListener
.Params
.SourceDistanceModel
= mSourceDistanceModel
;
2480 mListener
.Params
.mDistanceModel
= mDistanceModel
;
2483 mAsyncEvents
= RingBuffer::Create(511, sizeof(AsyncEvent
), false);
2484 StartEventThrd(this);
2488 mActiveVoiceCount
.store(64, std::memory_order_relaxed
);
2491 bool ALCcontext::deinit()
2493 if(LocalContext
== this)
2495 WARN("%p released while current on thread\n", decltype(std::declval
<void*>()){this});
2496 ThreadContext
.set(nullptr);
2500 ALCcontext
*origctx
{this};
2501 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2505 /* First make sure this context exists in the device's list. */
2506 auto *oldarray
= mDevice
->mContexts
.load(std::memory_order_acquire
);
2507 if(auto toremove
= static_cast<size_t>(std::count(oldarray
->begin(), oldarray
->end(), this)))
2509 using ContextArray
= al::FlexArray
<ALCcontext
*>;
2510 auto alloc_ctx_array
= [](const size_t count
) -> ContextArray
*
2512 if(count
== 0) return &EmptyContextArray
;
2513 return ContextArray::Create(count
).release();
2515 auto *newarray
= alloc_ctx_array(oldarray
->size() - toremove
);
2517 /* Copy the current/old context handles to the new array, excluding the
2520 std::copy_if(oldarray
->begin(), oldarray
->end(), newarray
->begin(),
2521 std::bind(std::not_equal_to
<ALCcontext
*>{}, _1
, this));
2523 /* Store the new context array in the device. Wait for any current mix
2524 * to finish before deleting the old array.
2526 mDevice
->mContexts
.store(newarray
);
2527 if(oldarray
!= &EmptyContextArray
)
2529 mDevice
->waitForMix();
2533 ret
= !newarray
->empty();
2536 ret
= !oldarray
->empty();
2538 StopEventThrd(this);
2545 * Checks if the given context is valid, returning a new reference to it if so.
2547 static ContextRef
VerifyContext(ALCcontext
*context
)
2549 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2550 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
2551 if(iter
!= ContextList
.end() && *iter
== context
)
2554 return ContextRef
{*iter
};
2559 /** Returns a new reference to the currently active context for this thread. */
2560 ContextRef
GetContextRef(void)
2562 ALCcontext
*context
{LocalContext
};
2567 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2568 context
= GlobalContext
.load(std::memory_order_acquire
);
2569 if(context
) context
->add_ref();
2571 return ContextRef
{context
};
2575 /************************************************
2576 * Standard ALC functions
2577 ************************************************/
2579 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2582 DeviceRef dev
{VerifyDevice(device
)};
2583 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2584 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2589 ALC_API
void ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2595 ContextRef ctx
{VerifyContext(context
)};
2597 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2599 ctx
->deferUpdates();
2603 ALC_API
void ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2609 ContextRef ctx
{VerifyContext(context
)};
2611 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2613 ctx
->processUpdates();
2618 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2621 const ALCchar
*value
{nullptr};
2629 case ALC_INVALID_ENUM
:
2630 value
= alcErrInvalidEnum
;
2633 case ALC_INVALID_VALUE
:
2634 value
= alcErrInvalidValue
;
2637 case ALC_INVALID_DEVICE
:
2638 value
= alcErrInvalidDevice
;
2641 case ALC_INVALID_CONTEXT
:
2642 value
= alcErrInvalidContext
;
2645 case ALC_OUT_OF_MEMORY
:
2646 value
= alcErrOutOfMemory
;
2649 case ALC_DEVICE_SPECIFIER
:
2650 value
= alcDefaultName
;
2653 case ALC_ALL_DEVICES_SPECIFIER
:
2654 if(DeviceRef dev
{VerifyDevice(Device
)})
2655 value
= dev
->DeviceName
.c_str();
2658 ProbeAllDevicesList();
2659 value
= alcAllDevicesList
.c_str();
2663 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2664 if(DeviceRef dev
{VerifyDevice(Device
)})
2665 value
= dev
->DeviceName
.c_str();
2668 ProbeCaptureDeviceList();
2669 value
= alcCaptureDeviceList
.c_str();
2673 /* Default devices are always first in the list */
2674 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2675 value
= alcDefaultName
;
2678 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2679 if(alcAllDevicesList
.empty())
2680 ProbeAllDevicesList();
2682 /* Copy first entry as default. */
2683 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2684 value
= alcDefaultAllDevicesSpecifier
.c_str();
2687 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2688 if(alcCaptureDeviceList
.empty())
2689 ProbeCaptureDeviceList();
2691 /* Copy first entry as default. */
2692 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2693 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2696 case ALC_EXTENSIONS
:
2697 if(VerifyDevice(Device
))
2698 value
= alcExtensionList
;
2700 value
= alcNoDeviceExtList
;
2703 case ALC_HRTF_SPECIFIER_SOFT
:
2704 if(DeviceRef dev
{VerifyDevice(Device
)})
2706 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
2707 value
= (dev
->mHrtf
? dev
->HrtfName
.c_str() : "");
2710 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2714 alcSetError(VerifyDevice(Device
).get(), ALC_INVALID_ENUM
);
2723 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2725 if(device
->Type
== Capture
) return 9;
2726 if(device
->Type
!= Loopback
) return 29;
2727 if(device
->FmtChans
== DevFmtAmbi3D
)
2732 static size_t GetIntegerv(ALCdevice
*device
, ALCenum param
, const al::span
<int> values
)
2738 alcSetError(device
, ALC_INVALID_VALUE
);
2746 case ALC_MAJOR_VERSION
:
2747 values
[0] = alcMajorVersion
;
2749 case ALC_MINOR_VERSION
:
2750 values
[0] = alcMinorVersion
;
2753 case ALC_ATTRIBUTES_SIZE
:
2754 case ALC_ALL_ATTRIBUTES
:
2758 case ALC_MONO_SOURCES
:
2759 case ALC_STEREO_SOURCES
:
2760 case ALC_CAPTURE_SAMPLES
:
2761 case ALC_FORMAT_CHANNELS_SOFT
:
2762 case ALC_FORMAT_TYPE_SOFT
:
2763 case ALC_AMBISONIC_LAYOUT_SOFT
:
2764 case ALC_AMBISONIC_SCALING_SOFT
:
2765 case ALC_AMBISONIC_ORDER_SOFT
:
2766 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
2767 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2771 alcSetError(nullptr, ALC_INVALID_ENUM
);
2776 if(device
->Type
== Capture
)
2780 case ALC_ATTRIBUTES_SIZE
:
2781 values
[0] = NumAttrsForDevice(device
);
2784 case ALC_ALL_ATTRIBUTES
:
2786 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2787 alcSetError(device
, ALC_INVALID_VALUE
);
2790 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2791 values
[i
++] = ALC_MAJOR_VERSION
;
2792 values
[i
++] = alcMajorVersion
;
2793 values
[i
++] = ALC_MINOR_VERSION
;
2794 values
[i
++] = alcMinorVersion
;
2795 values
[i
++] = ALC_CAPTURE_SAMPLES
;
2796 values
[i
++] = static_cast<int>(device
->Backend
->availableSamples());
2797 values
[i
++] = ALC_CONNECTED
;
2798 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
2803 case ALC_MAJOR_VERSION
:
2804 values
[0] = alcMajorVersion
;
2806 case ALC_MINOR_VERSION
:
2807 values
[0] = alcMinorVersion
;
2810 case ALC_CAPTURE_SAMPLES
:
2812 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2813 values
[0] = static_cast<int>(device
->Backend
->availableSamples());
2819 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2820 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2825 alcSetError(device
, ALC_INVALID_ENUM
);
2833 case ALC_ATTRIBUTES_SIZE
:
2834 values
[0] = NumAttrsForDevice(device
);
2837 case ALC_ALL_ATTRIBUTES
:
2839 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2840 alcSetError(device
, ALC_INVALID_VALUE
);
2843 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2844 values
[i
++] = ALC_MAJOR_VERSION
;
2845 values
[i
++] = alcMajorVersion
;
2846 values
[i
++] = ALC_MINOR_VERSION
;
2847 values
[i
++] = alcMinorVersion
;
2848 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
2849 values
[i
++] = alcEFXMajorVersion
;
2850 values
[i
++] = ALC_EFX_MINOR_VERSION
;
2851 values
[i
++] = alcEFXMinorVersion
;
2853 values
[i
++] = ALC_FREQUENCY
;
2854 values
[i
++] = static_cast<int>(device
->Frequency
);
2855 if(device
->Type
!= Loopback
)
2857 values
[i
++] = ALC_REFRESH
;
2858 values
[i
++] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2860 values
[i
++] = ALC_SYNC
;
2861 values
[i
++] = ALC_FALSE
;
2865 if(device
->FmtChans
== DevFmtAmbi3D
)
2867 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
2868 values
[i
++] = static_cast<int>(device
->mAmbiLayout
);
2870 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
2871 values
[i
++] = static_cast<int>(device
->mAmbiScale
);
2873 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
2874 values
[i
++] = static_cast<int>(device
->mAmbiOrder
);
2877 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2878 values
[i
++] = device
->FmtChans
;
2880 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2881 values
[i
++] = device
->FmtType
;
2884 values
[i
++] = ALC_MONO_SOURCES
;
2885 values
[i
++] = static_cast<int>(device
->NumMonoSources
);
2887 values
[i
++] = ALC_STEREO_SOURCES
;
2888 values
[i
++] = static_cast<int>(device
->NumStereoSources
);
2890 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2891 values
[i
++] = static_cast<int>(device
->NumAuxSends
);
2893 values
[i
++] = ALC_HRTF_SOFT
;
2894 values
[i
++] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
2896 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
2897 values
[i
++] = device
->HrtfStatus
;
2899 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
2900 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
2902 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
2903 values
[i
++] = MAX_AMBI_ORDER
;
2909 case ALC_MAJOR_VERSION
:
2910 values
[0] = alcMajorVersion
;
2913 case ALC_MINOR_VERSION
:
2914 values
[0] = alcMinorVersion
;
2917 case ALC_EFX_MAJOR_VERSION
:
2918 values
[0] = alcEFXMajorVersion
;
2921 case ALC_EFX_MINOR_VERSION
:
2922 values
[0] = alcEFXMinorVersion
;
2926 values
[0] = static_cast<int>(device
->Frequency
);
2930 if(device
->Type
== Loopback
)
2932 alcSetError(device
, ALC_INVALID_DEVICE
);
2936 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2937 values
[0] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2942 if(device
->Type
== Loopback
)
2944 alcSetError(device
, ALC_INVALID_DEVICE
);
2947 values
[0] = ALC_FALSE
;
2950 case ALC_FORMAT_CHANNELS_SOFT
:
2951 if(device
->Type
!= Loopback
)
2953 alcSetError(device
, ALC_INVALID_DEVICE
);
2956 values
[0] = device
->FmtChans
;
2959 case ALC_FORMAT_TYPE_SOFT
:
2960 if(device
->Type
!= Loopback
)
2962 alcSetError(device
, ALC_INVALID_DEVICE
);
2965 values
[0] = device
->FmtType
;
2968 case ALC_AMBISONIC_LAYOUT_SOFT
:
2969 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2971 alcSetError(device
, ALC_INVALID_DEVICE
);
2974 values
[0] = static_cast<int>(device
->mAmbiLayout
);
2977 case ALC_AMBISONIC_SCALING_SOFT
:
2978 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2980 alcSetError(device
, ALC_INVALID_DEVICE
);
2983 values
[0] = static_cast<int>(device
->mAmbiScale
);
2986 case ALC_AMBISONIC_ORDER_SOFT
:
2987 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2989 alcSetError(device
, ALC_INVALID_DEVICE
);
2992 values
[0] = static_cast<int>(device
->mAmbiOrder
);
2995 case ALC_MONO_SOURCES
:
2996 values
[0] = static_cast<int>(device
->NumMonoSources
);
2999 case ALC_STEREO_SOURCES
:
3000 values
[0] = static_cast<int>(device
->NumStereoSources
);
3003 case ALC_MAX_AUXILIARY_SENDS
:
3004 values
[0] = static_cast<int>(device
->NumAuxSends
);
3009 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3010 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3015 values
[0] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3018 case ALC_HRTF_STATUS_SOFT
:
3019 values
[0] = device
->HrtfStatus
;
3022 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3024 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3025 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3026 values
[0] = static_cast<int>(minz(device
->HrtfList
.size(),
3027 std::numeric_limits
<int>::max()));
3031 case ALC_OUTPUT_LIMITER_SOFT
:
3032 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3035 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3036 values
[0] = MAX_AMBI_ORDER
;
3040 alcSetError(device
, ALC_INVALID_ENUM
);
3045 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3048 DeviceRef dev
{VerifyDevice(device
)};
3049 if(size
<= 0 || values
== nullptr)
3050 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3052 GetIntegerv(dev
.get(), param
, {values
, static_cast<ALuint
>(size
)});
3056 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3059 DeviceRef dev
{VerifyDevice(device
)};
3060 if(size
<= 0 || values
== nullptr)
3062 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3065 if(!dev
|| dev
->Type
== Capture
)
3067 auto ivals
= al::vector
<int>(static_cast<ALuint
>(size
));
3068 size_t got
{GetIntegerv(dev
.get(), pname
, ivals
)};
3069 std::copy_n(ivals
.begin(), got
, values
);
3075 case ALC_ATTRIBUTES_SIZE
:
3076 *values
= NumAttrsForDevice(dev
.get())+4;
3079 case ALC_ALL_ATTRIBUTES
:
3080 if(size
< NumAttrsForDevice(dev
.get())+4)
3081 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3085 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3086 values
[i
++] = ALC_FREQUENCY
;
3087 values
[i
++] = dev
->Frequency
;
3089 if(dev
->Type
!= Loopback
)
3091 values
[i
++] = ALC_REFRESH
;
3092 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3094 values
[i
++] = ALC_SYNC
;
3095 values
[i
++] = ALC_FALSE
;
3099 if(dev
->FmtChans
== DevFmtAmbi3D
)
3101 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3102 values
[i
++] = static_cast<int64_t>(dev
->mAmbiLayout
);
3104 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3105 values
[i
++] = static_cast<int64_t>(dev
->mAmbiScale
);
3107 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3108 values
[i
++] = dev
->mAmbiOrder
;
3111 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3112 values
[i
++] = dev
->FmtChans
;
3114 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3115 values
[i
++] = dev
->FmtType
;
3118 values
[i
++] = ALC_MONO_SOURCES
;
3119 values
[i
++] = dev
->NumMonoSources
;
3121 values
[i
++] = ALC_STEREO_SOURCES
;
3122 values
[i
++] = dev
->NumStereoSources
;
3124 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3125 values
[i
++] = dev
->NumAuxSends
;
3127 values
[i
++] = ALC_HRTF_SOFT
;
3128 values
[i
++] = (dev
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3130 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3131 values
[i
++] = dev
->HrtfStatus
;
3133 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3134 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3136 ClockLatency clock
{GetClockLatency(dev
.get())};
3137 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3138 values
[i
++] = clock
.ClockTime
.count();
3140 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3141 values
[i
++] = clock
.Latency
.count();
3147 case ALC_DEVICE_CLOCK_SOFT
:
3149 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3150 ALuint samplecount
, refcount
;
3151 nanoseconds basecount
;
3153 refcount
= dev
->waitForMix();
3154 basecount
= dev
->ClockBase
;
3155 samplecount
= dev
->SamplesDone
;
3156 } while(refcount
!= ReadRef(dev
->MixCount
));
3157 basecount
+= nanoseconds
{seconds
{samplecount
}} / dev
->Frequency
;
3158 *values
= basecount
.count();
3162 case ALC_DEVICE_LATENCY_SOFT
:
3164 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3165 ClockLatency clock
{GetClockLatency(dev
.get())};
3166 *values
= clock
.Latency
.count();
3170 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3172 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3175 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3176 ClockLatency clock
{GetClockLatency(dev
.get())};
3177 values
[0] = clock
.ClockTime
.count();
3178 values
[1] = clock
.Latency
.count();
3183 auto ivals
= al::vector
<int>(static_cast<ALuint
>(size
));
3184 size_t got
{GetIntegerv(dev
.get(), pname
, ivals
)};
3185 std::copy_n(ivals
.begin(), got
, values
);
3192 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3195 DeviceRef dev
{VerifyDevice(device
)};
3197 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3200 size_t len
= strlen(extName
);
3201 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3204 if(al::strncasecmp(ptr
, extName
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3207 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3211 } while(isspace(*ptr
));
3220 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3225 DeviceRef dev
{VerifyDevice(device
)};
3226 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3230 for(const auto &func
: alcFunctions
)
3232 if(strcmp(func
.funcName
, funcName
) == 0)
3233 return func
.address
;
3241 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3246 DeviceRef dev
{VerifyDevice(device
)};
3247 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3251 for(const auto &enm
: alcEnumerations
)
3253 if(strcmp(enm
.enumName
, enumName
) == 0)
3262 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3265 /* Explicitly hold the list lock while taking the StateLock in case the
3266 * device is asynchronously destroyed, to ensure this new context is
3267 * properly cleaned up after being made.
3269 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3270 DeviceRef dev
{VerifyDevice(device
)};
3271 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3274 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3277 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3280 dev
->LastError
.store(ALC_NO_ERROR
);
3282 ALCenum err
{UpdateDeviceParams(dev
.get(), attrList
)};
3283 if(err
!= ALC_NO_ERROR
)
3285 alcSetError(dev
.get(), err
);
3289 ContextRef context
{new ALCcontext
{dev
}};
3292 if(auto volopt
= ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust"))
3294 const float valf
{*volopt
};
3295 if(!std::isfinite(valf
))
3296 ERR("volume-adjust must be finite: %f\n", valf
);
3299 const float db
{clampf(valf
, -24.0f
, 24.0f
)};
3301 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3302 context
->mGainBoost
= std::pow(10.0f
, db
/20.0f
);
3303 TRACE("volume-adjust gain: %f\n", context
->mGainBoost
);
3306 UpdateListenerProps(context
.get());
3309 using ContextArray
= al::FlexArray
<ALCcontext
*>;
3311 /* Allocate a new context array, which holds 1 more than the current/
3314 auto *oldarray
= device
->mContexts
.load();
3315 const size_t newcount
{oldarray
->size()+1};
3316 std::unique_ptr
<ContextArray
> newarray
{ContextArray::Create(newcount
)};
3318 /* Copy the current/old context handles to the new array, appending the
3321 auto iter
= std::copy(oldarray
->begin(), oldarray
->end(), newarray
->begin());
3322 *iter
= context
.get();
3324 /* Store the new context array in the device. Wait for any current mix
3325 * to finish before deleting the old array.
3327 dev
->mContexts
.store(newarray
.release());
3328 if(oldarray
!= &EmptyContextArray
)
3337 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3338 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
.get());
3339 ContextList
.emplace(iter
, context
.get());
3342 if(ALeffectslot
*slot
{context
->mDefaultSlot
.get()})
3344 if(slot
->initEffect(&DefaultEffect
, context
.get()) == AL_NO_ERROR
)
3345 slot
->updateProps(context
.get());
3347 ERR("Failed to initialize the default effect\n");
3350 TRACE("Created context %p\n", decltype(std::declval
<void*>()){context
.get()});
3351 return context
.release();
3355 ALC_API
void ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3358 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3359 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
3360 if(iter
== ContextList
.end() || *iter
!= context
)
3363 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3366 /* Hold a reference to this context so it remains valid until the ListLock
3369 ContextRef ctx
{*iter
};
3370 ContextList
.erase(iter
);
3372 ALCdevice
*Device
{ctx
->mDevice
.get()};
3374 std::lock_guard
<std::mutex
> _
{Device
->StateLock
};
3375 if(!ctx
->deinit() && Device
->Flags
.get
<DeviceRunning
>())
3377 Device
->Backend
->stop();
3378 Device
->Flags
.unset
<DeviceRunning
>();
3384 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3387 ALCcontext
*Context
{LocalContext
};
3388 if(!Context
) Context
= GlobalContext
.load();
3393 /** Returns the currently active thread-local context. */
3394 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3396 { return LocalContext
; }
3399 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3402 /* context must be valid or nullptr */
3406 ctx
= VerifyContext(context
);
3409 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3413 /* Release this reference (if any) to store it in the GlobalContext
3414 * pointer. Take ownership of the reference (if any) that was previously
3417 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3419 /* Reset (decrement) the previous global reference by replacing it with the
3420 * thread-local context. Take ownership of the thread-local context
3421 * reference (if any), clearing the storage to null.
3423 ctx
= ContextRef
{LocalContext
};
3424 if(ctx
) ThreadContext
.set(nullptr);
3425 /* Reset (decrement) the previous thread-local reference. */
3431 /** Makes the given context the active context for the current thread. */
3432 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3435 /* context must be valid or nullptr */
3439 ctx
= VerifyContext(context
);
3442 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3446 /* context's reference count is already incremented */
3447 ContextRef old
{LocalContext
};
3448 ThreadContext
.set(ctx
.release());
3455 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3458 ContextRef ctx
{VerifyContext(Context
)};
3461 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3464 return ctx
->mDevice
.get();
3469 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3474 if(!PlaybackFactory
)
3476 alcSetError(nullptr, ALC_INVALID_VALUE
);
3482 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3484 /* Some old Windows apps hardcode these expecting OpenAL to use a
3485 * specific audio API, even when they're not enumerated. Creative's
3486 * router effectively ignores them too.
3488 || al::strcasecmp(deviceName
, "DirectSound3D") == 0
3489 || al::strcasecmp(deviceName
, "DirectSound") == 0
3490 || al::strcasecmp(deviceName
, "MMSYSTEM") == 0
3492 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3493 deviceName
= nullptr;
3496 DeviceRef device
{new ALCdevice
{Playback
}};
3498 /* Set output format */
3499 device
->FmtChans
= DevFmtChannelsDefault
;
3500 device
->FmtType
= DevFmtTypeDefault
;
3501 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3502 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
3503 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
3505 device
->SourcesMax
= 256;
3506 device
->AuxiliaryEffectSlotMax
= 64;
3507 device
->NumAuxSends
= DEFAULT_SENDS
;
3510 auto backend
= PlaybackFactory
->createBackend(device
.get(), BackendType::Playback
);
3511 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3512 backend
->open(deviceName
);
3513 device
->Backend
= std::move(backend
);
3515 catch(al::backend_exception
&e
) {
3516 WARN("Failed to open playback device: %s\n", e
.what());
3517 alcSetError(nullptr, e
.errorCode());
3521 deviceName
= device
->DeviceName
.c_str();
3522 if(auto chanopt
= ConfigValueStr(deviceName
, nullptr, "channels"))
3524 static const struct ChannelMap
{
3525 const char name
[16];
3526 DevFmtChannels chans
;
3529 { "mono", DevFmtMono
, 0 },
3530 { "stereo", DevFmtStereo
, 0 },
3531 { "quad", DevFmtQuad
, 0 },
3532 { "surround51", DevFmtX51
, 0 },
3533 { "surround61", DevFmtX61
, 0 },
3534 { "surround71", DevFmtX71
, 0 },
3535 { "surround51rear", DevFmtX51Rear
, 0 },
3536 { "ambi1", DevFmtAmbi3D
, 1 },
3537 { "ambi2", DevFmtAmbi3D
, 2 },
3538 { "ambi3", DevFmtAmbi3D
, 3 },
3541 const ALCchar
*fmt
{chanopt
->c_str()};
3542 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3543 [fmt
](const ChannelMap
&entry
) -> bool
3544 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3546 if(iter
== std::end(chanlist
))
3547 ERR("Unsupported channels: %s\n", fmt
);
3550 device
->FmtChans
= iter
->chans
;
3551 device
->mAmbiOrder
= iter
->order
;
3552 device
->Flags
.set
<ChannelsRequest
>();
3555 if(auto typeopt
= ConfigValueStr(deviceName
, nullptr, "sample-type"))
3557 static const struct TypeMap
{
3558 const char name
[16];
3561 { "int8", DevFmtByte
},
3562 { "uint8", DevFmtUByte
},
3563 { "int16", DevFmtShort
},
3564 { "uint16", DevFmtUShort
},
3565 { "int32", DevFmtInt
},
3566 { "uint32", DevFmtUInt
},
3567 { "float32", DevFmtFloat
},
3570 const ALCchar
*fmt
{typeopt
->c_str()};
3571 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3572 [fmt
](const TypeMap
&entry
) -> bool
3573 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3575 if(iter
== std::end(typelist
))
3576 ERR("Unsupported sample-type: %s\n", fmt
);
3579 device
->FmtType
= iter
->type
;
3580 device
->Flags
.set
<SampleTypeRequest
>();
3584 if(ALuint freq
{ConfigValueUInt(deviceName
, nullptr, "frequency").value_or(0)})
3586 if(freq
< MIN_OUTPUT_RATE
|| freq
> MAX_OUTPUT_RATE
)
3588 const ALuint newfreq
{clampu(freq
, MIN_OUTPUT_RATE
, MAX_OUTPUT_RATE
)};
3589 ERR("%uhz request clamped to %uhz\n", freq
, newfreq
);
3592 const double scale
{static_cast<double>(freq
) / device
->Frequency
};
3593 device
->UpdateSize
= static_cast<ALuint
>(device
->UpdateSize
*scale
+ 0.5);
3594 device
->BufferSize
= static_cast<ALuint
>(device
->BufferSize
*scale
+ 0.5);
3595 device
->Frequency
= freq
;
3596 device
->Flags
.set
<FrequencyRequest
>();
3599 if(auto persizeopt
= ConfigValueUInt(deviceName
, nullptr, "period_size"))
3600 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
3602 if(auto peropt
= ConfigValueUInt(deviceName
, nullptr, "periods"))
3603 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
3605 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
3607 if(auto srcsmax
= ConfigValueUInt(deviceName
, nullptr, "sources").value_or(0))
3608 device
->SourcesMax
= srcsmax
;
3610 if(auto slotsmax
= ConfigValueUInt(deviceName
, nullptr, "slots").value_or(0))
3611 device
->AuxiliaryEffectSlotMax
= minu(slotsmax
, INT_MAX
);
3613 if(auto sendsopt
= ConfigValueInt(deviceName
, nullptr, "sends"))
3614 device
->NumAuxSends
= minu(DEFAULT_SENDS
,
3615 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3617 device
->NumStereoSources
= 1;
3618 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3620 if(auto ambiopt
= ConfigValueStr(deviceName
, nullptr, "ambi-format"))
3622 const ALCchar
*fmt
{ambiopt
->c_str()};
3623 if(al::strcasecmp(fmt
, "fuma") == 0)
3625 if(device
->mAmbiOrder
> 3)
3626 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3628 (((device
->mAmbiOrder
%100)/10) == 1) ? "th" :
3629 ((device
->mAmbiOrder
%10) == 1) ? "st" :
3630 ((device
->mAmbiOrder
%10) == 2) ? "nd" :
3631 ((device
->mAmbiOrder
%10) == 3) ? "rd" : "th");
3634 device
->mAmbiLayout
= DevAmbiLayout::FuMa
;
3635 device
->mAmbiScale
= DevAmbiScaling::FuMa
;
3638 else if(al::strcasecmp(fmt
, "ambix") == 0 || al::strcasecmp(fmt
, "acn+sn3d") == 0)
3640 device
->mAmbiLayout
= DevAmbiLayout::ACN
;
3641 device
->mAmbiScale
= DevAmbiScaling::SN3D
;
3643 else if(al::strcasecmp(fmt
, "acn+n3d") == 0)
3645 device
->mAmbiLayout
= DevAmbiLayout::ACN
;
3646 device
->mAmbiScale
= DevAmbiScaling::N3D
;
3649 ERR("Unsupported ambi-format: %s\n", fmt
);
3653 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3654 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3655 DeviceList
.emplace(iter
, device
.get());
3658 TRACE("Created device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3659 device
->DeviceName
.c_str());
3660 return device
.release();
3664 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3667 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3668 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3669 if(iter
== DeviceList
.end() || *iter
!= device
)
3671 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3674 if((*iter
)->Type
== Capture
)
3676 alcSetError(*iter
, ALC_INVALID_DEVICE
);
3680 /* Erase the device, and any remaining contexts left on it, from their
3683 DeviceRef dev
{*iter
};
3684 DeviceList
.erase(iter
);
3686 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3687 al::vector
<ContextRef
> orphanctxs
;
3688 for(ALCcontext
*ctx
: *dev
->mContexts
.load())
3690 auto ctxiter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), ctx
);
3691 if(ctxiter
!= ContextList
.end() && *ctxiter
== ctx
)
3693 orphanctxs
.emplace_back(ContextRef
{*ctxiter
});
3694 ContextList
.erase(ctxiter
);
3699 for(ContextRef
&context
: orphanctxs
)
3701 WARN("Releasing orphaned context %p\n", decltype(std::declval
<void*>()){context
.get()});
3706 if(dev
->Flags
.get
<DeviceRunning
>())
3707 dev
->Backend
->stop();
3708 dev
->Flags
.unset
<DeviceRunning
>();
3715 /************************************************
3716 * ALC capture functions
3717 ************************************************/
3718 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3725 alcSetError(nullptr, ALC_INVALID_VALUE
);
3731 alcSetError(nullptr, ALC_INVALID_VALUE
);
3737 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3738 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3739 deviceName
= nullptr;
3742 DeviceRef device
{new ALCdevice
{Capture
}};
3744 auto decompfmt
= DecomposeDevFormat(format
);
3747 alcSetError(nullptr, ALC_INVALID_ENUM
);
3751 device
->Frequency
= frequency
;
3752 device
->FmtChans
= decompfmt
->chans
;
3753 device
->FmtType
= decompfmt
->type
;
3754 device
->Flags
.set
<FrequencyRequest
, ChannelsRequest
, SampleTypeRequest
>();
3756 device
->UpdateSize
= static_cast<ALuint
>(samples
);
3757 device
->BufferSize
= static_cast<ALuint
>(samples
);
3760 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3761 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
3762 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
3764 auto backend
= CaptureFactory
->createBackend(device
.get(), BackendType::Capture
);
3765 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3766 backend
->open(deviceName
);
3767 device
->Backend
= std::move(backend
);
3769 catch(al::backend_exception
&e
) {
3770 WARN("Failed to open capture device: %s\n", e
.what());
3771 alcSetError(nullptr, e
.errorCode());
3776 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3777 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3778 DeviceList
.emplace(iter
, device
.get());
3781 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3782 device
->DeviceName
.c_str());
3783 return device
.release();
3787 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3790 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3791 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3792 if(iter
== DeviceList
.end() || *iter
!= device
)
3794 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3797 if((*iter
)->Type
!= Capture
)
3799 alcSetError(*iter
, ALC_INVALID_DEVICE
);
3803 DeviceRef dev
{*iter
};
3804 DeviceList
.erase(iter
);
3807 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3808 if(dev
->Flags
.get
<DeviceRunning
>())
3809 dev
->Backend
->stop();
3810 dev
->Flags
.unset
<DeviceRunning
>();
3816 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3819 DeviceRef dev
{VerifyDevice(device
)};
3820 if(!dev
|| dev
->Type
!= Capture
)
3822 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3826 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3827 if(!dev
->Connected
.load(std::memory_order_acquire
))
3828 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3829 else if(!dev
->Flags
.get
<DeviceRunning
>())
3832 auto backend
= dev
->Backend
.get();
3834 dev
->Flags
.set
<DeviceRunning
>();
3836 catch(al::backend_exception
& e
) {
3837 dev
->handleDisconnect("%s", e
.what());
3838 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3844 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3847 DeviceRef dev
{VerifyDevice(device
)};
3848 if(!dev
|| dev
->Type
!= Capture
)
3849 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3852 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3853 if(dev
->Flags
.get
<DeviceRunning
>())
3854 dev
->Backend
->stop();
3855 dev
->Flags
.unset
<DeviceRunning
>();
3860 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3863 DeviceRef dev
{VerifyDevice(device
)};
3864 if(!dev
|| dev
->Type
!= Capture
)
3866 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3870 if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
3872 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3878 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3879 BackendBase
*backend
{dev
->Backend
.get()};
3881 const auto usamples
= static_cast<ALCuint
>(samples
);
3882 if(usamples
> backend
->availableSamples())
3884 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3888 auto *bbuffer
= static_cast<al::byte
*>(buffer
);
3889 if(ALCenum err
{backend
->captureSamples(bbuffer
, usamples
)})
3890 alcSetError(dev
.get(), err
);
3895 /************************************************
3896 * ALC loopback functions
3897 ************************************************/
3899 /** Open a loopback device, for manual rendering. */
3900 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3905 /* Make sure the device name, if specified, is us. */
3906 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3908 alcSetError(nullptr, ALC_INVALID_VALUE
);
3912 DeviceRef device
{new ALCdevice
{Loopback
}};
3914 device
->SourcesMax
= 256;
3915 device
->AuxiliaryEffectSlotMax
= 64;
3916 device
->NumAuxSends
= DEFAULT_SENDS
;
3919 device
->BufferSize
= 0;
3920 device
->UpdateSize
= 0;
3922 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3923 device
->FmtChans
= DevFmtChannelsDefault
;
3924 device
->FmtType
= DevFmtTypeDefault
;
3926 if(auto srcsmax
= ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3927 device
->SourcesMax
= srcsmax
;
3929 if(auto slotsmax
= ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3930 device
->AuxiliaryEffectSlotMax
= minu(slotsmax
, INT_MAX
);
3932 if(auto sendsopt
= ConfigValueInt(nullptr, nullptr, "sends"))
3933 device
->NumAuxSends
= minu(DEFAULT_SENDS
,
3934 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3936 device
->NumStereoSources
= 1;
3937 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3940 auto backend
= LoopbackBackendFactory::getFactory().createBackend(device
.get(),
3941 BackendType::Playback
);
3942 backend
->open("Loopback");
3943 device
->Backend
= std::move(backend
);
3945 catch(al::backend_exception
&e
) {
3946 WARN("Failed to open loopback device: %s\n", e
.what());
3947 alcSetError(nullptr, e
.errorCode());
3952 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3953 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3954 DeviceList
.emplace(iter
, device
.get());
3957 TRACE("Created loopback device %p\n", decltype(std::declval
<void*>()){device
.get()});
3958 return device
.release();
3963 * Determines if the loopback device supports the given format for rendering.
3965 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3968 DeviceRef dev
{VerifyDevice(device
)};
3969 if(!dev
|| dev
->Type
!= Loopback
)
3970 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3972 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3975 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
3976 && freq
<= MAX_OUTPUT_RATE
)
3985 * Renders some samples into a buffer, using the format last set by the
3986 * attributes given to alcCreateContext.
3988 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3991 DeviceRef dev
{VerifyDevice(device
)};
3992 if(!dev
|| dev
->Type
!= Loopback
)
3993 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3994 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
3995 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3997 dev
->renderSamples(buffer
, static_cast<ALuint
>(samples
), dev
->channelsFromFmt());
4002 /************************************************
4003 * ALC DSP pause/resume functions
4004 ************************************************/
4006 /** Pause the DSP to stop audio processing. */
4007 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4010 DeviceRef dev
{VerifyDevice(device
)};
4011 if(!dev
|| dev
->Type
!= Playback
)
4012 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4015 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4016 if(dev
->Flags
.get
<DeviceRunning
>())
4017 dev
->Backend
->stop();
4018 dev
->Flags
.unset
<DeviceRunning
>();
4019 dev
->Flags
.set
<DevicePaused
>();
4024 /** Resume the DSP to restart audio processing. */
4025 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4028 DeviceRef dev
{VerifyDevice(device
)};
4029 if(!dev
|| dev
->Type
!= Playback
)
4031 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4035 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4036 if(!dev
->Flags
.get
<DevicePaused
>())
4038 dev
->Flags
.unset
<DevicePaused
>();
4039 if(dev
->mContexts
.load()->empty())
4043 auto backend
= dev
->Backend
.get();
4045 dev
->Flags
.set
<DeviceRunning
>();
4047 catch(al::backend_exception
& e
) {
4048 dev
->handleDisconnect("%s", e
.what());
4049 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4055 /************************************************
4056 * ALC HRTF functions
4057 ************************************************/
4059 /** Gets a string parameter at the given index. */
4060 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4063 DeviceRef dev
{VerifyDevice(device
)};
4064 if(!dev
|| dev
->Type
== Capture
)
4065 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4066 else switch(paramName
)
4068 case ALC_HRTF_SPECIFIER_SOFT
:
4069 if(index
>= 0 && static_cast<size_t>(index
) < dev
->HrtfList
.size())
4070 return dev
->HrtfList
[static_cast<ALuint
>(index
)].c_str();
4071 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4075 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4083 /** Resets the given device output, using the specified attribute list. */
4084 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4087 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4088 DeviceRef dev
{VerifyDevice(device
)};
4089 if(!dev
|| dev
->Type
== Capture
)
4092 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4095 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4098 /* Force the backend to stop mixing first since we're resetting. Also reset
4099 * the connected state so lost devices can attempt recover.
4101 if(dev
->Flags
.get
<DeviceRunning
>())
4102 dev
->Backend
->stop();
4103 dev
->Flags
.unset
<DeviceRunning
>();
4104 if(!dev
->Connected
.load(std::memory_order_relaxed
))
4106 /* Make sure disconnection is finished before continuing on. */
4109 for(ALCcontext
*ctx
: *dev
->mContexts
.load(std::memory_order_acquire
))
4111 /* Clear any pending voice changes and reallocate voices to get a
4114 std::lock_guard
<std::mutex
> __
{ctx
->mSourceLock
};
4115 auto *vchg
= ctx
->mCurrentVoiceChange
.load(std::memory_order_acquire
);
4116 while(auto *next
= vchg
->mNext
.load(std::memory_order_acquire
))
4118 ctx
->mCurrentVoiceChange
.store(vchg
, std::memory_order_release
);
4120 ctx
->mVoiceClusters
.clear();
4121 ctx
->allocVoices(std::max
<size_t>(256,
4122 ctx
->mActiveVoiceCount
.load(std::memory_order_relaxed
)));
4125 dev
->Connected
.store(true);
4128 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4129 if LIKELY(err
== ALC_NO_ERROR
) return ALC_TRUE
;
4131 alcSetError(dev
.get(), err
);