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
),
407 DECL(alAuxiliaryEffectSlotPlaySOFT
),
408 DECL(alAuxiliaryEffectSlotPlayvSOFT
),
409 DECL(alAuxiliaryEffectSlotStopSOFT
),
410 DECL(alAuxiliaryEffectSlotStopvSOFT
),
414 #define DECL(x) { #x, (x) }
416 const ALCchar
*enumName
;
418 } alcEnumerations
[] = {
423 DECL(ALC_MAJOR_VERSION
),
424 DECL(ALC_MINOR_VERSION
),
425 DECL(ALC_ATTRIBUTES_SIZE
),
426 DECL(ALC_ALL_ATTRIBUTES
),
427 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
428 DECL(ALC_DEVICE_SPECIFIER
),
429 DECL(ALC_ALL_DEVICES_SPECIFIER
),
430 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
431 DECL(ALC_EXTENSIONS
),
435 DECL(ALC_MONO_SOURCES
),
436 DECL(ALC_STEREO_SOURCES
),
437 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
438 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
439 DECL(ALC_CAPTURE_SAMPLES
),
442 DECL(ALC_EFX_MAJOR_VERSION
),
443 DECL(ALC_EFX_MINOR_VERSION
),
444 DECL(ALC_MAX_AUXILIARY_SENDS
),
446 DECL(ALC_FORMAT_CHANNELS_SOFT
),
447 DECL(ALC_FORMAT_TYPE_SOFT
),
450 DECL(ALC_STEREO_SOFT
),
452 DECL(ALC_5POINT1_SOFT
),
453 DECL(ALC_6POINT1_SOFT
),
454 DECL(ALC_7POINT1_SOFT
),
455 DECL(ALC_BFORMAT3D_SOFT
),
458 DECL(ALC_UNSIGNED_BYTE_SOFT
),
459 DECL(ALC_SHORT_SOFT
),
460 DECL(ALC_UNSIGNED_SHORT_SOFT
),
462 DECL(ALC_UNSIGNED_INT_SOFT
),
463 DECL(ALC_FLOAT_SOFT
),
466 DECL(ALC_DONT_CARE_SOFT
),
467 DECL(ALC_HRTF_STATUS_SOFT
),
468 DECL(ALC_HRTF_DISABLED_SOFT
),
469 DECL(ALC_HRTF_ENABLED_SOFT
),
470 DECL(ALC_HRTF_DENIED_SOFT
),
471 DECL(ALC_HRTF_REQUIRED_SOFT
),
472 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
473 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
474 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
475 DECL(ALC_HRTF_SPECIFIER_SOFT
),
476 DECL(ALC_HRTF_ID_SOFT
),
478 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
479 DECL(ALC_AMBISONIC_SCALING_SOFT
),
480 DECL(ALC_AMBISONIC_ORDER_SOFT
),
486 DECL(ALC_OUTPUT_LIMITER_SOFT
),
489 DECL(ALC_INVALID_DEVICE
),
490 DECL(ALC_INVALID_CONTEXT
),
491 DECL(ALC_INVALID_ENUM
),
492 DECL(ALC_INVALID_VALUE
),
493 DECL(ALC_OUT_OF_MEMORY
),
501 DECL(AL_SOURCE_RELATIVE
),
502 DECL(AL_CONE_INNER_ANGLE
),
503 DECL(AL_CONE_OUTER_ANGLE
),
513 DECL(AL_ORIENTATION
),
514 DECL(AL_REFERENCE_DISTANCE
),
515 DECL(AL_ROLLOFF_FACTOR
),
516 DECL(AL_CONE_OUTER_GAIN
),
517 DECL(AL_MAX_DISTANCE
),
519 DECL(AL_SAMPLE_OFFSET
),
520 DECL(AL_BYTE_OFFSET
),
521 DECL(AL_SOURCE_TYPE
),
524 DECL(AL_UNDETERMINED
),
525 DECL(AL_METERS_PER_UNIT
),
526 DECL(AL_LOOP_POINTS_SOFT
),
527 DECL(AL_DIRECT_CHANNELS_SOFT
),
529 DECL(AL_DIRECT_FILTER
),
530 DECL(AL_AUXILIARY_SEND_FILTER
),
531 DECL(AL_AIR_ABSORPTION_FACTOR
),
532 DECL(AL_ROOM_ROLLOFF_FACTOR
),
533 DECL(AL_CONE_OUTER_GAINHF
),
534 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
535 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
536 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
538 DECL(AL_SOURCE_STATE
),
544 DECL(AL_BUFFERS_QUEUED
),
545 DECL(AL_BUFFERS_PROCESSED
),
547 DECL(AL_FORMAT_MONO8
),
548 DECL(AL_FORMAT_MONO16
),
549 DECL(AL_FORMAT_MONO_FLOAT32
),
550 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
551 DECL(AL_FORMAT_STEREO8
),
552 DECL(AL_FORMAT_STEREO16
),
553 DECL(AL_FORMAT_STEREO_FLOAT32
),
554 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
555 DECL(AL_FORMAT_MONO_IMA4
),
556 DECL(AL_FORMAT_STEREO_IMA4
),
557 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
558 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
559 DECL(AL_FORMAT_QUAD8_LOKI
),
560 DECL(AL_FORMAT_QUAD16_LOKI
),
561 DECL(AL_FORMAT_QUAD8
),
562 DECL(AL_FORMAT_QUAD16
),
563 DECL(AL_FORMAT_QUAD32
),
564 DECL(AL_FORMAT_51CHN8
),
565 DECL(AL_FORMAT_51CHN16
),
566 DECL(AL_FORMAT_51CHN32
),
567 DECL(AL_FORMAT_61CHN8
),
568 DECL(AL_FORMAT_61CHN16
),
569 DECL(AL_FORMAT_61CHN32
),
570 DECL(AL_FORMAT_71CHN8
),
571 DECL(AL_FORMAT_71CHN16
),
572 DECL(AL_FORMAT_71CHN32
),
573 DECL(AL_FORMAT_REAR8
),
574 DECL(AL_FORMAT_REAR16
),
575 DECL(AL_FORMAT_REAR32
),
576 DECL(AL_FORMAT_MONO_MULAW
),
577 DECL(AL_FORMAT_MONO_MULAW_EXT
),
578 DECL(AL_FORMAT_STEREO_MULAW
),
579 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
580 DECL(AL_FORMAT_QUAD_MULAW
),
581 DECL(AL_FORMAT_51CHN_MULAW
),
582 DECL(AL_FORMAT_61CHN_MULAW
),
583 DECL(AL_FORMAT_71CHN_MULAW
),
584 DECL(AL_FORMAT_REAR_MULAW
),
585 DECL(AL_FORMAT_MONO_ALAW_EXT
),
586 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
588 DECL(AL_FORMAT_BFORMAT2D_8
),
589 DECL(AL_FORMAT_BFORMAT2D_16
),
590 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
591 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
592 DECL(AL_FORMAT_BFORMAT3D_8
),
593 DECL(AL_FORMAT_BFORMAT3D_16
),
594 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
595 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
601 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
602 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
604 DECL(AL_SOURCE_RADIUS
),
606 DECL(AL_STEREO_ANGLES
),
613 DECL(AL_INVALID_NAME
),
614 DECL(AL_INVALID_ENUM
),
615 DECL(AL_INVALID_VALUE
),
616 DECL(AL_INVALID_OPERATION
),
617 DECL(AL_OUT_OF_MEMORY
),
624 DECL(AL_DOPPLER_FACTOR
),
625 DECL(AL_DOPPLER_VELOCITY
),
626 DECL(AL_DISTANCE_MODEL
),
627 DECL(AL_SPEED_OF_SOUND
),
628 DECL(AL_SOURCE_DISTANCE_MODEL
),
629 DECL(AL_DEFERRED_UPDATES_SOFT
),
630 DECL(AL_GAIN_LIMIT_SOFT
),
632 DECL(AL_INVERSE_DISTANCE
),
633 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
634 DECL(AL_LINEAR_DISTANCE
),
635 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
636 DECL(AL_EXPONENT_DISTANCE
),
637 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
639 DECL(AL_FILTER_TYPE
),
640 DECL(AL_FILTER_NULL
),
641 DECL(AL_FILTER_LOWPASS
),
642 DECL(AL_FILTER_HIGHPASS
),
643 DECL(AL_FILTER_BANDPASS
),
645 DECL(AL_LOWPASS_GAIN
),
646 DECL(AL_LOWPASS_GAINHF
),
648 DECL(AL_HIGHPASS_GAIN
),
649 DECL(AL_HIGHPASS_GAINLF
),
651 DECL(AL_BANDPASS_GAIN
),
652 DECL(AL_BANDPASS_GAINHF
),
653 DECL(AL_BANDPASS_GAINLF
),
655 DECL(AL_EFFECT_TYPE
),
656 DECL(AL_EFFECT_NULL
),
657 DECL(AL_EFFECT_REVERB
),
658 DECL(AL_EFFECT_EAXREVERB
),
659 DECL(AL_EFFECT_CHORUS
),
660 DECL(AL_EFFECT_DISTORTION
),
661 DECL(AL_EFFECT_ECHO
),
662 DECL(AL_EFFECT_FLANGER
),
663 DECL(AL_EFFECT_PITCH_SHIFTER
),
664 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
665 DECL(AL_EFFECT_VOCAL_MORPHER
),
666 DECL(AL_EFFECT_RING_MODULATOR
),
667 DECL(AL_EFFECT_AUTOWAH
),
668 DECL(AL_EFFECT_COMPRESSOR
),
669 DECL(AL_EFFECT_EQUALIZER
),
670 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
671 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
673 DECL(AL_EFFECTSLOT_EFFECT
),
674 DECL(AL_EFFECTSLOT_GAIN
),
675 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
676 DECL(AL_EFFECTSLOT_NULL
),
678 DECL(AL_EAXREVERB_DENSITY
),
679 DECL(AL_EAXREVERB_DIFFUSION
),
680 DECL(AL_EAXREVERB_GAIN
),
681 DECL(AL_EAXREVERB_GAINHF
),
682 DECL(AL_EAXREVERB_GAINLF
),
683 DECL(AL_EAXREVERB_DECAY_TIME
),
684 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
685 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
686 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
687 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
688 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
689 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
690 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
691 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
692 DECL(AL_EAXREVERB_ECHO_TIME
),
693 DECL(AL_EAXREVERB_ECHO_DEPTH
),
694 DECL(AL_EAXREVERB_MODULATION_TIME
),
695 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
696 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
697 DECL(AL_EAXREVERB_HFREFERENCE
),
698 DECL(AL_EAXREVERB_LFREFERENCE
),
699 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
700 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
702 DECL(AL_REVERB_DENSITY
),
703 DECL(AL_REVERB_DIFFUSION
),
704 DECL(AL_REVERB_GAIN
),
705 DECL(AL_REVERB_GAINHF
),
706 DECL(AL_REVERB_DECAY_TIME
),
707 DECL(AL_REVERB_DECAY_HFRATIO
),
708 DECL(AL_REVERB_REFLECTIONS_GAIN
),
709 DECL(AL_REVERB_REFLECTIONS_DELAY
),
710 DECL(AL_REVERB_LATE_REVERB_GAIN
),
711 DECL(AL_REVERB_LATE_REVERB_DELAY
),
712 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
713 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
714 DECL(AL_REVERB_DECAY_HFLIMIT
),
716 DECL(AL_CHORUS_WAVEFORM
),
717 DECL(AL_CHORUS_PHASE
),
718 DECL(AL_CHORUS_RATE
),
719 DECL(AL_CHORUS_DEPTH
),
720 DECL(AL_CHORUS_FEEDBACK
),
721 DECL(AL_CHORUS_DELAY
),
723 DECL(AL_DISTORTION_EDGE
),
724 DECL(AL_DISTORTION_GAIN
),
725 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
726 DECL(AL_DISTORTION_EQCENTER
),
727 DECL(AL_DISTORTION_EQBANDWIDTH
),
730 DECL(AL_ECHO_LRDELAY
),
731 DECL(AL_ECHO_DAMPING
),
732 DECL(AL_ECHO_FEEDBACK
),
733 DECL(AL_ECHO_SPREAD
),
735 DECL(AL_FLANGER_WAVEFORM
),
736 DECL(AL_FLANGER_PHASE
),
737 DECL(AL_FLANGER_RATE
),
738 DECL(AL_FLANGER_DEPTH
),
739 DECL(AL_FLANGER_FEEDBACK
),
740 DECL(AL_FLANGER_DELAY
),
742 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
743 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
744 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
746 DECL(AL_RING_MODULATOR_FREQUENCY
),
747 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
748 DECL(AL_RING_MODULATOR_WAVEFORM
),
750 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
751 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
753 DECL(AL_COMPRESSOR_ONOFF
),
755 DECL(AL_EQUALIZER_LOW_GAIN
),
756 DECL(AL_EQUALIZER_LOW_CUTOFF
),
757 DECL(AL_EQUALIZER_MID1_GAIN
),
758 DECL(AL_EQUALIZER_MID1_CENTER
),
759 DECL(AL_EQUALIZER_MID1_WIDTH
),
760 DECL(AL_EQUALIZER_MID2_GAIN
),
761 DECL(AL_EQUALIZER_MID2_CENTER
),
762 DECL(AL_EQUALIZER_MID2_WIDTH
),
763 DECL(AL_EQUALIZER_HIGH_GAIN
),
764 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
766 DECL(AL_DEDICATED_GAIN
),
768 DECL(AL_AUTOWAH_ATTACK_TIME
),
769 DECL(AL_AUTOWAH_RELEASE_TIME
),
770 DECL(AL_AUTOWAH_RESONANCE
),
771 DECL(AL_AUTOWAH_PEAK_GAIN
),
773 DECL(AL_VOCAL_MORPHER_PHONEMEA
),
774 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
775 DECL(AL_VOCAL_MORPHER_PHONEMEB
),
776 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
777 DECL(AL_VOCAL_MORPHER_WAVEFORM
),
778 DECL(AL_VOCAL_MORPHER_RATE
),
780 DECL(AL_EFFECTSLOT_TARGET_SOFT
),
782 DECL(AL_NUM_RESAMPLERS_SOFT
),
783 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
784 DECL(AL_SOURCE_RESAMPLER_SOFT
),
785 DECL(AL_RESAMPLER_NAME_SOFT
),
787 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
790 DECL(AL_MAP_READ_BIT_SOFT
),
791 DECL(AL_MAP_WRITE_BIT_SOFT
),
792 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
793 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
795 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
796 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
797 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
798 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
799 DECL(AL_EVENT_TYPE_DISCONNECTED_SOFT
),
801 DECL(AL_DROP_UNMATCHED_SOFT
),
802 DECL(AL_REMIX_UNMATCHED_SOFT
),
804 DECL(AL_AMBISONIC_LAYOUT_SOFT
),
805 DECL(AL_AMBISONIC_SCALING_SOFT
),
811 DECL(AL_BUFFER_CALLBACK_FUNCTION_SOFT
),
812 DECL(AL_BUFFER_CALLBACK_USER_PARAM_SOFT
),
814 DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT
),
816 DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT
),
817 DECL(AL_EFFECTSLOT_STATE_SOFT
),
821 constexpr ALCchar alcNoError
[] = "No Error";
822 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
823 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
824 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
825 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
826 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
829 /************************************************
831 ************************************************/
833 /* Enumerated device names */
834 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
836 std::string alcAllDevicesList
;
837 std::string alcCaptureDeviceList
;
839 /* Default is always the first in the list */
840 al::string alcDefaultAllDevicesSpecifier
;
841 al::string alcCaptureDefaultDeviceSpecifier
;
843 /* Default context extensions */
844 constexpr ALchar alExtList
[] =
848 "AL_EXT_EXPONENT_DISTANCE "
851 "AL_EXT_LINEAR_DISTANCE "
854 "AL_EXT_MULAW_BFORMAT "
855 "AL_EXT_MULAW_MCFORMATS "
857 "AL_EXT_source_distance_model "
858 "AL_EXT_SOURCE_RADIUS "
859 "AL_EXT_STEREO_ANGLES "
860 "AL_LOKI_quadriphonic "
861 "AL_SOFT_bformat_ex "
862 "AL_SOFTX_bformat_hoa "
863 "AL_SOFT_block_alignment "
864 "AL_SOFTX_callback_buffer "
865 "AL_SOFTX_convolution_reverb "
866 "AL_SOFT_deferred_updates "
867 "AL_SOFT_direct_channels "
868 "AL_SOFT_direct_channels_remix "
869 "AL_SOFT_effect_target "
871 "AL_SOFTX_filter_gain_ex "
872 "AL_SOFT_gain_clamp_ex "
873 "AL_SOFT_loop_points "
874 "AL_SOFTX_map_buffer "
876 "AL_SOFT_source_latency "
877 "AL_SOFT_source_length "
878 "AL_SOFT_source_resampler "
879 "AL_SOFT_source_spatialize";
881 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
883 /* Thread-local current context. The handling may look a little obtuse, but
884 * it's designed this way to avoid a bug with 32-bit GCC/MinGW, which causes
885 * thread-local object destructors to get a junk 'this' pointer. This method
886 * has the benefit of making LocalContext access more efficient since it's a
887 * a plain pointer, with the ThreadContext object used to check it at thread
888 * exit (and given no data fields, 'this' being junk is inconsequential since
889 * it's never accessed).
891 thread_local ALCcontext
*LocalContext
{nullptr};
896 if(ALCcontext
*ctx
{LocalContext
})
898 const bool result
{ctx
->releaseIfNoDelete()};
899 ERR("Context %p current for thread being destroyed%s!\n",
900 decltype(std::declval
<void*>()){ctx
}, result
? "" : ", leak detected");
904 void set(ALCcontext
*ctx
) const noexcept
{ LocalContext
= ctx
; }
906 thread_local ThreadCtx ThreadContext
;
908 /* Process-wide current context */
909 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
911 /* Flag to trap ALC device errors */
912 bool TrapALCError
{false};
914 /* One-time configuration init control */
915 std::once_flag alc_config_once
{};
917 /* Default effect that applies to sources that don't have an effect on send 0 */
918 ALeffect DefaultEffect
;
920 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
923 bool SuspendDefers
{true};
925 /* Initial seed for dithering. */
926 constexpr ALuint DitherRNGSeed
{22222u};
929 /************************************************
931 ************************************************/
932 constexpr ALCchar alcNoDeviceExtList
[] =
933 "ALC_ENUMERATE_ALL_EXT "
934 "ALC_ENUMERATION_EXT "
936 "ALC_EXT_thread_local_context "
938 "ALC_SOFT_loopback_bformat";
939 constexpr ALCchar alcExtensionList
[] =
940 "ALC_ENUMERATE_ALL_EXT "
941 "ALC_ENUMERATION_EXT "
944 "ALC_EXT_disconnect "
946 "ALC_EXT_thread_local_context "
947 "ALC_SOFT_device_clock "
950 "ALC_SOFT_loopback_bformat "
951 "ALC_SOFT_output_limiter "
952 "ALC_SOFT_pause_device";
953 constexpr int alcMajorVersion
{1};
954 constexpr int alcMinorVersion
{1};
956 constexpr int alcEFXMajorVersion
{1};
957 constexpr int alcEFXMinorVersion
{0};
960 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
961 * globally as a sharable object.
963 al::FlexArray
<ALCcontext
*> EmptyContextArray
{0u};
966 using DeviceRef
= al::intrusive_ptr
<ALCdevice
>;
969 /************************************************
971 ************************************************/
972 al::vector
<ALCdevice
*> DeviceList
;
973 al::vector
<ALCcontext
*> ContextList
;
975 std::recursive_mutex ListLock
;
978 void alc_initconfig(void)
980 if(auto loglevel
= al::getenv("ALSOFT_LOGLEVEL"))
982 long lvl
= strtol(loglevel
->c_str(), nullptr, 0);
983 if(lvl
>= static_cast<long>(LogLevel::Trace
))
984 gLogLevel
= LogLevel::Trace
;
985 else if(lvl
<= static_cast<long>(LogLevel::Disable
))
986 gLogLevel
= LogLevel::Disable
;
988 gLogLevel
= static_cast<LogLevel
>(lvl
);
992 if(const auto logfile
= al::getenv(L
"ALSOFT_LOGFILE"))
994 FILE *logf
{_wfopen(logfile
->c_str(), L
"wt")};
995 if(logf
) gLogFile
= logf
;
998 auto u8name
= wstr_to_utf8(logfile
->c_str());
999 ERR("Failed to open log file '%s'\n", u8name
.c_str());
1003 if(const auto logfile
= al::getenv("ALSOFT_LOGFILE"))
1005 FILE *logf
{fopen(logfile
->c_str(), "wt")};
1006 if(logf
) gLogFile
= logf
;
1007 else ERR("Failed to open log file '%s'\n", logfile
->c_str());
1011 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
, ALSOFT_GIT_COMMIT_HASH
,
1015 if(al::size(BackendList
) < 1)
1019 const al::span
<const BackendInfo
> infos
{BackendList
};
1020 names
= infos
[0].name
;
1021 for(const auto &backend
: infos
.subspan
<1>())
1024 names
+= backend
.name
;
1027 TRACE("Supported backends: %s\n", names
.c_str());
1031 if(auto suspendmode
= al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
1033 if(al::strcasecmp(suspendmode
->c_str(), "ignore") == 0)
1035 SuspendDefers
= false;
1036 TRACE("Selected context suspend behavior, \"ignore\"\n");
1039 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode
->c_str());
1043 #if defined(HAVE_SSE4_1)
1044 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1045 #elif defined(HAVE_SSE3)
1046 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1047 #elif defined(HAVE_SSE2)
1048 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1049 #elif defined(HAVE_SSE)
1050 capfilter
|= CPU_CAP_SSE
;
1053 capfilter
|= CPU_CAP_NEON
;
1055 if(auto cpuopt
= ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1057 const char *str
{cpuopt
->c_str()};
1058 if(al::strcasecmp(str
, "all") == 0)
1062 const char *next
= str
;
1065 while(isspace(str
[0]))
1067 next
= strchr(str
, ',');
1069 if(!str
[0] || str
[0] == ',')
1072 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1073 while(len
> 0 && isspace(str
[len
-1]))
1075 if(len
== 3 && al::strncasecmp(str
, "sse", len
) == 0)
1076 capfilter
&= ~CPU_CAP_SSE
;
1077 else if(len
== 4 && al::strncasecmp(str
, "sse2", len
) == 0)
1078 capfilter
&= ~CPU_CAP_SSE2
;
1079 else if(len
== 4 && al::strncasecmp(str
, "sse3", len
) == 0)
1080 capfilter
&= ~CPU_CAP_SSE3
;
1081 else if(len
== 6 && al::strncasecmp(str
, "sse4.1", len
) == 0)
1082 capfilter
&= ~CPU_CAP_SSE4_1
;
1083 else if(len
== 4 && al::strncasecmp(str
, "neon", len
) == 0)
1084 capfilter
&= ~CPU_CAP_NEON
;
1086 WARN("Invalid CPU extension \"%s\"\n", str
);
1090 FillCPUCaps(capfilter
);
1092 if(auto priopt
= ConfigValueInt(nullptr, nullptr, "rt-prio"))
1093 RTPrioLevel
= *priopt
;
1098 auto traperr
= al::getenv("ALSOFT_TRAP_ERROR");
1099 if(traperr
&& (al::strcasecmp(traperr
->c_str(), "true") == 0
1100 || std::strtol(traperr
->c_str(), nullptr, 0) == 1))
1103 TrapALCError
= true;
1107 traperr
= al::getenv("ALSOFT_TRAP_AL_ERROR");
1109 TrapALError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1110 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1112 TrapALError
= !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1114 traperr
= al::getenv("ALSOFT_TRAP_ALC_ERROR");
1116 TrapALCError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1117 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1119 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1122 if(auto boostopt
= ConfigValueFloat(nullptr, "reverb", "boost"))
1124 const float valf
{std::isfinite(*boostopt
) ? clampf(*boostopt
, -24.0f
, 24.0f
) : 0.0f
};
1125 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1128 auto BackendListEnd
= std::end(BackendList
);
1129 auto devopt
= al::getenv("ALSOFT_DRIVERS");
1130 if(devopt
|| (devopt
=ConfigValueStr(nullptr, nullptr, "drivers")))
1132 auto backendlist_cur
= std::begin(BackendList
);
1135 const char *next
{devopt
->c_str()};
1137 const char *devs
{next
};
1138 while(isspace(devs
[0]))
1140 next
= strchr(devs
, ',');
1142 const bool delitem
{devs
[0] == '-'};
1143 if(devs
[0] == '-') devs
++;
1145 if(!devs
[0] || devs
[0] == ',')
1152 size_t len
{next
? (static_cast<size_t>(next
-devs
)) : strlen(devs
)};
1153 while(len
> 0 && isspace(devs
[len
-1])) --len
;
1155 /* HACK: For backwards compatibility, convert backend references of
1156 * mmdevapi to wasapi. This should eventually be removed.
1158 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1165 auto find_backend
= [devs
,len
](const BackendInfo
&backend
) -> bool
1166 { return len
== strlen(backend
.name
) && strncmp(backend
.name
, devs
, len
) == 0; };
1167 auto this_backend
= std::find_if(std::begin(BackendList
), BackendListEnd
,
1170 if(this_backend
== BackendListEnd
)
1174 BackendListEnd
= std::move(this_backend
+1, BackendListEnd
, this_backend
);
1176 backendlist_cur
= std::rotate(backendlist_cur
, this_backend
, this_backend
+1);
1180 BackendListEnd
= backendlist_cur
;
1183 auto init_backend
= [](BackendInfo
&backend
) -> void
1185 if(PlaybackFactory
&& CaptureFactory
)
1188 BackendFactory
&factory
= backend
.getFactory();
1191 WARN("Failed to initialize backend \"%s\"\n", backend
.name
);
1195 TRACE("Initialized backend \"%s\"\n", backend
.name
);
1196 if(!PlaybackFactory
&& factory
.querySupport(BackendType::Playback
))
1198 PlaybackFactory
= &factory
;
1199 TRACE("Added \"%s\" for playback\n", backend
.name
);
1201 if(!CaptureFactory
&& factory
.querySupport(BackendType::Capture
))
1203 CaptureFactory
= &factory
;
1204 TRACE("Added \"%s\" for capture\n", backend
.name
);
1207 std::for_each(std::begin(BackendList
), BackendListEnd
, init_backend
);
1209 LoopbackBackendFactory::getFactory().init();
1211 if(!PlaybackFactory
)
1212 WARN("No playback backend available!\n");
1214 WARN("No capture backend available!\n");
1216 if(auto exclopt
= ConfigValueStr(nullptr, nullptr, "excludefx"))
1218 const char *next
{exclopt
->c_str()};
1220 const char *str
{next
};
1221 next
= strchr(str
, ',');
1223 if(!str
[0] || next
== str
)
1226 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1227 for(const EffectList
&effectitem
: gEffectList
)
1229 if(len
== strlen(effectitem
.name
) &&
1230 strncmp(effectitem
.name
, str
, len
) == 0)
1231 DisabledEffects
[effectitem
.type
] = true;
1236 InitEffect(&DefaultEffect
);
1237 auto defrevopt
= al::getenv("ALSOFT_DEFAULT_REVERB");
1238 if(defrevopt
|| (defrevopt
=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1239 LoadReverbPreset(defrevopt
->c_str(), &DefaultEffect
);
1241 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1244 /************************************************
1245 * Device enumeration
1246 ************************************************/
1247 void ProbeAllDevicesList()
1251 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1252 if(!PlaybackFactory
)
1253 decltype(alcAllDevicesList
){}.swap(alcAllDevicesList
);
1256 std::string names
{PlaybackFactory
->probe(BackendType::Playback
)};
1257 if(names
.empty()) names
+= '\0';
1258 names
.swap(alcAllDevicesList
);
1261 void ProbeCaptureDeviceList()
1265 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1267 decltype(alcCaptureDeviceList
){}.swap(alcCaptureDeviceList
);
1270 std::string names
{CaptureFactory
->probe(BackendType::Capture
)};
1271 if(names
.empty()) names
+= '\0';
1272 names
.swap(alcCaptureDeviceList
);
1278 /* Mixing thread piority level */
1281 FILE *gLogFile
{stderr
};
1283 LogLevel gLogLevel
{LogLevel::Warning
};
1285 LogLevel gLogLevel
{LogLevel::Error
};
1288 /************************************************
1289 * Library initialization
1290 ************************************************/
1291 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1292 BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID
/*reserved*/)
1296 case DLL_PROCESS_ATTACH
:
1297 /* Pin the DLL so we won't get unloaded until the process terminates */
1298 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
1299 reinterpret_cast<WCHAR
*>(module
), &module
);
1306 /************************************************
1307 * Device format information
1308 ************************************************/
1309 const ALCchar
*DevFmtTypeString(DevFmtType type
) noexcept
1313 case DevFmtByte
: return "Int8";
1314 case DevFmtUByte
: return "UInt8";
1315 case DevFmtShort
: return "Int16";
1316 case DevFmtUShort
: return "UInt16";
1317 case DevFmtInt
: return "Int32";
1318 case DevFmtUInt
: return "UInt32";
1319 case DevFmtFloat
: return "Float32";
1321 return "(unknown type)";
1323 const ALCchar
*DevFmtChannelsString(DevFmtChannels chans
) noexcept
1327 case DevFmtMono
: return "Mono";
1328 case DevFmtStereo
: return "Stereo";
1329 case DevFmtQuad
: return "Quadraphonic";
1330 case DevFmtX51
: return "5.1 Surround";
1331 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1332 case DevFmtX61
: return "6.1 Surround";
1333 case DevFmtX71
: return "7.1 Surround";
1334 case DevFmtAmbi3D
: return "Ambisonic 3D";
1336 return "(unknown channels)";
1339 ALuint
BytesFromDevFmt(DevFmtType type
) noexcept
1343 case DevFmtByte
: return sizeof(int8_t);
1344 case DevFmtUByte
: return sizeof(uint8_t);
1345 case DevFmtShort
: return sizeof(int16_t);
1346 case DevFmtUShort
: return sizeof(uint16_t);
1347 case DevFmtInt
: return sizeof(int32_t);
1348 case DevFmtUInt
: return sizeof(uint32_t);
1349 case DevFmtFloat
: return sizeof(float);
1353 ALuint
ChannelsFromDevFmt(DevFmtChannels chans
, ALuint ambiorder
) noexcept
1357 case DevFmtMono
: return 1;
1358 case DevFmtStereo
: return 2;
1359 case DevFmtQuad
: return 4;
1360 case DevFmtX51
: return 6;
1361 case DevFmtX51Rear
: return 6;
1362 case DevFmtX61
: return 7;
1363 case DevFmtX71
: return 8;
1364 case DevFmtAmbi3D
: return (ambiorder
+1) * (ambiorder
+1);
1371 struct DevFmtPair
{ DevFmtChannels chans
; DevFmtType type
; };
1372 al::optional
<DevFmtPair
> DecomposeDevFormat(ALenum format
)
1374 static const struct {
1376 DevFmtChannels channels
;
1379 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1380 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1381 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1383 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1384 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1385 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1387 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1388 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1389 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1391 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1392 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1393 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1395 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1396 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1397 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1399 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1400 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1401 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1404 for(const auto &item
: list
)
1406 if(item
.format
== format
)
1407 return al::make_optional(DevFmtPair
{item
.channels
, item
.type
});
1413 bool IsValidALCType(ALCenum type
)
1418 case ALC_UNSIGNED_BYTE_SOFT
:
1419 case ALC_SHORT_SOFT
:
1420 case ALC_UNSIGNED_SHORT_SOFT
:
1422 case ALC_UNSIGNED_INT_SOFT
:
1423 case ALC_FLOAT_SOFT
:
1429 bool IsValidALCChannels(ALCenum channels
)
1434 case ALC_STEREO_SOFT
:
1436 case ALC_5POINT1_SOFT
:
1437 case ALC_6POINT1_SOFT
:
1438 case ALC_7POINT1_SOFT
:
1439 case ALC_BFORMAT3D_SOFT
:
1445 bool IsValidAmbiLayout(ALCenum layout
)
1456 bool IsValidAmbiScaling(ALCenum scaling
)
1469 /* Downmixing channel arrays, to map the given format's missing channels to
1470 * existing ones. Based on Wine's DSound downmix values, which are based on
1473 const std::array
<InputRemixMap
,7> MonoDownmix
{{
1474 { FrontLeft
, {{{FrontCenter
, 0.5f
}, {LFE
, 0.0f
}}} },
1475 { FrontRight
, {{{FrontCenter
, 0.5f
}, {LFE
, 0.0f
}}} },
1476 { SideLeft
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1477 { SideRight
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1478 { BackLeft
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1479 { BackRight
, {{{FrontCenter
, 0.5f
/9.0f
}, {LFE
, 0.0f
}}} },
1480 { BackCenter
, {{{FrontCenter
, 1.0f
/9.0f
}, {LFE
, 0.0f
}}} },
1482 const std::array
<InputRemixMap
,6> StereoDownmix
{{
1483 { FrontCenter
, {{{FrontLeft
, 0.5f
}, {FrontRight
, 0.5f
}}} },
1484 { SideLeft
, {{{FrontLeft
, 1.0f
/9.0f
}, {FrontRight
, 0.0f
}}} },
1485 { SideRight
, {{{FrontLeft
, 0.0f
}, {FrontRight
, 1.0f
/9.0f
}}} },
1486 { BackLeft
, {{{FrontLeft
, 1.0f
/9.0f
}, {FrontRight
, 0.0f
}}} },
1487 { BackRight
, {{{FrontLeft
, 0.0f
}, {FrontRight
, 1.0f
/9.0f
}}} },
1488 { BackCenter
, {{{FrontLeft
, 0.5f
/9.0f
}, {FrontRight
, 0.5f
/9.0f
}}} },
1490 const std::array
<InputRemixMap
,4> QuadDownmix
{{
1491 { FrontCenter
, {{{FrontLeft
, 0.5f
}, {FrontRight
, 0.5f
}}} },
1492 { SideLeft
, {{{FrontLeft
, 0.5f
}, {BackLeft
, 0.5f
}}} },
1493 { SideRight
, {{{FrontRight
, 0.5f
}, {BackRight
, 0.5f
}}} },
1494 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1496 const std::array
<InputRemixMap
,3> X51Downmix
{{
1497 { BackLeft
, {{{SideLeft
, 1.0f
}, {SideRight
, 0.0f
}}} },
1498 { BackRight
, {{{SideLeft
, 0.0f
}, {SideRight
, 1.0f
}}} },
1499 { BackCenter
, {{{SideLeft
, 0.5f
}, {SideRight
, 0.5f
}}} },
1501 const std::array
<InputRemixMap
,3> X51RearDownmix
{{
1502 { SideLeft
, {{{BackLeft
, 1.0f
}, {BackRight
, 0.0f
}}} },
1503 { SideRight
, {{{BackLeft
, 0.0f
}, {BackRight
, 1.0f
}}} },
1504 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1506 const std::array
<InputRemixMap
,2> X61Downmix
{{
1507 { BackLeft
, {{{BackCenter
, 0.5f
}, {SideLeft
, 0.5f
}}} },
1508 { BackRight
, {{{BackCenter
, 0.5f
}, {SideRight
, 0.5f
}}} },
1510 const std::array
<InputRemixMap
,1> X71Downmix
{{
1511 { BackCenter
, {{{BackLeft
, 0.5f
}, {BackRight
, 0.5f
}}} },
1516 /************************************************
1517 * Miscellaneous ALC helpers
1518 ************************************************/
1520 void ALCcontext::processUpdates()
1522 std::lock_guard
<std::mutex
> _
{mPropLock
};
1523 if(mDeferUpdates
.exchange(false, std::memory_order_acq_rel
))
1525 /* Tell the mixer to stop applying updates, then wait for any active
1526 * updating to finish, before providing updates.
1528 mHoldUpdates
.store(true, std::memory_order_release
);
1529 while((mUpdateCount
.load(std::memory_order_acquire
)&1) != 0) {
1533 if(!mPropsClean
.test_and_set(std::memory_order_acq_rel
))
1534 UpdateContextProps(this);
1535 if(!mListener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1536 UpdateListenerProps(this);
1537 UpdateAllEffectSlotProps(this);
1538 UpdateAllSourceProps(this);
1540 /* Now with all updates declared, let the mixer continue applying them
1541 * so they all happen at once.
1543 mHoldUpdates
.store(false, std::memory_order_release
);
1548 void ALCcontext::allocVoiceChanges(size_t addcount
)
1550 constexpr size_t clustersize
{128};
1551 /* Convert element count to cluster count. */
1552 addcount
= (addcount
+(clustersize
-1)) / clustersize
;
1555 VoiceChangeCluster cluster
{std::make_unique
<VoiceChange
[]>(clustersize
)};
1556 for(size_t i
{1};i
< clustersize
;++i
)
1557 cluster
[i
-1].mNext
.store(std::addressof(cluster
[i
]), std::memory_order_relaxed
);
1558 cluster
[clustersize
-1].mNext
.store(mVoiceChangeTail
, std::memory_order_relaxed
);
1559 mVoiceChangeClusters
.emplace_back(std::move(cluster
));
1560 mVoiceChangeTail
= mVoiceChangeClusters
.back().get();
1565 void ALCcontext::allocVoices(size_t addcount
)
1567 constexpr size_t clustersize
{32};
1568 /* Convert element count to cluster count. */
1569 addcount
= (addcount
+(clustersize
-1)) / clustersize
;
1571 if(addcount
>= std::numeric_limits
<int>::max()/clustersize
- mVoiceClusters
.size())
1572 throw std::runtime_error
{"Allocating too many voices"};
1573 const size_t totalcount
{(mVoiceClusters
.size()+addcount
) * clustersize
};
1574 TRACE("Increasing allocated voices to %zu\n", totalcount
);
1576 auto newarray
= VoiceArray::Create(totalcount
);
1579 mVoiceClusters
.emplace_back(std::make_unique
<Voice
[]>(clustersize
));
1583 auto voice_iter
= newarray
->begin();
1584 for(VoiceCluster
&cluster
: mVoiceClusters
)
1586 for(size_t i
{0};i
< clustersize
;++i
)
1587 *(voice_iter
++) = &cluster
[i
];
1590 if(auto *oldvoices
= mVoices
.exchange(newarray
.release(), std::memory_order_acq_rel
))
1592 mDevice
->waitForMix();
1598 /** Stores the latest ALC device error. */
1599 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1601 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval
<void*>()){device
},
1606 /* DebugBreak() will cause an exception if there is no debugger */
1607 if(IsDebuggerPresent())
1609 #elif defined(SIGTRAP)
1615 device
->LastError
.store(errorCode
);
1617 LastNullDeviceError
.store(errorCode
);
1621 static std::unique_ptr
<Compressor
> CreateDeviceLimiter(const ALCdevice
*device
, const float threshold
)
1623 constexpr bool AutoKnee
{true};
1624 constexpr bool AutoAttack
{true};
1625 constexpr bool AutoRelease
{true};
1626 constexpr bool AutoPostGain
{true};
1627 constexpr bool AutoDeclip
{true};
1628 constexpr float LookAheadTime
{0.001f
};
1629 constexpr float HoldTime
{0.002f
};
1630 constexpr float PreGainDb
{0.0f
};
1631 constexpr float PostGainDb
{0.0f
};
1632 constexpr float Ratio
{std::numeric_limits
<float>::infinity()};
1633 constexpr float KneeDb
{0.0f
};
1634 constexpr float AttackTime
{0.02f
};
1635 constexpr float ReleaseTime
{0.2f
};
1637 return Compressor::Create(device
->RealOut
.Buffer
.size(), static_cast<float>(device
->Frequency
),
1638 AutoKnee
, AutoAttack
, AutoRelease
, AutoPostGain
, AutoDeclip
, LookAheadTime
, HoldTime
,
1639 PreGainDb
, PostGainDb
, threshold
, Ratio
, KneeDb
, AttackTime
, ReleaseTime
);
1643 * Updates the device's base clock time with however many samples have been
1644 * done. This is used so frequency changes on the device don't cause the time
1645 * to jump forward or back. Must not be called while the device is running/
1648 static inline void UpdateClockBase(ALCdevice
*device
)
1650 IncrementRef(device
->MixCount
);
1651 device
->ClockBase
+= nanoseconds
{seconds
{device
->SamplesDone
}} / device
->Frequency
;
1652 device
->SamplesDone
= 0;
1653 IncrementRef(device
->MixCount
);
1657 * Updates device parameters according to the attribute list (caller is
1658 * responsible for holding the list lock).
1660 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const int *attrList
)
1662 HrtfRequestMode hrtf_userreq
{Hrtf_Default
};
1663 HrtfRequestMode hrtf_appreq
{Hrtf_Default
};
1664 ALCenum gainLimiter
{device
->LimiterState
};
1665 ALCuint new_sends
{device
->NumAuxSends
};
1666 DevFmtChannels oldChans
;
1668 ALCsizei hrtf_id
{-1};
1671 if((!attrList
|| !attrList
[0]) && device
->Type
== DeviceType::Loopback
)
1673 WARN("Missing attributes for loopback device\n");
1674 return ALC_INVALID_VALUE
;
1677 // Check for attributes
1678 if(attrList
&& attrList
[0])
1680 ALCenum alayout
{AL_NONE
};
1681 ALCenum ascale
{AL_NONE
};
1682 ALCenum schans
{AL_NONE
};
1683 ALCenum stype
{AL_NONE
};
1684 ALCsizei attrIdx
{0};
1688 ALuint numMono
{device
->NumMonoSources
};
1689 ALuint numStereo
{device
->NumStereoSources
};
1690 ALuint numSends
{device
->NumAuxSends
};
1692 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1693 while(attrList
[attrIdx
])
1695 switch(attrList
[attrIdx
])
1697 case ALC_FORMAT_CHANNELS_SOFT
:
1698 schans
= attrList
[attrIdx
+ 1];
1699 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1702 case ALC_FORMAT_TYPE_SOFT
:
1703 stype
= attrList
[attrIdx
+ 1];
1704 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1708 freq
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1709 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1712 case ALC_AMBISONIC_LAYOUT_SOFT
:
1713 alayout
= attrList
[attrIdx
+ 1];
1714 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1717 case ALC_AMBISONIC_SCALING_SOFT
:
1718 ascale
= attrList
[attrIdx
+ 1];
1719 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1722 case ALC_AMBISONIC_ORDER_SOFT
:
1723 aorder
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1724 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1727 case ALC_MONO_SOURCES
:
1728 numMono
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1729 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1730 if(numMono
> INT_MAX
) numMono
= 0;
1733 case ALC_STEREO_SOURCES
:
1734 numStereo
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1735 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1736 if(numStereo
> INT_MAX
) numStereo
= 0;
1739 case ALC_MAX_AUXILIARY_SENDS
:
1740 numSends
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1741 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1742 if(numSends
> INT_MAX
) numSends
= 0;
1743 else numSends
= minu(numSends
, MAX_SENDS
);
1747 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1748 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1749 hrtf_appreq
= Hrtf_Disable
;
1750 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1751 hrtf_appreq
= Hrtf_Enable
;
1753 hrtf_appreq
= Hrtf_Default
;
1756 case ALC_HRTF_ID_SOFT
:
1757 hrtf_id
= attrList
[attrIdx
+ 1];
1758 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1761 case ALC_OUTPUT_LIMITER_SOFT
:
1762 gainLimiter
= attrList
[attrIdx
+ 1];
1763 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1767 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1768 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1776 const bool loopback
{device
->Type
== DeviceType::Loopback
};
1779 if(!schans
|| !stype
|| !freq
)
1781 WARN("Missing format for loopback device\n");
1782 return ALC_INVALID_VALUE
;
1784 if(!IsValidALCChannels(schans
) || !IsValidALCType(stype
) || freq
< MIN_OUTPUT_RATE
1785 || freq
> MAX_OUTPUT_RATE
)
1786 return ALC_INVALID_VALUE
;
1787 if(schans
== ALC_BFORMAT3D_SOFT
)
1789 if(!alayout
|| !ascale
|| !aorder
)
1791 WARN("Missing ambisonic info for loopback device\n");
1792 return ALC_INVALID_VALUE
;
1794 if(!IsValidAmbiLayout(alayout
) || !IsValidAmbiScaling(ascale
))
1795 return ALC_INVALID_VALUE
;
1796 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1797 return ALC_INVALID_VALUE
;
1798 if((alayout
== ALC_FUMA_SOFT
|| ascale
== ALC_FUMA_SOFT
) && aorder
> 3)
1799 return ALC_INVALID_VALUE
;
1803 /* If a context is already running on the device, stop playback so the
1804 * device attributes can be updated.
1806 if(device
->Flags
.get
<DeviceRunning
>())
1807 device
->Backend
->stop();
1808 device
->Flags
.unset
<DeviceRunning
>();
1810 UpdateClockBase(device
);
1812 const char *devname
{nullptr};
1815 devname
= device
->DeviceName
.c_str();
1817 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
1818 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
1819 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
1821 freq
= ConfigValueUInt(devname
, nullptr, "frequency").value_or(freq
);
1823 device
->Flags
.unset
<FrequencyRequest
>();
1826 freq
= clampu(freq
, MIN_OUTPUT_RATE
, MAX_OUTPUT_RATE
);
1828 const double scale
{static_cast<double>(freq
) / device
->Frequency
};
1829 device
->UpdateSize
= static_cast<ALuint
>(device
->UpdateSize
*scale
+ 0.5);
1830 device
->BufferSize
= static_cast<ALuint
>(device
->BufferSize
*scale
+ 0.5);
1832 device
->Frequency
= freq
;
1833 device
->Flags
.set
<FrequencyRequest
>();
1836 if(auto persizeopt
= ConfigValueUInt(devname
, nullptr, "period_size"))
1837 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
1839 if(auto peropt
= ConfigValueUInt(devname
, nullptr, "periods"))
1840 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
1842 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
1846 device
->Frequency
= freq
;
1847 device
->FmtChans
= static_cast<DevFmtChannels
>(schans
);
1848 device
->FmtType
= static_cast<DevFmtType
>(stype
);
1849 if(schans
== ALC_BFORMAT3D_SOFT
)
1851 device
->mAmbiOrder
= aorder
;
1852 device
->mAmbiLayout
= static_cast<DevAmbiLayout
>(alayout
);
1853 device
->mAmbiScale
= static_cast<DevAmbiScaling
>(ascale
);
1857 if(numMono
> INT_MAX
-numStereo
)
1858 numMono
= INT_MAX
-numStereo
;
1859 numMono
+= numStereo
;
1860 if(auto srcsopt
= ConfigValueUInt(devname
, nullptr, "sources"))
1862 if(*srcsopt
<= 0) numMono
= 256;
1863 else numMono
= *srcsopt
;
1866 numMono
= maxu(numMono
, 256);
1867 numStereo
= minu(numStereo
, numMono
);
1868 numMono
-= numStereo
;
1869 device
->SourcesMax
= numMono
+ numStereo
;
1871 device
->NumMonoSources
= numMono
;
1872 device
->NumStereoSources
= numStereo
;
1874 if(auto sendsopt
= ConfigValueInt(devname
, nullptr, "sends"))
1875 new_sends
= minu(numSends
, static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
1877 new_sends
= numSends
;
1880 if(device
->Flags
.get
<DeviceRunning
>())
1881 return ALC_NO_ERROR
;
1883 device
->AvgSpeakerDist
= 0.0f
;
1884 device
->Uhj_Encoder
= nullptr;
1885 device
->AmbiDecoder
= nullptr;
1886 device
->Bs2b
= nullptr;
1887 device
->PostProcess
= nullptr;
1889 device
->Limiter
= nullptr;
1890 device
->ChannelDelay
.clear();
1892 std::fill(std::begin(device
->HrtfAccumData
), std::end(device
->HrtfAccumData
), float2
{});
1894 device
->Dry
.AmbiMap
.fill(BFChannelConfig
{});
1895 device
->Dry
.Buffer
= {};
1896 std::fill(std::begin(device
->NumChannelsPerOrder
), std::end(device
->NumChannelsPerOrder
), 0u);
1897 device
->RealOut
.RemixMap
= {};
1898 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1899 device
->RealOut
.Buffer
= {};
1900 device
->MixBuffer
.clear();
1901 device
->MixBuffer
.shrink_to_fit();
1903 UpdateClockBase(device
);
1904 device
->FixedLatency
= nanoseconds::zero();
1906 device
->DitherDepth
= 0.0f
;
1907 device
->DitherSeed
= DitherRNGSeed
;
1909 /*************************************************************************
1910 * Update device format request if HRTF is requested
1912 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1913 if(device
->Type
!= DeviceType::Loopback
)
1915 if(auto hrtfopt
= ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf"))
1917 const char *hrtf
{hrtfopt
->c_str()};
1918 if(al::strcasecmp(hrtf
, "true") == 0)
1919 hrtf_userreq
= Hrtf_Enable
;
1920 else if(al::strcasecmp(hrtf
, "false") == 0)
1921 hrtf_userreq
= Hrtf_Disable
;
1922 else if(al::strcasecmp(hrtf
, "auto") != 0)
1923 ERR("Unexpected hrtf value: %s\n", hrtf
);
1926 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1928 device
->FmtChans
= DevFmtStereo
;
1929 device
->Flags
.set
<ChannelsRequest
>();
1933 oldFreq
= device
->Frequency
;
1934 oldChans
= device
->FmtChans
;
1935 oldType
= device
->FmtType
;
1937 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1938 device
->Flags
.get
<ChannelsRequest
>()?"*":"", DevFmtChannelsString(device
->FmtChans
),
1939 device
->Flags
.get
<SampleTypeRequest
>()?"*":"", DevFmtTypeString(device
->FmtType
),
1940 device
->Flags
.get
<FrequencyRequest
>()?"*":"", device
->Frequency
,
1941 device
->UpdateSize
, device
->BufferSize
);
1944 auto backend
= device
->Backend
.get();
1945 if(!backend
->reset())
1946 throw al::backend_exception
{ALC_INVALID_DEVICE
, "Device reset failure"};
1948 catch(std::exception
&e
) {
1949 device
->handleDisconnect("%s", e
.what());
1950 return ALC_INVALID_DEVICE
;
1953 if(device
->FmtChans
!= oldChans
&& device
->Flags
.get
<ChannelsRequest
>())
1955 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1956 DevFmtChannelsString(device
->FmtChans
));
1957 device
->Flags
.unset
<ChannelsRequest
>();
1959 if(device
->FmtType
!= oldType
&& device
->Flags
.get
<SampleTypeRequest
>())
1961 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1962 DevFmtTypeString(device
->FmtType
));
1963 device
->Flags
.unset
<SampleTypeRequest
>();
1965 if(device
->Frequency
!= oldFreq
&& device
->Flags
.get
<FrequencyRequest
>())
1967 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1968 device
->Flags
.unset
<FrequencyRequest
>();
1971 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1972 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
1973 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
1975 switch(device
->FmtChans
)
1977 case DevFmtMono
: device
->RealOut
.RemixMap
= MonoDownmix
; break;
1978 case DevFmtStereo
: device
->RealOut
.RemixMap
= StereoDownmix
; break;
1979 case DevFmtQuad
: device
->RealOut
.RemixMap
= QuadDownmix
; break;
1980 case DevFmtX51
: device
->RealOut
.RemixMap
= X51Downmix
; break;
1981 case DevFmtX51Rear
: device
->RealOut
.RemixMap
= X51RearDownmix
; break;
1982 case DevFmtX61
: device
->RealOut
.RemixMap
= X61Downmix
; break;
1983 case DevFmtX71
: device
->RealOut
.RemixMap
= X71Downmix
; break;
1984 case DevFmtAmbi3D
: break;
1987 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
1989 device
->NumAuxSends
= new_sends
;
1990 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1991 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
1992 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
1994 nanoseconds::rep sample_delay
{0};
1995 if(device
->Uhj_Encoder
)
1996 sample_delay
+= Uhj2Encoder::sFilterSize
;
1997 if(device
->mHrtfState
)
1998 sample_delay
+= HRTF_DIRECT_DELAY
;
1999 if(auto *ambidec
= device
->AmbiDecoder
.get())
2001 if(ambidec
->hasStablizer())
2002 sample_delay
+= FrontStablizer::DelayLength
;
2005 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2007 int depth
{ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth").value_or(0)};
2010 switch(device
->FmtType
)
2029 depth
= clampi(depth
, 2, 24);
2030 device
->DitherDepth
= std::pow(2.0f
, static_cast<float>(depth
-1));
2033 if(!(device
->DitherDepth
> 0.0f
))
2034 TRACE("Dithering disabled\n");
2036 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2037 device
->DitherDepth
);
2039 device
->LimiterState
= gainLimiter
;
2040 if(auto limopt
= ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter"))
2041 gainLimiter
= *limopt
? ALC_TRUE
: ALC_FALSE
;
2043 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2044 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2045 * output (where samples must be clamped), and don't for floating-point
2046 * (which can take unclamped samples).
2048 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2050 switch(device
->FmtType
)
2058 gainLimiter
= ALC_TRUE
;
2061 gainLimiter
= ALC_FALSE
;
2065 if(gainLimiter
== ALC_FALSE
)
2066 TRACE("Output limiter disabled\n");
2069 float thrshld
{1.0f
};
2070 switch(device
->FmtType
)
2074 thrshld
= 127.0f
/ 128.0f
;
2078 thrshld
= 32767.0f
/ 32768.0f
;
2085 if(device
->DitherDepth
> 0.0f
)
2086 thrshld
-= 1.0f
/ device
->DitherDepth
;
2088 const float thrshld_dB
{std::log10(thrshld
) * 20.0f
};
2089 auto limiter
= CreateDeviceLimiter(device
, thrshld_dB
);
2091 sample_delay
+= limiter
->getLookAhead();
2092 device
->Limiter
= std::move(limiter
);
2093 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB
);
2096 /* Convert the sample delay from samples to nanosamples to nanoseconds. */
2097 device
->FixedLatency
+= nanoseconds
{seconds
{sample_delay
}} / device
->Frequency
;
2098 TRACE("Fixed device latency: %" PRId64
"ns\n", int64_t{device
->FixedLatency
.count()});
2100 FPUCtl mixer_mode
{};
2101 for(ALCcontext
*context
: *device
->mContexts
.load())
2103 std::unique_lock
<std::mutex
> proplock
{context
->mPropLock
};
2104 std::unique_lock
<std::mutex
> slotlock
{context
->mEffectSlotLock
};
2106 /* Clear out unused wet buffers. */
2107 auto buffer_not_in_use
= [](WetBufferPtr
&wetbuffer
) noexcept
-> bool
2108 { return !wetbuffer
->mInUse
; };
2109 auto wetbuffer_iter
= std::remove_if(context
->mWetBuffers
.begin(),
2110 context
->mWetBuffers
.end(), buffer_not_in_use
);
2111 context
->mWetBuffers
.erase(wetbuffer_iter
, context
->mWetBuffers
.end());
2113 if(ALeffectslot
*slot
{context
->mDefaultSlot
.get()})
2115 aluInitEffectPanning(slot
, context
);
2117 EffectState
*state
{slot
->Effect
.State
.get()};
2118 state
->mOutTarget
= device
->Dry
.Buffer
;
2119 state
->deviceUpdate(device
);
2120 if(ALbuffer
*buffer
{slot
->Buffer
})
2121 state
->setBuffer(device
, &buffer
->mBuffer
);
2122 slot
->updateProps(context
);
2125 if(ALeffectslotArray
*curarray
{context
->mActiveAuxSlots
.load(std::memory_order_relaxed
)})
2126 std::fill_n(curarray
->end(), curarray
->size(), nullptr);
2127 for(auto &sublist
: context
->mEffectSlotList
)
2129 uint64_t usemask
{~sublist
.FreeMask
};
2132 const ALsizei idx
{CountTrailingZeros(usemask
)};
2133 ALeffectslot
*slot
{sublist
.EffectSlots
+ idx
};
2134 usemask
&= ~(1_u64
<< idx
);
2136 aluInitEffectPanning(slot
, context
);
2138 EffectState
*state
{slot
->Effect
.State
.get()};
2139 state
->mOutTarget
= device
->Dry
.Buffer
;
2140 state
->deviceUpdate(device
);
2141 if(ALbuffer
*buffer
{slot
->Buffer
})
2142 state
->setBuffer(device
, &buffer
->mBuffer
);
2143 slot
->updateProps(context
);
2148 const ALuint num_sends
{device
->NumAuxSends
};
2149 std::unique_lock
<std::mutex
> srclock
{context
->mSourceLock
};
2150 for(auto &sublist
: context
->mSourceList
)
2152 uint64_t usemask
{~sublist
.FreeMask
};
2155 const ALsizei idx
{CountTrailingZeros(usemask
)};
2156 ALsource
*source
{sublist
.Sources
+ idx
};
2157 usemask
&= ~(1_u64
<< idx
);
2159 auto clear_send
= [](ALsource::SendData
&send
) -> void
2162 DecrementRef(send
.Slot
->ref
);
2163 send
.Slot
= nullptr;
2166 send
.HFReference
= LOWPASSFREQREF
;
2168 send
.LFReference
= HIGHPASSFREQREF
;
2170 auto send_begin
= source
->Send
.begin() + static_cast<ptrdiff_t>(num_sends
);
2171 std::for_each(send_begin
, source
->Send
.end(), clear_send
);
2173 source
->PropsClean
.clear(std::memory_order_release
);
2177 /* Clear any pre-existing voice property structs, in case the number of
2178 * auxiliary sends is changing. Active sources will have updates
2179 * respecified in UpdateAllSourceProps.
2181 VoicePropsItem
*vprops
{context
->mFreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2184 VoicePropsItem
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2189 auto voicelist
= context
->getVoicesSpan();
2190 for(Voice
*voice
: voicelist
)
2192 /* Clear extraneous property set sends. */
2193 std::fill(std::begin(voice
->mProps
.Send
)+num_sends
, std::end(voice
->mProps
.Send
),
2194 VoiceProps::SendData
{});
2196 std::fill(voice
->mSend
.begin()+num_sends
, voice
->mSend
.end(), Voice::TargetData
{});
2197 for(auto &chandata
: voice
->mChans
)
2199 std::fill(chandata
.mWetParams
.begin()+num_sends
, chandata
.mWetParams
.end(),
2203 delete voice
->mUpdate
.exchange(nullptr, std::memory_order_acq_rel
);
2205 /* Force the voice to stopped if it was stopping. */
2206 Voice::State vstate
{Voice::Stopping
};
2207 voice
->mPlayState
.compare_exchange_strong(vstate
, Voice::Stopped
,
2208 std::memory_order_acquire
, std::memory_order_acquire
);
2209 if(voice
->mSourceID
.load(std::memory_order_relaxed
) == 0u)
2213 voice
->mFlags
|= VoiceIsFading
;
2215 if(voice
->mAmbiOrder
&& device
->mAmbiOrder
> voice
->mAmbiOrder
)
2217 const uint8_t *OrderFromChan
{(voice
->mFmtChannels
== FmtBFormat2D
) ?
2218 AmbiIndex::OrderFrom2DChannel
.data() :
2219 AmbiIndex::OrderFromChannel
.data()};
2221 const BandSplitter splitter
{400.0f
/ static_cast<float>(device
->Frequency
)};
2223 const auto scales
= BFormatDec::GetHFOrderScales(voice
->mAmbiOrder
,
2224 device
->mAmbiOrder
);
2225 for(auto &chandata
: voice
->mChans
)
2227 chandata
.mPrevSamples
.fill(0.0f
);
2228 chandata
.mAmbiScale
= scales
[*(OrderFromChan
++)];
2229 chandata
.mAmbiSplitter
= splitter
;
2230 chandata
.mDryParams
= DirectParams
{};
2231 std::fill_n(chandata
.mWetParams
.begin(), num_sends
, SendParams
{});
2234 voice
->mFlags
|= VoiceIsAmbisonic
;
2238 /* Clear previous samples. */
2239 for(auto &chandata
: voice
->mChans
)
2241 chandata
.mPrevSamples
.fill(0.0f
);
2242 chandata
.mDryParams
= DirectParams
{};
2243 std::fill_n(chandata
.mWetParams
.begin(), num_sends
, SendParams
{});
2246 voice
->mFlags
&= ~VoiceIsAmbisonic
;
2249 if(device
->AvgSpeakerDist
> 0.0f
)
2251 /* Reinitialize the NFC filters for new parameters. */
2252 const float w1
{SpeedOfSoundMetersPerSec
/
2253 (device
->AvgSpeakerDist
* static_cast<float>(device
->Frequency
))};
2254 for(auto &chandata
: voice
->mChans
)
2255 chandata
.mDryParams
.NFCtrlFilter
.init(w1
);
2260 context
->mPropsClean
.test_and_set(std::memory_order_release
);
2261 UpdateContextProps(context
);
2262 context
->mListener
.PropsClean
.test_and_set(std::memory_order_release
);
2263 UpdateListenerProps(context
);
2264 UpdateAllSourceProps(context
);
2268 if(!device
->Flags
.get
<DevicePaused
>())
2271 auto backend
= device
->Backend
.get();
2273 device
->Flags
.set
<DeviceRunning
>();
2275 catch(al::backend_exception
& e
) {
2276 device
->handleDisconnect("%s", e
.what());
2277 return ALC_INVALID_DEVICE
;
2281 return ALC_NO_ERROR
;
2285 ALCdevice::ALCdevice(DeviceType type
) : Type
{type
}, mContexts
{&EmptyContextArray
}
2289 ALCdevice::~ALCdevice()
2291 TRACE("Freeing device %p\n", decltype(std::declval
<void*>()){this});
2295 size_t count
{std::accumulate(BufferList
.cbegin(), BufferList
.cend(), size_t{0u},
2296 [](size_t cur
, const BufferSubList
&sublist
) noexcept
-> size_t
2297 { return cur
+ static_cast<ALuint
>(PopCount(~sublist
.FreeMask
)); })};
2299 WARN("%zu Buffer%s not deleted\n", count
, (count
==1)?"":"s");
2301 count
= std::accumulate(EffectList
.cbegin(), EffectList
.cend(), size_t{0u},
2302 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
2303 { return cur
+ static_cast<ALuint
>(PopCount(~sublist
.FreeMask
)); });
2305 WARN("%zu Effect%s not deleted\n", count
, (count
==1)?"":"s");
2307 count
= std::accumulate(FilterList
.cbegin(), FilterList
.cend(), size_t{0u},
2308 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
2309 { return cur
+ static_cast<ALuint
>(PopCount(~sublist
.FreeMask
)); });
2311 WARN("%zu Filter%s not deleted\n", count
, (count
==1)?"":"s");
2315 auto *oldarray
= mContexts
.exchange(nullptr, std::memory_order_relaxed
);
2316 if(oldarray
!= &EmptyContextArray
) delete oldarray
;
2320 /** Checks if the device handle is valid, and returns a new reference if so. */
2321 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2323 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2324 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
2325 if(iter
!= DeviceList
.end() && *iter
== device
)
2328 return DeviceRef
{*iter
};
2334 ALCcontext::ALCcontext(al::intrusive_ptr
<ALCdevice
> device
) : mDevice
{std::move(device
)}
2336 mPropsClean
.test_and_set(std::memory_order_relaxed
);
2339 ALCcontext::~ALCcontext()
2341 TRACE("Freeing context %p\n", decltype(std::declval
<void*>()){this});
2344 ALcontextProps
*cprops
{mUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
2350 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
2353 ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2358 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
2360 count
= std::accumulate(mSourceList
.cbegin(), mSourceList
.cend(), size_t{0u},
2361 [](size_t cur
, const SourceSubList
&sublist
) noexcept
-> size_t
2362 { return cur
+ static_cast<ALuint
>(PopCount(~sublist
.FreeMask
)); });
2364 WARN("%zu Source%s not deleted\n", count
, (count
==1)?"":"s");
2365 mSourceList
.clear();
2369 ALeffectslotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
2372 ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2377 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2379 if(ALeffectslotArray
*curarray
{mActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
)})
2381 al::destroy_n(curarray
->end(), curarray
->size());
2384 mDefaultSlot
= nullptr;
2386 count
= std::accumulate(mEffectSlotList
.cbegin(), mEffectSlotList
.cend(), size_t{0u},
2387 [](size_t cur
, const EffectSlotSubList
&sublist
) noexcept
-> size_t
2388 { return cur
+ static_cast<ALuint
>(PopCount(~sublist
.FreeMask
)); });
2390 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count
, (count
==1)?"":"s");
2391 mEffectSlotList
.clear();
2392 mNumEffectSlots
= 0;
2395 VoicePropsItem
*vprops
{mFreeVoiceProps
.exchange(nullptr, std::memory_order_acquire
)};
2398 VoicePropsItem
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2403 TRACE("Freed %zu voice property object%s\n", count
, (count
==1)?"":"s");
2405 delete mVoices
.exchange(nullptr, std::memory_order_relaxed
);
2408 ALlistenerProps
*lprops
{mListener
.Params
.Update
.exchange(nullptr, std::memory_order_relaxed
)};
2414 lprops
= mFreeListenerProps
.exchange(nullptr, std::memory_order_acquire
);
2417 ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2422 TRACE("Freed %zu listener property object%s\n", count
, (count
==1)?"":"s");
2427 auto evt_vec
= mAsyncEvents
->getReadVector();
2428 if(evt_vec
.first
.len
> 0)
2430 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.first
.buf
), evt_vec
.first
.len
);
2431 count
+= evt_vec
.first
.len
;
2433 if(evt_vec
.second
.len
> 0)
2435 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.second
.buf
), evt_vec
.second
.len
);
2436 count
+= evt_vec
.second
.len
;
2439 TRACE("Destructed %zu orphaned event%s\n", count
, (count
==1)?"":"s");
2440 mAsyncEvents
->readAdvance(count
);
2444 void ALCcontext::init()
2446 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& mDevice
->Type
== DeviceType::Playback
)
2448 mDefaultSlot
= std::unique_ptr
<ALeffectslot
>{new ALeffectslot
{}};
2449 if(mDefaultSlot
->init() == AL_NO_ERROR
)
2450 aluInitEffectPanning(mDefaultSlot
.get(), this);
2453 mDefaultSlot
= nullptr;
2454 ERR("Failed to initialize the default effect slot\n");
2458 ALeffectslotArray
*auxslots
;
2460 auxslots
= ALeffectslot::CreatePtrArray(0);
2463 auxslots
= ALeffectslot::CreatePtrArray(1);
2464 (*auxslots
)[0] = mDefaultSlot
.get();
2465 mDefaultSlot
->mState
= SlotState::Playing
;
2467 mActiveAuxSlots
.store(auxslots
, std::memory_order_relaxed
);
2469 allocVoiceChanges(1);
2471 VoiceChange
*cur
{mVoiceChangeTail
};
2472 while(VoiceChange
*next
{cur
->mNext
.load(std::memory_order_relaxed
)})
2474 mCurrentVoiceChange
.store(cur
, std::memory_order_relaxed
);
2477 mExtensionList
= alExtList
;
2480 mListener
.Params
.Matrix
= alu::Matrix::Identity();
2481 mListener
.Params
.Velocity
= alu::Vector
{};
2482 mListener
.Params
.Gain
= mListener
.Gain
;
2483 mListener
.Params
.MetersPerUnit
= mListener
.mMetersPerUnit
;
2484 mListener
.Params
.DopplerFactor
= mDopplerFactor
;
2485 mListener
.Params
.SpeedOfSound
= mSpeedOfSound
* mDopplerVelocity
;
2486 mListener
.Params
.SourceDistanceModel
= mSourceDistanceModel
;
2487 mListener
.Params
.mDistanceModel
= mDistanceModel
;
2490 mAsyncEvents
= RingBuffer::Create(511, sizeof(AsyncEvent
), false);
2491 StartEventThrd(this);
2495 mActiveVoiceCount
.store(64, std::memory_order_relaxed
);
2498 bool ALCcontext::deinit()
2500 if(LocalContext
== this)
2502 WARN("%p released while current on thread\n", decltype(std::declval
<void*>()){this});
2503 ThreadContext
.set(nullptr);
2507 ALCcontext
*origctx
{this};
2508 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2512 /* First make sure this context exists in the device's list. */
2513 auto *oldarray
= mDevice
->mContexts
.load(std::memory_order_acquire
);
2514 if(auto toremove
= static_cast<size_t>(std::count(oldarray
->begin(), oldarray
->end(), this)))
2516 using ContextArray
= al::FlexArray
<ALCcontext
*>;
2517 auto alloc_ctx_array
= [](const size_t count
) -> ContextArray
*
2519 if(count
== 0) return &EmptyContextArray
;
2520 return ContextArray::Create(count
).release();
2522 auto *newarray
= alloc_ctx_array(oldarray
->size() - toremove
);
2524 /* Copy the current/old context handles to the new array, excluding the
2527 std::copy_if(oldarray
->begin(), oldarray
->end(), newarray
->begin(),
2528 std::bind(std::not_equal_to
<ALCcontext
*>{}, _1
, this));
2530 /* Store the new context array in the device. Wait for any current mix
2531 * to finish before deleting the old array.
2533 mDevice
->mContexts
.store(newarray
);
2534 if(oldarray
!= &EmptyContextArray
)
2536 mDevice
->waitForMix();
2540 ret
= !newarray
->empty();
2543 ret
= !oldarray
->empty();
2545 StopEventThrd(this);
2552 * Checks if the given context is valid, returning a new reference to it if so.
2554 static ContextRef
VerifyContext(ALCcontext
*context
)
2556 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2557 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
2558 if(iter
!= ContextList
.end() && *iter
== context
)
2561 return ContextRef
{*iter
};
2566 /** Returns a new reference to the currently active context for this thread. */
2567 ContextRef
GetContextRef(void)
2569 ALCcontext
*context
{LocalContext
};
2574 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2575 context
= GlobalContext
.load(std::memory_order_acquire
);
2576 if(context
) context
->add_ref();
2578 return ContextRef
{context
};
2582 /************************************************
2583 * Standard ALC functions
2584 ************************************************/
2586 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2589 DeviceRef dev
{VerifyDevice(device
)};
2590 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2591 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2596 ALC_API
void ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2602 ContextRef ctx
{VerifyContext(context
)};
2604 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2606 ctx
->deferUpdates();
2610 ALC_API
void ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2616 ContextRef ctx
{VerifyContext(context
)};
2618 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2620 ctx
->processUpdates();
2625 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2628 const ALCchar
*value
{nullptr};
2636 case ALC_INVALID_ENUM
:
2637 value
= alcErrInvalidEnum
;
2640 case ALC_INVALID_VALUE
:
2641 value
= alcErrInvalidValue
;
2644 case ALC_INVALID_DEVICE
:
2645 value
= alcErrInvalidDevice
;
2648 case ALC_INVALID_CONTEXT
:
2649 value
= alcErrInvalidContext
;
2652 case ALC_OUT_OF_MEMORY
:
2653 value
= alcErrOutOfMemory
;
2656 case ALC_DEVICE_SPECIFIER
:
2657 value
= alcDefaultName
;
2660 case ALC_ALL_DEVICES_SPECIFIER
:
2661 if(DeviceRef dev
{VerifyDevice(Device
)})
2662 value
= dev
->DeviceName
.c_str();
2665 ProbeAllDevicesList();
2666 value
= alcAllDevicesList
.c_str();
2670 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2671 if(DeviceRef dev
{VerifyDevice(Device
)})
2672 value
= dev
->DeviceName
.c_str();
2675 ProbeCaptureDeviceList();
2676 value
= alcCaptureDeviceList
.c_str();
2680 /* Default devices are always first in the list */
2681 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2682 value
= alcDefaultName
;
2685 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2686 if(alcAllDevicesList
.empty())
2687 ProbeAllDevicesList();
2689 /* Copy first entry as default. */
2690 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2691 value
= alcDefaultAllDevicesSpecifier
.c_str();
2694 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2695 if(alcCaptureDeviceList
.empty())
2696 ProbeCaptureDeviceList();
2698 /* Copy first entry as default. */
2699 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2700 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2703 case ALC_EXTENSIONS
:
2704 if(VerifyDevice(Device
))
2705 value
= alcExtensionList
;
2707 value
= alcNoDeviceExtList
;
2710 case ALC_HRTF_SPECIFIER_SOFT
:
2711 if(DeviceRef dev
{VerifyDevice(Device
)})
2713 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
2714 value
= (dev
->mHrtf
? dev
->HrtfName
.c_str() : "");
2717 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2721 alcSetError(VerifyDevice(Device
).get(), ALC_INVALID_ENUM
);
2730 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2732 if(device
->Type
== DeviceType::Capture
) return 9;
2733 if(device
->Type
!= DeviceType::Loopback
) return 29;
2734 if(device
->FmtChans
== DevFmtAmbi3D
)
2739 static size_t GetIntegerv(ALCdevice
*device
, ALCenum param
, const al::span
<int> values
)
2745 alcSetError(device
, ALC_INVALID_VALUE
);
2753 case ALC_MAJOR_VERSION
:
2754 values
[0] = alcMajorVersion
;
2756 case ALC_MINOR_VERSION
:
2757 values
[0] = alcMinorVersion
;
2760 case ALC_ATTRIBUTES_SIZE
:
2761 case ALC_ALL_ATTRIBUTES
:
2765 case ALC_MONO_SOURCES
:
2766 case ALC_STEREO_SOURCES
:
2767 case ALC_CAPTURE_SAMPLES
:
2768 case ALC_FORMAT_CHANNELS_SOFT
:
2769 case ALC_FORMAT_TYPE_SOFT
:
2770 case ALC_AMBISONIC_LAYOUT_SOFT
:
2771 case ALC_AMBISONIC_SCALING_SOFT
:
2772 case ALC_AMBISONIC_ORDER_SOFT
:
2773 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
2774 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2778 alcSetError(nullptr, ALC_INVALID_ENUM
);
2783 if(device
->Type
== DeviceType::Capture
)
2787 case ALC_ATTRIBUTES_SIZE
:
2788 values
[0] = NumAttrsForDevice(device
);
2791 case ALC_ALL_ATTRIBUTES
:
2793 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2794 alcSetError(device
, ALC_INVALID_VALUE
);
2797 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2798 values
[i
++] = ALC_MAJOR_VERSION
;
2799 values
[i
++] = alcMajorVersion
;
2800 values
[i
++] = ALC_MINOR_VERSION
;
2801 values
[i
++] = alcMinorVersion
;
2802 values
[i
++] = ALC_CAPTURE_SAMPLES
;
2803 values
[i
++] = static_cast<int>(device
->Backend
->availableSamples());
2804 values
[i
++] = ALC_CONNECTED
;
2805 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
2810 case ALC_MAJOR_VERSION
:
2811 values
[0] = alcMajorVersion
;
2813 case ALC_MINOR_VERSION
:
2814 values
[0] = alcMinorVersion
;
2817 case ALC_CAPTURE_SAMPLES
:
2819 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2820 values
[0] = static_cast<int>(device
->Backend
->availableSamples());
2826 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2827 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2832 alcSetError(device
, ALC_INVALID_ENUM
);
2840 case ALC_ATTRIBUTES_SIZE
:
2841 values
[0] = NumAttrsForDevice(device
);
2844 case ALC_ALL_ATTRIBUTES
:
2846 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2847 alcSetError(device
, ALC_INVALID_VALUE
);
2850 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2851 values
[i
++] = ALC_MAJOR_VERSION
;
2852 values
[i
++] = alcMajorVersion
;
2853 values
[i
++] = ALC_MINOR_VERSION
;
2854 values
[i
++] = alcMinorVersion
;
2855 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
2856 values
[i
++] = alcEFXMajorVersion
;
2857 values
[i
++] = ALC_EFX_MINOR_VERSION
;
2858 values
[i
++] = alcEFXMinorVersion
;
2860 values
[i
++] = ALC_FREQUENCY
;
2861 values
[i
++] = static_cast<int>(device
->Frequency
);
2862 if(device
->Type
!= DeviceType::Loopback
)
2864 values
[i
++] = ALC_REFRESH
;
2865 values
[i
++] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2867 values
[i
++] = ALC_SYNC
;
2868 values
[i
++] = ALC_FALSE
;
2872 if(device
->FmtChans
== DevFmtAmbi3D
)
2874 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
2875 values
[i
++] = static_cast<int>(device
->mAmbiLayout
);
2877 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
2878 values
[i
++] = static_cast<int>(device
->mAmbiScale
);
2880 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
2881 values
[i
++] = static_cast<int>(device
->mAmbiOrder
);
2884 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2885 values
[i
++] = device
->FmtChans
;
2887 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2888 values
[i
++] = device
->FmtType
;
2891 values
[i
++] = ALC_MONO_SOURCES
;
2892 values
[i
++] = static_cast<int>(device
->NumMonoSources
);
2894 values
[i
++] = ALC_STEREO_SOURCES
;
2895 values
[i
++] = static_cast<int>(device
->NumStereoSources
);
2897 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2898 values
[i
++] = static_cast<int>(device
->NumAuxSends
);
2900 values
[i
++] = ALC_HRTF_SOFT
;
2901 values
[i
++] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
2903 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
2904 values
[i
++] = device
->HrtfStatus
;
2906 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
2907 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
2909 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
2910 values
[i
++] = MAX_AMBI_ORDER
;
2916 case ALC_MAJOR_VERSION
:
2917 values
[0] = alcMajorVersion
;
2920 case ALC_MINOR_VERSION
:
2921 values
[0] = alcMinorVersion
;
2924 case ALC_EFX_MAJOR_VERSION
:
2925 values
[0] = alcEFXMajorVersion
;
2928 case ALC_EFX_MINOR_VERSION
:
2929 values
[0] = alcEFXMinorVersion
;
2933 values
[0] = static_cast<int>(device
->Frequency
);
2937 if(device
->Type
== DeviceType::Loopback
)
2939 alcSetError(device
, ALC_INVALID_DEVICE
);
2943 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2944 values
[0] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2949 if(device
->Type
== DeviceType::Loopback
)
2951 alcSetError(device
, ALC_INVALID_DEVICE
);
2954 values
[0] = ALC_FALSE
;
2957 case ALC_FORMAT_CHANNELS_SOFT
:
2958 if(device
->Type
!= DeviceType::Loopback
)
2960 alcSetError(device
, ALC_INVALID_DEVICE
);
2963 values
[0] = device
->FmtChans
;
2966 case ALC_FORMAT_TYPE_SOFT
:
2967 if(device
->Type
!= DeviceType::Loopback
)
2969 alcSetError(device
, ALC_INVALID_DEVICE
);
2972 values
[0] = device
->FmtType
;
2975 case ALC_AMBISONIC_LAYOUT_SOFT
:
2976 if(device
->Type
!= DeviceType::Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2978 alcSetError(device
, ALC_INVALID_DEVICE
);
2981 values
[0] = static_cast<int>(device
->mAmbiLayout
);
2984 case ALC_AMBISONIC_SCALING_SOFT
:
2985 if(device
->Type
!= DeviceType::Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2987 alcSetError(device
, ALC_INVALID_DEVICE
);
2990 values
[0] = static_cast<int>(device
->mAmbiScale
);
2993 case ALC_AMBISONIC_ORDER_SOFT
:
2994 if(device
->Type
!= DeviceType::Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2996 alcSetError(device
, ALC_INVALID_DEVICE
);
2999 values
[0] = static_cast<int>(device
->mAmbiOrder
);
3002 case ALC_MONO_SOURCES
:
3003 values
[0] = static_cast<int>(device
->NumMonoSources
);
3006 case ALC_STEREO_SOURCES
:
3007 values
[0] = static_cast<int>(device
->NumStereoSources
);
3010 case ALC_MAX_AUXILIARY_SENDS
:
3011 values
[0] = static_cast<int>(device
->NumAuxSends
);
3016 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3017 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3022 values
[0] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3025 case ALC_HRTF_STATUS_SOFT
:
3026 values
[0] = device
->HrtfStatus
;
3029 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3031 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3032 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3033 values
[0] = static_cast<int>(minz(device
->HrtfList
.size(),
3034 std::numeric_limits
<int>::max()));
3038 case ALC_OUTPUT_LIMITER_SOFT
:
3039 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3042 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3043 values
[0] = MAX_AMBI_ORDER
;
3047 alcSetError(device
, ALC_INVALID_ENUM
);
3052 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3055 DeviceRef dev
{VerifyDevice(device
)};
3056 if(size
<= 0 || values
== nullptr)
3057 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3059 GetIntegerv(dev
.get(), param
, {values
, static_cast<ALuint
>(size
)});
3063 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3066 DeviceRef dev
{VerifyDevice(device
)};
3067 if(size
<= 0 || values
== nullptr)
3069 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3072 if(!dev
|| dev
->Type
== DeviceType::Capture
)
3074 auto ivals
= al::vector
<int>(static_cast<ALuint
>(size
));
3075 size_t got
{GetIntegerv(dev
.get(), pname
, ivals
)};
3076 std::copy_n(ivals
.begin(), got
, values
);
3082 case ALC_ATTRIBUTES_SIZE
:
3083 *values
= NumAttrsForDevice(dev
.get())+4;
3086 case ALC_ALL_ATTRIBUTES
:
3087 if(size
< NumAttrsForDevice(dev
.get())+4)
3088 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3092 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3093 values
[i
++] = ALC_FREQUENCY
;
3094 values
[i
++] = dev
->Frequency
;
3096 if(dev
->Type
!= DeviceType::Loopback
)
3098 values
[i
++] = ALC_REFRESH
;
3099 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3101 values
[i
++] = ALC_SYNC
;
3102 values
[i
++] = ALC_FALSE
;
3106 if(dev
->FmtChans
== DevFmtAmbi3D
)
3108 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3109 values
[i
++] = static_cast<int64_t>(dev
->mAmbiLayout
);
3111 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3112 values
[i
++] = static_cast<int64_t>(dev
->mAmbiScale
);
3114 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3115 values
[i
++] = dev
->mAmbiOrder
;
3118 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3119 values
[i
++] = dev
->FmtChans
;
3121 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3122 values
[i
++] = dev
->FmtType
;
3125 values
[i
++] = ALC_MONO_SOURCES
;
3126 values
[i
++] = dev
->NumMonoSources
;
3128 values
[i
++] = ALC_STEREO_SOURCES
;
3129 values
[i
++] = dev
->NumStereoSources
;
3131 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3132 values
[i
++] = dev
->NumAuxSends
;
3134 values
[i
++] = ALC_HRTF_SOFT
;
3135 values
[i
++] = (dev
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3137 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3138 values
[i
++] = dev
->HrtfStatus
;
3140 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3141 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3143 ClockLatency clock
{GetClockLatency(dev
.get())};
3144 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3145 values
[i
++] = clock
.ClockTime
.count();
3147 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3148 values
[i
++] = clock
.Latency
.count();
3154 case ALC_DEVICE_CLOCK_SOFT
:
3156 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3157 ALuint samplecount
, refcount
;
3158 nanoseconds basecount
;
3160 refcount
= dev
->waitForMix();
3161 basecount
= dev
->ClockBase
;
3162 samplecount
= dev
->SamplesDone
;
3163 } while(refcount
!= ReadRef(dev
->MixCount
));
3164 basecount
+= nanoseconds
{seconds
{samplecount
}} / dev
->Frequency
;
3165 *values
= basecount
.count();
3169 case ALC_DEVICE_LATENCY_SOFT
:
3171 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3172 ClockLatency clock
{GetClockLatency(dev
.get())};
3173 *values
= clock
.Latency
.count();
3177 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3179 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3182 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3183 ClockLatency clock
{GetClockLatency(dev
.get())};
3184 values
[0] = clock
.ClockTime
.count();
3185 values
[1] = clock
.Latency
.count();
3190 auto ivals
= al::vector
<int>(static_cast<ALuint
>(size
));
3191 size_t got
{GetIntegerv(dev
.get(), pname
, ivals
)};
3192 std::copy_n(ivals
.begin(), got
, values
);
3199 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3202 DeviceRef dev
{VerifyDevice(device
)};
3204 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3207 size_t len
= strlen(extName
);
3208 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3211 if(al::strncasecmp(ptr
, extName
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3214 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3218 } while(isspace(*ptr
));
3227 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3232 DeviceRef dev
{VerifyDevice(device
)};
3233 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3237 for(const auto &func
: alcFunctions
)
3239 if(strcmp(func
.funcName
, funcName
) == 0)
3240 return func
.address
;
3248 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3253 DeviceRef dev
{VerifyDevice(device
)};
3254 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3258 for(const auto &enm
: alcEnumerations
)
3260 if(strcmp(enm
.enumName
, enumName
) == 0)
3269 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3272 /* Explicitly hold the list lock while taking the StateLock in case the
3273 * device is asynchronously destroyed, to ensure this new context is
3274 * properly cleaned up after being made.
3276 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3277 DeviceRef dev
{VerifyDevice(device
)};
3278 if(!dev
|| dev
->Type
== DeviceType::Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3281 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3284 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3287 dev
->LastError
.store(ALC_NO_ERROR
);
3289 ALCenum err
{UpdateDeviceParams(dev
.get(), attrList
)};
3290 if(err
!= ALC_NO_ERROR
)
3292 alcSetError(dev
.get(), err
);
3296 ContextRef context
{new ALCcontext
{dev
}};
3299 if(auto volopt
= ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust"))
3301 const float valf
{*volopt
};
3302 if(!std::isfinite(valf
))
3303 ERR("volume-adjust must be finite: %f\n", valf
);
3306 const float db
{clampf(valf
, -24.0f
, 24.0f
)};
3308 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3309 context
->mGainBoost
= std::pow(10.0f
, db
/20.0f
);
3310 TRACE("volume-adjust gain: %f\n", context
->mGainBoost
);
3313 UpdateListenerProps(context
.get());
3316 using ContextArray
= al::FlexArray
<ALCcontext
*>;
3318 /* Allocate a new context array, which holds 1 more than the current/
3321 auto *oldarray
= device
->mContexts
.load();
3322 const size_t newcount
{oldarray
->size()+1};
3323 std::unique_ptr
<ContextArray
> newarray
{ContextArray::Create(newcount
)};
3325 /* Copy the current/old context handles to the new array, appending the
3328 auto iter
= std::copy(oldarray
->begin(), oldarray
->end(), newarray
->begin());
3329 *iter
= context
.get();
3331 /* Store the new context array in the device. Wait for any current mix
3332 * to finish before deleting the old array.
3334 dev
->mContexts
.store(newarray
.release());
3335 if(oldarray
!= &EmptyContextArray
)
3344 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3345 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
.get());
3346 ContextList
.emplace(iter
, context
.get());
3349 if(ALeffectslot
*slot
{context
->mDefaultSlot
.get()})
3351 if(slot
->initEffect(&DefaultEffect
, context
.get()) == AL_NO_ERROR
)
3352 slot
->updateProps(context
.get());
3354 ERR("Failed to initialize the default effect\n");
3357 TRACE("Created context %p\n", decltype(std::declval
<void*>()){context
.get()});
3358 return context
.release();
3362 ALC_API
void ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3365 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3366 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
3367 if(iter
== ContextList
.end() || *iter
!= context
)
3370 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3373 /* Hold a reference to this context so it remains valid until the ListLock
3376 ContextRef ctx
{*iter
};
3377 ContextList
.erase(iter
);
3379 ALCdevice
*Device
{ctx
->mDevice
.get()};
3381 std::lock_guard
<std::mutex
> _
{Device
->StateLock
};
3382 if(!ctx
->deinit() && Device
->Flags
.get
<DeviceRunning
>())
3384 Device
->Backend
->stop();
3385 Device
->Flags
.unset
<DeviceRunning
>();
3391 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3394 ALCcontext
*Context
{LocalContext
};
3395 if(!Context
) Context
= GlobalContext
.load();
3400 /** Returns the currently active thread-local context. */
3401 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3403 { return LocalContext
; }
3406 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3409 /* context must be valid or nullptr */
3413 ctx
= VerifyContext(context
);
3416 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3420 /* Release this reference (if any) to store it in the GlobalContext
3421 * pointer. Take ownership of the reference (if any) that was previously
3424 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3426 /* Reset (decrement) the previous global reference by replacing it with the
3427 * thread-local context. Take ownership of the thread-local context
3428 * reference (if any), clearing the storage to null.
3430 ctx
= ContextRef
{LocalContext
};
3431 if(ctx
) ThreadContext
.set(nullptr);
3432 /* Reset (decrement) the previous thread-local reference. */
3438 /** Makes the given context the active context for the current thread. */
3439 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3442 /* context must be valid or nullptr */
3446 ctx
= VerifyContext(context
);
3449 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3453 /* context's reference count is already incremented */
3454 ContextRef old
{LocalContext
};
3455 ThreadContext
.set(ctx
.release());
3462 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3465 ContextRef ctx
{VerifyContext(Context
)};
3468 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3471 return ctx
->mDevice
.get();
3476 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3481 if(!PlaybackFactory
)
3483 alcSetError(nullptr, ALC_INVALID_VALUE
);
3489 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3491 /* Some old Windows apps hardcode these expecting OpenAL to use a
3492 * specific audio API, even when they're not enumerated. Creative's
3493 * router effectively ignores them too.
3495 || al::strcasecmp(deviceName
, "DirectSound3D") == 0
3496 || al::strcasecmp(deviceName
, "DirectSound") == 0
3497 || al::strcasecmp(deviceName
, "MMSYSTEM") == 0
3499 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3500 deviceName
= nullptr;
3503 DeviceRef device
{new ALCdevice
{DeviceType::Playback
}};
3505 /* Set output format */
3506 device
->FmtChans
= DevFmtChannelsDefault
;
3507 device
->FmtType
= DevFmtTypeDefault
;
3508 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3509 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
3510 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
3512 device
->SourcesMax
= 256;
3513 device
->AuxiliaryEffectSlotMax
= 64;
3514 device
->NumAuxSends
= DEFAULT_SENDS
;
3517 auto backend
= PlaybackFactory
->createBackend(device
.get(), BackendType::Playback
);
3518 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3519 backend
->open(deviceName
);
3520 device
->Backend
= std::move(backend
);
3522 catch(al::backend_exception
&e
) {
3523 WARN("Failed to open playback device: %s\n", e
.what());
3524 alcSetError(nullptr, e
.errorCode());
3528 deviceName
= device
->DeviceName
.c_str();
3529 if(auto chanopt
= ConfigValueStr(deviceName
, nullptr, "channels"))
3531 static const struct ChannelMap
{
3532 const char name
[16];
3533 DevFmtChannels chans
;
3536 { "mono", DevFmtMono
, 0 },
3537 { "stereo", DevFmtStereo
, 0 },
3538 { "quad", DevFmtQuad
, 0 },
3539 { "surround51", DevFmtX51
, 0 },
3540 { "surround61", DevFmtX61
, 0 },
3541 { "surround71", DevFmtX71
, 0 },
3542 { "surround51rear", DevFmtX51Rear
, 0 },
3543 { "ambi1", DevFmtAmbi3D
, 1 },
3544 { "ambi2", DevFmtAmbi3D
, 2 },
3545 { "ambi3", DevFmtAmbi3D
, 3 },
3548 const ALCchar
*fmt
{chanopt
->c_str()};
3549 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3550 [fmt
](const ChannelMap
&entry
) -> bool
3551 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3553 if(iter
== std::end(chanlist
))
3554 ERR("Unsupported channels: %s\n", fmt
);
3557 device
->FmtChans
= iter
->chans
;
3558 device
->mAmbiOrder
= iter
->order
;
3559 device
->Flags
.set
<ChannelsRequest
>();
3562 if(auto typeopt
= ConfigValueStr(deviceName
, nullptr, "sample-type"))
3564 static const struct TypeMap
{
3565 const char name
[16];
3568 { "int8", DevFmtByte
},
3569 { "uint8", DevFmtUByte
},
3570 { "int16", DevFmtShort
},
3571 { "uint16", DevFmtUShort
},
3572 { "int32", DevFmtInt
},
3573 { "uint32", DevFmtUInt
},
3574 { "float32", DevFmtFloat
},
3577 const ALCchar
*fmt
{typeopt
->c_str()};
3578 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3579 [fmt
](const TypeMap
&entry
) -> bool
3580 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3582 if(iter
== std::end(typelist
))
3583 ERR("Unsupported sample-type: %s\n", fmt
);
3586 device
->FmtType
= iter
->type
;
3587 device
->Flags
.set
<SampleTypeRequest
>();
3591 if(ALuint freq
{ConfigValueUInt(deviceName
, nullptr, "frequency").value_or(0)})
3593 if(freq
< MIN_OUTPUT_RATE
|| freq
> MAX_OUTPUT_RATE
)
3595 const ALuint newfreq
{clampu(freq
, MIN_OUTPUT_RATE
, MAX_OUTPUT_RATE
)};
3596 ERR("%uhz request clamped to %uhz\n", freq
, newfreq
);
3599 const double scale
{static_cast<double>(freq
) / device
->Frequency
};
3600 device
->UpdateSize
= static_cast<ALuint
>(device
->UpdateSize
*scale
+ 0.5);
3601 device
->BufferSize
= static_cast<ALuint
>(device
->BufferSize
*scale
+ 0.5);
3602 device
->Frequency
= freq
;
3603 device
->Flags
.set
<FrequencyRequest
>();
3606 if(auto persizeopt
= ConfigValueUInt(deviceName
, nullptr, "period_size"))
3607 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
3609 if(auto peropt
= ConfigValueUInt(deviceName
, nullptr, "periods"))
3610 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
3612 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
3614 if(auto srcsmax
= ConfigValueUInt(deviceName
, nullptr, "sources").value_or(0))
3615 device
->SourcesMax
= srcsmax
;
3617 if(auto slotsmax
= ConfigValueUInt(deviceName
, nullptr, "slots").value_or(0))
3618 device
->AuxiliaryEffectSlotMax
= minu(slotsmax
, INT_MAX
);
3620 if(auto sendsopt
= ConfigValueInt(deviceName
, nullptr, "sends"))
3621 device
->NumAuxSends
= minu(DEFAULT_SENDS
,
3622 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3624 device
->NumStereoSources
= 1;
3625 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3627 if(auto ambiopt
= ConfigValueStr(deviceName
, nullptr, "ambi-format"))
3629 const ALCchar
*fmt
{ambiopt
->c_str()};
3630 if(al::strcasecmp(fmt
, "fuma") == 0)
3632 if(device
->mAmbiOrder
> 3)
3633 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3635 (((device
->mAmbiOrder
%100)/10) == 1) ? "th" :
3636 ((device
->mAmbiOrder
%10) == 1) ? "st" :
3637 ((device
->mAmbiOrder
%10) == 2) ? "nd" :
3638 ((device
->mAmbiOrder
%10) == 3) ? "rd" : "th");
3641 device
->mAmbiLayout
= DevAmbiLayout::FuMa
;
3642 device
->mAmbiScale
= DevAmbiScaling::FuMa
;
3645 else if(al::strcasecmp(fmt
, "ambix") == 0 || al::strcasecmp(fmt
, "acn+sn3d") == 0)
3647 device
->mAmbiLayout
= DevAmbiLayout::ACN
;
3648 device
->mAmbiScale
= DevAmbiScaling::SN3D
;
3650 else if(al::strcasecmp(fmt
, "acn+n3d") == 0)
3652 device
->mAmbiLayout
= DevAmbiLayout::ACN
;
3653 device
->mAmbiScale
= DevAmbiScaling::N3D
;
3656 ERR("Unsupported ambi-format: %s\n", fmt
);
3660 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3661 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3662 DeviceList
.emplace(iter
, device
.get());
3665 TRACE("Created device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3666 device
->DeviceName
.c_str());
3667 return device
.release();
3671 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3674 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3675 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3676 if(iter
== DeviceList
.end() || *iter
!= device
)
3678 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3681 if((*iter
)->Type
== DeviceType::Capture
)
3683 alcSetError(*iter
, ALC_INVALID_DEVICE
);
3687 /* Erase the device, and any remaining contexts left on it, from their
3690 DeviceRef dev
{*iter
};
3691 DeviceList
.erase(iter
);
3693 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3694 al::vector
<ContextRef
> orphanctxs
;
3695 for(ALCcontext
*ctx
: *dev
->mContexts
.load())
3697 auto ctxiter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), ctx
);
3698 if(ctxiter
!= ContextList
.end() && *ctxiter
== ctx
)
3700 orphanctxs
.emplace_back(ContextRef
{*ctxiter
});
3701 ContextList
.erase(ctxiter
);
3706 for(ContextRef
&context
: orphanctxs
)
3708 WARN("Releasing orphaned context %p\n", decltype(std::declval
<void*>()){context
.get()});
3713 if(dev
->Flags
.get
<DeviceRunning
>())
3714 dev
->Backend
->stop();
3715 dev
->Flags
.unset
<DeviceRunning
>();
3722 /************************************************
3723 * ALC capture functions
3724 ************************************************/
3725 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3732 alcSetError(nullptr, ALC_INVALID_VALUE
);
3738 alcSetError(nullptr, ALC_INVALID_VALUE
);
3744 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3745 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3746 deviceName
= nullptr;
3749 DeviceRef device
{new ALCdevice
{DeviceType::Capture
}};
3751 auto decompfmt
= DecomposeDevFormat(format
);
3754 alcSetError(nullptr, ALC_INVALID_ENUM
);
3758 device
->Frequency
= frequency
;
3759 device
->FmtChans
= decompfmt
->chans
;
3760 device
->FmtType
= decompfmt
->type
;
3761 device
->Flags
.set
<FrequencyRequest
, ChannelsRequest
, SampleTypeRequest
>();
3763 device
->UpdateSize
= static_cast<ALuint
>(samples
);
3764 device
->BufferSize
= static_cast<ALuint
>(samples
);
3767 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3768 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
3769 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
3771 auto backend
= CaptureFactory
->createBackend(device
.get(), BackendType::Capture
);
3772 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3773 backend
->open(deviceName
);
3774 device
->Backend
= std::move(backend
);
3776 catch(al::backend_exception
&e
) {
3777 WARN("Failed to open capture device: %s\n", e
.what());
3778 alcSetError(nullptr, e
.errorCode());
3783 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3784 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3785 DeviceList
.emplace(iter
, device
.get());
3788 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3789 device
->DeviceName
.c_str());
3790 return device
.release();
3794 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3797 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3798 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3799 if(iter
== DeviceList
.end() || *iter
!= device
)
3801 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3804 if((*iter
)->Type
!= DeviceType::Capture
)
3806 alcSetError(*iter
, ALC_INVALID_DEVICE
);
3810 DeviceRef dev
{*iter
};
3811 DeviceList
.erase(iter
);
3814 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3815 if(dev
->Flags
.get
<DeviceRunning
>())
3816 dev
->Backend
->stop();
3817 dev
->Flags
.unset
<DeviceRunning
>();
3823 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3826 DeviceRef dev
{VerifyDevice(device
)};
3827 if(!dev
|| dev
->Type
!= DeviceType::Capture
)
3829 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3833 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3834 if(!dev
->Connected
.load(std::memory_order_acquire
))
3835 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3836 else if(!dev
->Flags
.get
<DeviceRunning
>())
3839 auto backend
= dev
->Backend
.get();
3841 dev
->Flags
.set
<DeviceRunning
>();
3843 catch(al::backend_exception
& e
) {
3844 dev
->handleDisconnect("%s", e
.what());
3845 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3851 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3854 DeviceRef dev
{VerifyDevice(device
)};
3855 if(!dev
|| dev
->Type
!= DeviceType::Capture
)
3856 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3859 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3860 if(dev
->Flags
.get
<DeviceRunning
>())
3861 dev
->Backend
->stop();
3862 dev
->Flags
.unset
<DeviceRunning
>();
3867 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3870 DeviceRef dev
{VerifyDevice(device
)};
3871 if(!dev
|| dev
->Type
!= DeviceType::Capture
)
3873 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3877 if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
3879 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3885 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3886 BackendBase
*backend
{dev
->Backend
.get()};
3888 const auto usamples
= static_cast<ALCuint
>(samples
);
3889 if(usamples
> backend
->availableSamples())
3891 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3895 auto *bbuffer
= static_cast<al::byte
*>(buffer
);
3896 if(ALCenum err
{backend
->captureSamples(bbuffer
, usamples
)})
3897 alcSetError(dev
.get(), err
);
3902 /************************************************
3903 * ALC loopback functions
3904 ************************************************/
3906 /** Open a loopback device, for manual rendering. */
3907 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3912 /* Make sure the device name, if specified, is us. */
3913 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3915 alcSetError(nullptr, ALC_INVALID_VALUE
);
3919 DeviceRef device
{new ALCdevice
{DeviceType::Loopback
}};
3921 device
->SourcesMax
= 256;
3922 device
->AuxiliaryEffectSlotMax
= 64;
3923 device
->NumAuxSends
= DEFAULT_SENDS
;
3926 device
->BufferSize
= 0;
3927 device
->UpdateSize
= 0;
3929 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3930 device
->FmtChans
= DevFmtChannelsDefault
;
3931 device
->FmtType
= DevFmtTypeDefault
;
3933 if(auto srcsmax
= ConfigValueUInt(nullptr, nullptr, "sources").value_or(0))
3934 device
->SourcesMax
= srcsmax
;
3936 if(auto slotsmax
= ConfigValueUInt(nullptr, nullptr, "slots").value_or(0))
3937 device
->AuxiliaryEffectSlotMax
= minu(slotsmax
, INT_MAX
);
3939 if(auto sendsopt
= ConfigValueInt(nullptr, nullptr, "sends"))
3940 device
->NumAuxSends
= minu(DEFAULT_SENDS
,
3941 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3943 device
->NumStereoSources
= 1;
3944 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3947 auto backend
= LoopbackBackendFactory::getFactory().createBackend(device
.get(),
3948 BackendType::Playback
);
3949 backend
->open("Loopback");
3950 device
->Backend
= std::move(backend
);
3952 catch(al::backend_exception
&e
) {
3953 WARN("Failed to open loopback device: %s\n", e
.what());
3954 alcSetError(nullptr, e
.errorCode());
3959 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3960 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3961 DeviceList
.emplace(iter
, device
.get());
3964 TRACE("Created loopback device %p\n", decltype(std::declval
<void*>()){device
.get()});
3965 return device
.release();
3970 * Determines if the loopback device supports the given format for rendering.
3972 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3975 DeviceRef dev
{VerifyDevice(device
)};
3976 if(!dev
|| dev
->Type
!= DeviceType::Loopback
)
3977 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3979 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3982 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
3983 && freq
<= MAX_OUTPUT_RATE
)
3992 * Renders some samples into a buffer, using the format last set by the
3993 * attributes given to alcCreateContext.
3995 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3998 DeviceRef dev
{VerifyDevice(device
)};
3999 if(!dev
|| dev
->Type
!= DeviceType::Loopback
)
4000 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4001 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4002 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4004 dev
->renderSamples(buffer
, static_cast<ALuint
>(samples
), dev
->channelsFromFmt());
4009 /************************************************
4010 * ALC DSP pause/resume functions
4011 ************************************************/
4013 /** Pause the DSP to stop audio processing. */
4014 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4017 DeviceRef dev
{VerifyDevice(device
)};
4018 if(!dev
|| dev
->Type
!= DeviceType::Playback
)
4019 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4022 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4023 if(dev
->Flags
.get
<DeviceRunning
>())
4024 dev
->Backend
->stop();
4025 dev
->Flags
.unset
<DeviceRunning
>();
4026 dev
->Flags
.set
<DevicePaused
>();
4031 /** Resume the DSP to restart audio processing. */
4032 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4035 DeviceRef dev
{VerifyDevice(device
)};
4036 if(!dev
|| dev
->Type
!= DeviceType::Playback
)
4038 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4042 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4043 if(!dev
->Flags
.get
<DevicePaused
>())
4045 dev
->Flags
.unset
<DevicePaused
>();
4046 if(dev
->mContexts
.load()->empty())
4050 auto backend
= dev
->Backend
.get();
4052 dev
->Flags
.set
<DeviceRunning
>();
4054 catch(al::backend_exception
& e
) {
4055 dev
->handleDisconnect("%s", e
.what());
4056 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4062 /************************************************
4063 * ALC HRTF functions
4064 ************************************************/
4066 /** Gets a string parameter at the given index. */
4067 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4070 DeviceRef dev
{VerifyDevice(device
)};
4071 if(!dev
|| dev
->Type
== DeviceType::Capture
)
4072 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4073 else switch(paramName
)
4075 case ALC_HRTF_SPECIFIER_SOFT
:
4076 if(index
>= 0 && static_cast<size_t>(index
) < dev
->HrtfList
.size())
4077 return dev
->HrtfList
[static_cast<ALuint
>(index
)].c_str();
4078 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4082 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4090 /** Resets the given device output, using the specified attribute list. */
4091 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4094 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4095 DeviceRef dev
{VerifyDevice(device
)};
4096 if(!dev
|| dev
->Type
== DeviceType::Capture
)
4099 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4102 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4105 /* Force the backend to stop mixing first since we're resetting. Also reset
4106 * the connected state so lost devices can attempt recover.
4108 if(dev
->Flags
.get
<DeviceRunning
>())
4109 dev
->Backend
->stop();
4110 dev
->Flags
.unset
<DeviceRunning
>();
4111 if(!dev
->Connected
.load(std::memory_order_relaxed
))
4113 /* Make sure disconnection is finished before continuing on. */
4116 for(ALCcontext
*ctx
: *dev
->mContexts
.load(std::memory_order_acquire
))
4118 /* Clear any pending voice changes and reallocate voices to get a
4121 std::lock_guard
<std::mutex
> __
{ctx
->mSourceLock
};
4122 auto *vchg
= ctx
->mCurrentVoiceChange
.load(std::memory_order_acquire
);
4123 while(auto *next
= vchg
->mNext
.load(std::memory_order_acquire
))
4125 ctx
->mCurrentVoiceChange
.store(vchg
, std::memory_order_release
);
4127 ctx
->mVoiceClusters
.clear();
4128 ctx
->allocVoices(std::max
<size_t>(256,
4129 ctx
->mActiveVoiceCount
.load(std::memory_order_relaxed
)));
4132 dev
->Connected
.store(true);
4135 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4136 if LIKELY(err
== ALC_NO_ERROR
) return ALC_TRUE
;
4138 alcSetError(dev
.get(), err
);