2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
55 #include "al/auxeffectslot.h"
56 #include "al/effect.h"
58 #include "al/filter.h"
59 #include "al/listener.h"
60 #include "al/source.h"
64 #include "alcontext.h"
67 #include "alnumeric.h"
68 #include "aloptional.h"
73 #include "bformatdec.h"
77 #include "devformat.h"
78 #include "effects/base.h"
79 #include "filters/nfc.h"
80 #include "filters/splitter.h"
81 #include "fpu_modes.h"
83 #include "inprogext.h"
84 #include "intrusive_ptr.h"
86 #include "mastering.h"
87 #include "opthelpers.h"
88 #include "ringbuffer.h"
91 #include "uhjfilter.h"
95 #include "backends/base.h"
96 #include "backends/null.h"
97 #include "backends/loopback.h"
99 #include "backends/jack.h"
101 #ifdef HAVE_PULSEAUDIO
102 #include "backends/pulseaudio.h"
105 #include "backends/alsa.h"
108 #include "backends/wasapi.h"
110 #ifdef HAVE_COREAUDIO
111 #include "backends/coreaudio.h"
114 #include "backends/opensl.h"
117 #include "backends/solaris.h"
120 #include "backends/sndio.h"
123 #include "backends/oss.h"
126 #include "backends/qsa.h"
129 #include "backends/dsound.h"
132 #include "backends/winmm.h"
134 #ifdef HAVE_PORTAUDIO
135 #include "backends/portaudio.h"
138 #include "backends/sdl2.h"
141 #include "backends/wave.h"
147 using namespace std::placeholders
;
148 using std::chrono::seconds
;
149 using std::chrono::nanoseconds
;
152 /************************************************
154 ************************************************/
157 BackendFactory
& (*getFactory
)(void);
160 BackendInfo BackendList
[] = {
162 { "jack", JackBackendFactory::getFactory
},
164 #ifdef HAVE_PULSEAUDIO
165 { "pulse", PulseBackendFactory::getFactory
},
168 { "alsa", AlsaBackendFactory::getFactory
},
171 { "wasapi", WasapiBackendFactory::getFactory
},
173 #ifdef HAVE_COREAUDIO
174 { "core", CoreAudioBackendFactory::getFactory
},
177 { "opensl", OSLBackendFactory::getFactory
},
180 { "solaris", SolarisBackendFactory::getFactory
},
183 { "sndio", SndIOBackendFactory::getFactory
},
186 { "oss", OSSBackendFactory::getFactory
},
189 { "qsa", QSABackendFactory::getFactory
},
192 { "dsound", DSoundBackendFactory::getFactory
},
195 { "winmm", WinMMBackendFactory::getFactory
},
197 #ifdef HAVE_PORTAUDIO
198 { "port", PortBackendFactory::getFactory
},
201 { "sdl2", SDL2BackendFactory::getFactory
},
204 { "null", NullBackendFactory::getFactory
},
206 { "wave", WaveBackendFactory::getFactory
},
209 auto BackendListEnd
= std::end(BackendList
);
211 BackendFactory
*PlaybackFactory
{};
212 BackendFactory
*CaptureFactory
{};
215 /************************************************
216 * Functions, enums, and errors
217 ************************************************/
218 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
220 const ALCchar
*funcName
;
223 DECL(alcCreateContext
),
224 DECL(alcMakeContextCurrent
),
225 DECL(alcProcessContext
),
226 DECL(alcSuspendContext
),
227 DECL(alcDestroyContext
),
228 DECL(alcGetCurrentContext
),
229 DECL(alcGetContextsDevice
),
231 DECL(alcCloseDevice
),
233 DECL(alcIsExtensionPresent
),
234 DECL(alcGetProcAddress
),
235 DECL(alcGetEnumValue
),
237 DECL(alcGetIntegerv
),
238 DECL(alcCaptureOpenDevice
),
239 DECL(alcCaptureCloseDevice
),
240 DECL(alcCaptureStart
),
241 DECL(alcCaptureStop
),
242 DECL(alcCaptureSamples
),
244 DECL(alcSetThreadContext
),
245 DECL(alcGetThreadContext
),
247 DECL(alcLoopbackOpenDeviceSOFT
),
248 DECL(alcIsRenderFormatSupportedSOFT
),
249 DECL(alcRenderSamplesSOFT
),
251 DECL(alcDevicePauseSOFT
),
252 DECL(alcDeviceResumeSOFT
),
254 DECL(alcGetStringiSOFT
),
255 DECL(alcResetDeviceSOFT
),
257 DECL(alcGetInteger64vSOFT
),
272 DECL(alIsExtensionPresent
),
273 DECL(alGetProcAddress
),
274 DECL(alGetEnumValue
),
281 DECL(alGetListenerf
),
282 DECL(alGetListener3f
),
283 DECL(alGetListenerfv
),
284 DECL(alGetListeneri
),
285 DECL(alGetListener3i
),
286 DECL(alGetListeneriv
),
288 DECL(alDeleteSources
),
304 DECL(alSourceRewindv
),
305 DECL(alSourcePausev
),
308 DECL(alSourceRewind
),
310 DECL(alSourceQueueBuffers
),
311 DECL(alSourceUnqueueBuffers
),
313 DECL(alDeleteBuffers
),
328 DECL(alDopplerFactor
),
329 DECL(alDopplerVelocity
),
330 DECL(alSpeedOfSound
),
331 DECL(alDistanceModel
),
334 DECL(alDeleteFilters
),
345 DECL(alDeleteEffects
),
355 DECL(alGenAuxiliaryEffectSlots
),
356 DECL(alDeleteAuxiliaryEffectSlots
),
357 DECL(alIsAuxiliaryEffectSlot
),
358 DECL(alAuxiliaryEffectSloti
),
359 DECL(alAuxiliaryEffectSlotiv
),
360 DECL(alAuxiliaryEffectSlotf
),
361 DECL(alAuxiliaryEffectSlotfv
),
362 DECL(alGetAuxiliaryEffectSloti
),
363 DECL(alGetAuxiliaryEffectSlotiv
),
364 DECL(alGetAuxiliaryEffectSlotf
),
365 DECL(alGetAuxiliaryEffectSlotfv
),
367 DECL(alDeferUpdatesSOFT
),
368 DECL(alProcessUpdatesSOFT
),
371 DECL(alSource3dSOFT
),
372 DECL(alSourcedvSOFT
),
373 DECL(alGetSourcedSOFT
),
374 DECL(alGetSource3dSOFT
),
375 DECL(alGetSourcedvSOFT
),
376 DECL(alSourcei64SOFT
),
377 DECL(alSource3i64SOFT
),
378 DECL(alSourcei64vSOFT
),
379 DECL(alGetSourcei64SOFT
),
380 DECL(alGetSource3i64SOFT
),
381 DECL(alGetSourcei64vSOFT
),
383 DECL(alGetStringiSOFT
),
385 DECL(alBufferStorageSOFT
),
386 DECL(alMapBufferSOFT
),
387 DECL(alUnmapBufferSOFT
),
388 DECL(alFlushMappedBufferSOFT
),
390 DECL(alEventControlSOFT
),
391 DECL(alEventCallbackSOFT
),
392 DECL(alGetPointerSOFT
),
393 DECL(alGetPointervSOFT
),
397 #define DECL(x) { #x, (x) }
399 const ALCchar
*enumName
;
401 } alcEnumerations
[] = {
406 DECL(ALC_MAJOR_VERSION
),
407 DECL(ALC_MINOR_VERSION
),
408 DECL(ALC_ATTRIBUTES_SIZE
),
409 DECL(ALC_ALL_ATTRIBUTES
),
410 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
411 DECL(ALC_DEVICE_SPECIFIER
),
412 DECL(ALC_ALL_DEVICES_SPECIFIER
),
413 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
414 DECL(ALC_EXTENSIONS
),
418 DECL(ALC_MONO_SOURCES
),
419 DECL(ALC_STEREO_SOURCES
),
420 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
421 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
422 DECL(ALC_CAPTURE_SAMPLES
),
425 DECL(ALC_EFX_MAJOR_VERSION
),
426 DECL(ALC_EFX_MINOR_VERSION
),
427 DECL(ALC_MAX_AUXILIARY_SENDS
),
429 DECL(ALC_FORMAT_CHANNELS_SOFT
),
430 DECL(ALC_FORMAT_TYPE_SOFT
),
433 DECL(ALC_STEREO_SOFT
),
435 DECL(ALC_5POINT1_SOFT
),
436 DECL(ALC_6POINT1_SOFT
),
437 DECL(ALC_7POINT1_SOFT
),
438 DECL(ALC_BFORMAT3D_SOFT
),
441 DECL(ALC_UNSIGNED_BYTE_SOFT
),
442 DECL(ALC_SHORT_SOFT
),
443 DECL(ALC_UNSIGNED_SHORT_SOFT
),
445 DECL(ALC_UNSIGNED_INT_SOFT
),
446 DECL(ALC_FLOAT_SOFT
),
449 DECL(ALC_DONT_CARE_SOFT
),
450 DECL(ALC_HRTF_STATUS_SOFT
),
451 DECL(ALC_HRTF_DISABLED_SOFT
),
452 DECL(ALC_HRTF_ENABLED_SOFT
),
453 DECL(ALC_HRTF_DENIED_SOFT
),
454 DECL(ALC_HRTF_REQUIRED_SOFT
),
455 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
456 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
457 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
458 DECL(ALC_HRTF_SPECIFIER_SOFT
),
459 DECL(ALC_HRTF_ID_SOFT
),
461 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
462 DECL(ALC_AMBISONIC_SCALING_SOFT
),
463 DECL(ALC_AMBISONIC_ORDER_SOFT
),
469 DECL(ALC_OUTPUT_LIMITER_SOFT
),
472 DECL(ALC_INVALID_DEVICE
),
473 DECL(ALC_INVALID_CONTEXT
),
474 DECL(ALC_INVALID_ENUM
),
475 DECL(ALC_INVALID_VALUE
),
476 DECL(ALC_OUT_OF_MEMORY
),
484 DECL(AL_SOURCE_RELATIVE
),
485 DECL(AL_CONE_INNER_ANGLE
),
486 DECL(AL_CONE_OUTER_ANGLE
),
496 DECL(AL_ORIENTATION
),
497 DECL(AL_REFERENCE_DISTANCE
),
498 DECL(AL_ROLLOFF_FACTOR
),
499 DECL(AL_CONE_OUTER_GAIN
),
500 DECL(AL_MAX_DISTANCE
),
502 DECL(AL_SAMPLE_OFFSET
),
503 DECL(AL_BYTE_OFFSET
),
504 DECL(AL_SOURCE_TYPE
),
507 DECL(AL_UNDETERMINED
),
508 DECL(AL_METERS_PER_UNIT
),
509 DECL(AL_LOOP_POINTS_SOFT
),
510 DECL(AL_DIRECT_CHANNELS_SOFT
),
512 DECL(AL_DIRECT_FILTER
),
513 DECL(AL_AUXILIARY_SEND_FILTER
),
514 DECL(AL_AIR_ABSORPTION_FACTOR
),
515 DECL(AL_ROOM_ROLLOFF_FACTOR
),
516 DECL(AL_CONE_OUTER_GAINHF
),
517 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
518 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
519 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
521 DECL(AL_SOURCE_STATE
),
527 DECL(AL_BUFFERS_QUEUED
),
528 DECL(AL_BUFFERS_PROCESSED
),
530 DECL(AL_FORMAT_MONO8
),
531 DECL(AL_FORMAT_MONO16
),
532 DECL(AL_FORMAT_MONO_FLOAT32
),
533 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
534 DECL(AL_FORMAT_STEREO8
),
535 DECL(AL_FORMAT_STEREO16
),
536 DECL(AL_FORMAT_STEREO_FLOAT32
),
537 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
538 DECL(AL_FORMAT_MONO_IMA4
),
539 DECL(AL_FORMAT_STEREO_IMA4
),
540 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
541 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
542 DECL(AL_FORMAT_QUAD8_LOKI
),
543 DECL(AL_FORMAT_QUAD16_LOKI
),
544 DECL(AL_FORMAT_QUAD8
),
545 DECL(AL_FORMAT_QUAD16
),
546 DECL(AL_FORMAT_QUAD32
),
547 DECL(AL_FORMAT_51CHN8
),
548 DECL(AL_FORMAT_51CHN16
),
549 DECL(AL_FORMAT_51CHN32
),
550 DECL(AL_FORMAT_61CHN8
),
551 DECL(AL_FORMAT_61CHN16
),
552 DECL(AL_FORMAT_61CHN32
),
553 DECL(AL_FORMAT_71CHN8
),
554 DECL(AL_FORMAT_71CHN16
),
555 DECL(AL_FORMAT_71CHN32
),
556 DECL(AL_FORMAT_REAR8
),
557 DECL(AL_FORMAT_REAR16
),
558 DECL(AL_FORMAT_REAR32
),
559 DECL(AL_FORMAT_MONO_MULAW
),
560 DECL(AL_FORMAT_MONO_MULAW_EXT
),
561 DECL(AL_FORMAT_STEREO_MULAW
),
562 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
563 DECL(AL_FORMAT_QUAD_MULAW
),
564 DECL(AL_FORMAT_51CHN_MULAW
),
565 DECL(AL_FORMAT_61CHN_MULAW
),
566 DECL(AL_FORMAT_71CHN_MULAW
),
567 DECL(AL_FORMAT_REAR_MULAW
),
568 DECL(AL_FORMAT_MONO_ALAW_EXT
),
569 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
571 DECL(AL_FORMAT_BFORMAT2D_8
),
572 DECL(AL_FORMAT_BFORMAT2D_16
),
573 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
574 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
575 DECL(AL_FORMAT_BFORMAT3D_8
),
576 DECL(AL_FORMAT_BFORMAT3D_16
),
577 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
578 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
584 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
585 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
587 DECL(AL_SOURCE_RADIUS
),
589 DECL(AL_STEREO_ANGLES
),
596 DECL(AL_INVALID_NAME
),
597 DECL(AL_INVALID_ENUM
),
598 DECL(AL_INVALID_VALUE
),
599 DECL(AL_INVALID_OPERATION
),
600 DECL(AL_OUT_OF_MEMORY
),
607 DECL(AL_DOPPLER_FACTOR
),
608 DECL(AL_DOPPLER_VELOCITY
),
609 DECL(AL_DISTANCE_MODEL
),
610 DECL(AL_SPEED_OF_SOUND
),
611 DECL(AL_SOURCE_DISTANCE_MODEL
),
612 DECL(AL_DEFERRED_UPDATES_SOFT
),
613 DECL(AL_GAIN_LIMIT_SOFT
),
615 DECL(AL_INVERSE_DISTANCE
),
616 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
617 DECL(AL_LINEAR_DISTANCE
),
618 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
619 DECL(AL_EXPONENT_DISTANCE
),
620 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
622 DECL(AL_FILTER_TYPE
),
623 DECL(AL_FILTER_NULL
),
624 DECL(AL_FILTER_LOWPASS
),
625 DECL(AL_FILTER_HIGHPASS
),
626 DECL(AL_FILTER_BANDPASS
),
628 DECL(AL_LOWPASS_GAIN
),
629 DECL(AL_LOWPASS_GAINHF
),
631 DECL(AL_HIGHPASS_GAIN
),
632 DECL(AL_HIGHPASS_GAINLF
),
634 DECL(AL_BANDPASS_GAIN
),
635 DECL(AL_BANDPASS_GAINHF
),
636 DECL(AL_BANDPASS_GAINLF
),
638 DECL(AL_EFFECT_TYPE
),
639 DECL(AL_EFFECT_NULL
),
640 DECL(AL_EFFECT_REVERB
),
641 DECL(AL_EFFECT_EAXREVERB
),
642 DECL(AL_EFFECT_CHORUS
),
643 DECL(AL_EFFECT_DISTORTION
),
644 DECL(AL_EFFECT_ECHO
),
645 DECL(AL_EFFECT_FLANGER
),
646 DECL(AL_EFFECT_PITCH_SHIFTER
),
647 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
648 DECL(AL_EFFECT_VOCAL_MORPHER
),
649 DECL(AL_EFFECT_RING_MODULATOR
),
650 DECL(AL_EFFECT_AUTOWAH
),
651 DECL(AL_EFFECT_COMPRESSOR
),
652 DECL(AL_EFFECT_EQUALIZER
),
653 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
654 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
656 DECL(AL_EFFECTSLOT_EFFECT
),
657 DECL(AL_EFFECTSLOT_GAIN
),
658 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
659 DECL(AL_EFFECTSLOT_NULL
),
661 DECL(AL_EAXREVERB_DENSITY
),
662 DECL(AL_EAXREVERB_DIFFUSION
),
663 DECL(AL_EAXREVERB_GAIN
),
664 DECL(AL_EAXREVERB_GAINHF
),
665 DECL(AL_EAXREVERB_GAINLF
),
666 DECL(AL_EAXREVERB_DECAY_TIME
),
667 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
668 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
669 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
670 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
671 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
672 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
673 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
674 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
675 DECL(AL_EAXREVERB_ECHO_TIME
),
676 DECL(AL_EAXREVERB_ECHO_DEPTH
),
677 DECL(AL_EAXREVERB_MODULATION_TIME
),
678 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
679 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
680 DECL(AL_EAXREVERB_HFREFERENCE
),
681 DECL(AL_EAXREVERB_LFREFERENCE
),
682 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
683 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
685 DECL(AL_REVERB_DENSITY
),
686 DECL(AL_REVERB_DIFFUSION
),
687 DECL(AL_REVERB_GAIN
),
688 DECL(AL_REVERB_GAINHF
),
689 DECL(AL_REVERB_DECAY_TIME
),
690 DECL(AL_REVERB_DECAY_HFRATIO
),
691 DECL(AL_REVERB_REFLECTIONS_GAIN
),
692 DECL(AL_REVERB_REFLECTIONS_DELAY
),
693 DECL(AL_REVERB_LATE_REVERB_GAIN
),
694 DECL(AL_REVERB_LATE_REVERB_DELAY
),
695 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
696 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
697 DECL(AL_REVERB_DECAY_HFLIMIT
),
699 DECL(AL_CHORUS_WAVEFORM
),
700 DECL(AL_CHORUS_PHASE
),
701 DECL(AL_CHORUS_RATE
),
702 DECL(AL_CHORUS_DEPTH
),
703 DECL(AL_CHORUS_FEEDBACK
),
704 DECL(AL_CHORUS_DELAY
),
706 DECL(AL_DISTORTION_EDGE
),
707 DECL(AL_DISTORTION_GAIN
),
708 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
709 DECL(AL_DISTORTION_EQCENTER
),
710 DECL(AL_DISTORTION_EQBANDWIDTH
),
713 DECL(AL_ECHO_LRDELAY
),
714 DECL(AL_ECHO_DAMPING
),
715 DECL(AL_ECHO_FEEDBACK
),
716 DECL(AL_ECHO_SPREAD
),
718 DECL(AL_FLANGER_WAVEFORM
),
719 DECL(AL_FLANGER_PHASE
),
720 DECL(AL_FLANGER_RATE
),
721 DECL(AL_FLANGER_DEPTH
),
722 DECL(AL_FLANGER_FEEDBACK
),
723 DECL(AL_FLANGER_DELAY
),
725 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
726 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
727 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
729 DECL(AL_RING_MODULATOR_FREQUENCY
),
730 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
731 DECL(AL_RING_MODULATOR_WAVEFORM
),
733 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
734 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
736 DECL(AL_COMPRESSOR_ONOFF
),
738 DECL(AL_EQUALIZER_LOW_GAIN
),
739 DECL(AL_EQUALIZER_LOW_CUTOFF
),
740 DECL(AL_EQUALIZER_MID1_GAIN
),
741 DECL(AL_EQUALIZER_MID1_CENTER
),
742 DECL(AL_EQUALIZER_MID1_WIDTH
),
743 DECL(AL_EQUALIZER_MID2_GAIN
),
744 DECL(AL_EQUALIZER_MID2_CENTER
),
745 DECL(AL_EQUALIZER_MID2_WIDTH
),
746 DECL(AL_EQUALIZER_HIGH_GAIN
),
747 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
749 DECL(AL_DEDICATED_GAIN
),
751 DECL(AL_AUTOWAH_ATTACK_TIME
),
752 DECL(AL_AUTOWAH_RELEASE_TIME
),
753 DECL(AL_AUTOWAH_RESONANCE
),
754 DECL(AL_AUTOWAH_PEAK_GAIN
),
756 DECL(AL_VOCAL_MORPHER_PHONEMEA
),
757 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
758 DECL(AL_VOCAL_MORPHER_PHONEMEB
),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
760 DECL(AL_VOCAL_MORPHER_WAVEFORM
),
761 DECL(AL_VOCAL_MORPHER_RATE
),
763 DECL(AL_NUM_RESAMPLERS_SOFT
),
764 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
765 DECL(AL_SOURCE_RESAMPLER_SOFT
),
766 DECL(AL_RESAMPLER_NAME_SOFT
),
768 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
771 DECL(AL_MAP_READ_BIT_SOFT
),
772 DECL(AL_MAP_WRITE_BIT_SOFT
),
773 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
774 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
776 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
777 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
778 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
779 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
780 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
781 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
782 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
786 constexpr ALCchar alcNoError
[] = "No Error";
787 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
788 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
789 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
790 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
791 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
794 /************************************************
796 ************************************************/
798 /* Enumerated device names */
799 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
801 std::string alcAllDevicesList
;
802 std::string alcCaptureDeviceList
;
804 /* Default is always the first in the list */
805 std::string alcDefaultAllDevicesSpecifier
;
806 std::string alcCaptureDefaultDeviceSpecifier
;
808 /* Default context extensions */
809 constexpr ALchar alExtList
[] =
813 "AL_EXT_EXPONENT_DISTANCE "
816 "AL_EXT_LINEAR_DISTANCE "
819 "AL_EXT_MULAW_BFORMAT "
820 "AL_EXT_MULAW_MCFORMATS "
822 "AL_EXT_source_distance_model "
823 "AL_EXT_SOURCE_RADIUS "
824 "AL_EXT_STEREO_ANGLES "
825 "AL_LOKI_quadriphonic "
826 "AL_SOFT_block_alignment "
827 "AL_SOFT_deferred_updates "
828 "AL_SOFT_direct_channels "
829 "AL_SOFTX_effect_chain "
831 "AL_SOFTX_filter_gain_ex "
832 "AL_SOFT_gain_clamp_ex "
833 "AL_SOFT_loop_points "
834 "AL_SOFTX_map_buffer "
836 "AL_SOFT_source_latency "
837 "AL_SOFT_source_length "
838 "AL_SOFT_source_resampler "
839 "AL_SOFT_source_spatialize";
841 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
843 /* Thread-local current context */
844 void ReleaseThreadCtx(ALCcontext
*context
)
846 const bool result
{context
->releaseIfNoDelete()};
847 ERR("Context %p current for thread being destroyed%s!\n", context
,
848 result
? "" : ", leak detected");
852 ALCcontext
*ctx
{nullptr};
858 ReleaseThreadCtx(ctx
);
862 ALCcontext
*get() const noexcept
{ return ctx
; }
863 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
865 thread_local ThreadCtx LocalContext
;
866 /* Process-wide current context */
867 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
869 /* Flag to trap ALC device errors */
870 bool TrapALCError
{false};
872 /* One-time configuration init control */
873 std::once_flag alc_config_once
{};
875 /* Default effect that applies to sources that don't have an effect on send 0 */
876 ALeffect DefaultEffect
;
878 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
881 bool SuspendDefers
{true};
884 /************************************************
886 ************************************************/
887 constexpr ALCchar alcNoDeviceExtList
[] =
888 "ALC_ENUMERATE_ALL_EXT "
889 "ALC_ENUMERATION_EXT "
891 "ALC_EXT_thread_local_context "
893 constexpr ALCchar alcExtensionList
[] =
894 "ALC_ENUMERATE_ALL_EXT "
895 "ALC_ENUMERATION_EXT "
898 "ALC_EXT_disconnect "
900 "ALC_EXT_thread_local_context "
901 "ALC_SOFT_device_clock "
904 "ALC_SOFT_output_limiter "
905 "ALC_SOFT_pause_device";
906 constexpr ALCint alcMajorVersion
= 1;
907 constexpr ALCint alcMinorVersion
= 1;
909 constexpr ALCint alcEFXMajorVersion
= 1;
910 constexpr ALCint alcEFXMinorVersion
= 0;
913 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
914 * globally as a sharable object.
916 al::FlexArray
<ALCcontext
*> EmptyContextArray
{0u};
919 using DeviceRef
= al::intrusive_ptr
<ALCdevice
>;
922 /************************************************
924 ************************************************/
925 al::vector
<DeviceRef
> DeviceList
;
926 al::vector
<ContextRef
> ContextList
;
928 std::recursive_mutex ListLock
;
931 void alc_initconfig(void)
933 if(auto loglevel
= al::getenv("ALSOFT_LOGLEVEL"))
935 long lvl
= strtol(loglevel
->c_str(), nullptr, 0);
936 if(lvl
>= NoLog
&& lvl
<= LogRef
)
937 gLogLevel
= static_cast<LogLevel
>(lvl
);
940 if(auto logfile
= al::getenv("ALSOFT_LOGFILE"))
943 std::wstring wname
{utf8_to_wstr(logfile
->c_str())};
944 FILE *logf
{_wfopen(wname
.c_str(), L
"wt")};
946 FILE *logf
{fopen(logfile
->c_str(), "wt")};
948 if(logf
) gLogFile
= logf
;
949 else ERR("Failed to open log file '%s'\n", logfile
->c_str());
952 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
, ALSOFT_GIT_COMMIT_HASH
,
956 if(std::begin(BackendList
) == BackendListEnd
)
960 const al::span
<const BackendInfo
> infos
{std::begin(BackendList
), BackendListEnd
};
961 names
+= infos
[0].name
;
962 for(const auto &backend
: infos
.subspan(1))
965 names
+= backend
.name
;
968 TRACE("Supported backends: %s\n", names
.c_str());
972 if(auto suspendmode
= al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
974 if(strcasecmp(suspendmode
->c_str(), "ignore") == 0)
976 SuspendDefers
= false;
977 TRACE("Selected context suspend behavior, \"ignore\"\n");
980 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode
->c_str());
984 #if defined(HAVE_SSE4_1)
985 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
986 #elif defined(HAVE_SSE3)
987 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
988 #elif defined(HAVE_SSE2)
989 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
990 #elif defined(HAVE_SSE)
991 capfilter
|= CPU_CAP_SSE
;
994 capfilter
|= CPU_CAP_NEON
;
996 if(auto cpuopt
= ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
998 const char *str
{cpuopt
->c_str()};
999 if(strcasecmp(str
, "all") == 0)
1003 const char *next
= str
;
1006 while(isspace(str
[0]))
1008 next
= strchr(str
, ',');
1010 if(!str
[0] || str
[0] == ',')
1013 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1014 while(len
> 0 && isspace(str
[len
-1]))
1016 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
1017 capfilter
&= ~CPU_CAP_SSE
;
1018 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
1019 capfilter
&= ~CPU_CAP_SSE2
;
1020 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
1021 capfilter
&= ~CPU_CAP_SSE3
;
1022 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
1023 capfilter
&= ~CPU_CAP_SSE4_1
;
1024 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
1025 capfilter
&= ~CPU_CAP_NEON
;
1027 WARN("Invalid CPU extension \"%s\"\n", str
);
1031 FillCPUCaps(capfilter
);
1034 #define DEF_MIXER_PRIO 1
1036 #define DEF_MIXER_PRIO 0
1038 RTPrioLevel
= ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO
);
1039 #undef DEF_MIXER_PRIO
1044 auto traperr
= al::getenv("ALSOFT_TRAP_ERROR");
1045 if(traperr
&& (strcasecmp(traperr
->c_str(), "true") == 0
1046 || strtol(traperr
->c_str(), nullptr, 0) == 1))
1049 TrapALCError
= true;
1053 traperr
= al::getenv("ALSOFT_TRAP_AL_ERROR");
1055 TrapALError
= strcasecmp(traperr
->c_str(), "true") == 0
1056 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1058 TrapALError
= !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1060 traperr
= al::getenv("ALSOFT_TRAP_ALC_ERROR");
1062 TrapALCError
= strcasecmp(traperr
->c_str(), "true") == 0
1063 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1065 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1068 if(auto boostopt
= ConfigValueFloat(nullptr, "reverb", "boost"))
1070 const float valf
{std::isfinite(*boostopt
) ? clampf(*boostopt
, -24.0f
, 24.0f
) : 0.0f
};
1071 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1074 auto devopt
= al::getenv("ALSOFT_DRIVERS");
1075 if(devopt
|| (devopt
=ConfigValueStr(nullptr, nullptr, "drivers")))
1077 auto backendlist_cur
= std::begin(BackendList
);
1080 const char *next
{devopt
->c_str()};
1082 const char *devs
{next
};
1083 while(isspace(devs
[0]))
1085 next
= strchr(devs
, ',');
1087 const bool delitem
{devs
[0] == '-'};
1088 if(devs
[0] == '-') devs
++;
1090 if(!devs
[0] || devs
[0] == ',')
1097 size_t len
{next
? (static_cast<size_t>(next
-devs
)) : strlen(devs
)};
1098 while(len
> 0 && isspace(devs
[len
-1])) --len
;
1100 /* HACK: For backwards compatibility, convert backend references of
1101 * mmdevapi to wasapi. This should eventually be removed.
1103 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1110 auto find_backend
= [devs
,len
](const BackendInfo
&backend
) -> bool
1111 { return len
== strlen(backend
.name
) && strncmp(backend
.name
, devs
, len
) == 0; };
1112 auto this_backend
= std::find_if(std::begin(BackendList
), BackendListEnd
,
1115 if(this_backend
== BackendListEnd
)
1119 BackendListEnd
= std::move(this_backend
+1, BackendListEnd
, this_backend
);
1121 backendlist_cur
= std::rotate(backendlist_cur
, this_backend
, this_backend
+1);
1125 BackendListEnd
= backendlist_cur
;
1128 auto init_backend
= [](BackendInfo
&backend
) -> bool
1130 if(PlaybackFactory
&& CaptureFactory
)
1133 BackendFactory
&factory
= backend
.getFactory();
1136 WARN("Failed to initialize backend \"%s\"\n", backend
.name
);
1140 TRACE("Initialized backend \"%s\"\n", backend
.name
);
1141 if(!PlaybackFactory
&& factory
.querySupport(BackendType::Playback
))
1143 PlaybackFactory
= &factory
;
1144 TRACE("Added \"%s\" for playback\n", backend
.name
);
1146 if(!CaptureFactory
&& factory
.querySupport(BackendType::Capture
))
1148 CaptureFactory
= &factory
;
1149 TRACE("Added \"%s\" for capture\n", backend
.name
);
1153 BackendListEnd
= std::remove_if(std::begin(BackendList
), BackendListEnd
, init_backend
);
1155 LoopbackBackendFactory::getFactory().init();
1157 if(!PlaybackFactory
)
1158 WARN("No playback backend available!\n");
1160 WARN("No capture backend available!\n");
1162 if(auto exclopt
= ConfigValueStr(nullptr, nullptr, "excludefx"))
1164 const char *next
{exclopt
->c_str()};
1166 const char *str
{next
};
1167 next
= strchr(str
, ',');
1169 if(!str
[0] || next
== str
)
1172 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1173 for(const EffectList
&effectitem
: gEffectList
)
1175 if(len
== strlen(effectitem
.name
) &&
1176 strncmp(effectitem
.name
, str
, len
) == 0)
1177 DisabledEffects
[effectitem
.type
] = AL_TRUE
;
1182 InitEffect(&DefaultEffect
);
1183 auto defrevopt
= al::getenv("ALSOFT_DEFAULT_REVERB");
1184 if(defrevopt
|| (defrevopt
=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1185 LoadReverbPreset(defrevopt
->c_str(), &DefaultEffect
);
1187 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1190 /************************************************
1191 * Device enumeration
1192 ************************************************/
1193 void ProbeAllDevicesList()
1197 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1198 alcAllDevicesList
.clear();
1200 PlaybackFactory
->probe(DevProbe::Playback
, &alcAllDevicesList
);
1202 void ProbeCaptureDeviceList()
1206 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1207 alcCaptureDeviceList
.clear();
1209 CaptureFactory
->probe(DevProbe::Capture
, &alcCaptureDeviceList
);
1214 /* Mixing thread piority level */
1217 FILE *gLogFile
{stderr
};
1219 LogLevel gLogLevel
{LogWarning
};
1221 LogLevel gLogLevel
{LogError
};
1224 /************************************************
1225 * Library initialization
1226 ************************************************/
1227 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1228 BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID
/*reserved*/)
1232 case DLL_PROCESS_ATTACH
:
1233 /* Pin the DLL so we won't get unloaded until the process terminates */
1234 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
1235 reinterpret_cast<WCHAR
*>(module
), &module
);
1242 /************************************************
1243 * Device format information
1244 ************************************************/
1245 const ALCchar
*DevFmtTypeString(DevFmtType type
) noexcept
1249 case DevFmtByte
: return "Signed Byte";
1250 case DevFmtUByte
: return "Unsigned Byte";
1251 case DevFmtShort
: return "Signed Short";
1252 case DevFmtUShort
: return "Unsigned Short";
1253 case DevFmtInt
: return "Signed Int";
1254 case DevFmtUInt
: return "Unsigned Int";
1255 case DevFmtFloat
: return "Float";
1257 return "(unknown type)";
1259 const ALCchar
*DevFmtChannelsString(DevFmtChannels chans
) noexcept
1263 case DevFmtMono
: return "Mono";
1264 case DevFmtStereo
: return "Stereo";
1265 case DevFmtQuad
: return "Quadraphonic";
1266 case DevFmtX51
: return "5.1 Surround";
1267 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1268 case DevFmtX61
: return "6.1 Surround";
1269 case DevFmtX71
: return "7.1 Surround";
1270 case DevFmtAmbi3D
: return "Ambisonic 3D";
1272 return "(unknown channels)";
1275 ALuint
BytesFromDevFmt(DevFmtType type
) noexcept
1279 case DevFmtByte
: return sizeof(ALbyte
);
1280 case DevFmtUByte
: return sizeof(ALubyte
);
1281 case DevFmtShort
: return sizeof(ALshort
);
1282 case DevFmtUShort
: return sizeof(ALushort
);
1283 case DevFmtInt
: return sizeof(ALint
);
1284 case DevFmtUInt
: return sizeof(ALuint
);
1285 case DevFmtFloat
: return sizeof(ALfloat
);
1289 ALuint
ChannelsFromDevFmt(DevFmtChannels chans
, ALuint ambiorder
) noexcept
1293 case DevFmtMono
: return 1;
1294 case DevFmtStereo
: return 2;
1295 case DevFmtQuad
: return 4;
1296 case DevFmtX51
: return 6;
1297 case DevFmtX51Rear
: return 6;
1298 case DevFmtX61
: return 7;
1299 case DevFmtX71
: return 8;
1300 case DevFmtAmbi3D
: return (ambiorder
+1) * (ambiorder
+1);
1305 struct DevFmtPair
{ DevFmtChannels chans
; DevFmtType type
; };
1306 static al::optional
<DevFmtPair
> DecomposeDevFormat(ALenum format
)
1308 static const struct {
1310 DevFmtChannels channels
;
1313 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1314 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1315 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1317 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1318 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1319 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1321 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1322 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1323 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1325 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1326 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1327 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1329 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1330 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1331 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1333 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1334 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1335 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1338 for(const auto &item
: list
)
1340 if(item
.format
== format
)
1341 return al::make_optional(DevFmtPair
{item
.channels
, item
.type
});
1347 static ALCboolean
IsValidALCType(ALCenum type
)
1352 case ALC_UNSIGNED_BYTE_SOFT
:
1353 case ALC_SHORT_SOFT
:
1354 case ALC_UNSIGNED_SHORT_SOFT
:
1356 case ALC_UNSIGNED_INT_SOFT
:
1357 case ALC_FLOAT_SOFT
:
1363 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1368 case ALC_STEREO_SOFT
:
1370 case ALC_5POINT1_SOFT
:
1371 case ALC_6POINT1_SOFT
:
1372 case ALC_7POINT1_SOFT
:
1373 case ALC_BFORMAT3D_SOFT
:
1379 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1390 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1402 /************************************************
1403 * Miscellaneous ALC helpers
1404 ************************************************/
1406 /* SetDefaultWFXChannelOrder
1408 * Sets the default channel order used by WaveFormatEx.
1410 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1412 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1414 switch(device
->FmtChans
)
1417 device
->RealOut
.ChannelIndex
[FrontCenter
] = 0;
1420 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1421 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1424 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1425 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1426 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1427 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1430 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1431 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1432 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1433 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1434 device
->RealOut
.ChannelIndex
[SideLeft
] = 4;
1435 device
->RealOut
.ChannelIndex
[SideRight
] = 5;
1438 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1439 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1440 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1441 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1442 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1443 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1446 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1447 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1448 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1449 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1450 device
->RealOut
.ChannelIndex
[BackCenter
] = 4;
1451 device
->RealOut
.ChannelIndex
[SideLeft
] = 5;
1452 device
->RealOut
.ChannelIndex
[SideRight
] = 6;
1455 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1456 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1457 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1458 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1459 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1460 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1461 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1462 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1465 device
->RealOut
.ChannelIndex
[Aux0
] = 0;
1466 if(device
->mAmbiOrder
> 0)
1468 device
->RealOut
.ChannelIndex
[Aux1
] = 1;
1469 device
->RealOut
.ChannelIndex
[Aux2
] = 2;
1470 device
->RealOut
.ChannelIndex
[Aux3
] = 3;
1472 if(device
->mAmbiOrder
> 1)
1474 device
->RealOut
.ChannelIndex
[Aux4
] = 4;
1475 device
->RealOut
.ChannelIndex
[Aux5
] = 5;
1476 device
->RealOut
.ChannelIndex
[Aux6
] = 6;
1477 device
->RealOut
.ChannelIndex
[Aux7
] = 7;
1478 device
->RealOut
.ChannelIndex
[Aux8
] = 8;
1480 if(device
->mAmbiOrder
> 2)
1482 device
->RealOut
.ChannelIndex
[Aux9
] = 9;
1483 device
->RealOut
.ChannelIndex
[Aux10
] = 10;
1484 device
->RealOut
.ChannelIndex
[Aux11
] = 11;
1485 device
->RealOut
.ChannelIndex
[Aux12
] = 12;
1486 device
->RealOut
.ChannelIndex
[Aux13
] = 13;
1487 device
->RealOut
.ChannelIndex
[Aux14
] = 14;
1488 device
->RealOut
.ChannelIndex
[Aux15
] = 15;
1494 /* SetDefaultChannelOrder
1496 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1498 void SetDefaultChannelOrder(ALCdevice
*device
)
1500 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1502 switch(device
->FmtChans
)
1505 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1506 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1507 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1508 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1509 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1510 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1513 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1514 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1515 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1516 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1517 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1518 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1519 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1520 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1523 /* Same as WFX order */
1530 SetDefaultWFXChannelOrder(device
);
1536 void ALCcontext::processUpdates()
1538 std::lock_guard
<std::mutex
> _
{mPropLock
};
1539 if(mDeferUpdates
.exchange(false))
1541 /* Tell the mixer to stop applying updates, then wait for any active
1542 * updating to finish, before providing updates.
1544 mHoldUpdates
.store(true, std::memory_order_release
);
1545 while((mUpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1546 std::this_thread::yield();
1548 if(!mPropsClean
.test_and_set(std::memory_order_acq_rel
))
1549 UpdateContextProps(this);
1550 if(!mListener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1551 UpdateListenerProps(this);
1552 UpdateAllEffectSlotProps(this);
1553 UpdateAllSourceProps(this);
1555 /* Now with all updates declared, let the mixer continue applying them
1556 * so they all happen at once.
1558 mHoldUpdates
.store(false, std::memory_order_release
);
1565 * Stores the latest ALC device error
1567 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1569 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1573 /* DebugBreak() will cause an exception if there is no debugger */
1574 if(IsDebuggerPresent())
1576 #elif defined(SIGTRAP)
1582 device
->LastError
.store(errorCode
);
1584 LastNullDeviceError
.store(errorCode
);
1588 static std::unique_ptr
<Compressor
> CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1590 return CompressorInit(static_cast<ALuint
>(device
->RealOut
.Buffer
.size()), device
->Frequency
,
1591 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
, 0.0f
, 0.0f
, threshold
,
1592 INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1597 * Updates the device's base clock time with however many samples have been
1598 * done. This is used so frequency changes on the device don't cause the time
1599 * to jump forward or back. Must not be called while the device is running/
1602 static inline void UpdateClockBase(ALCdevice
*device
)
1604 IncrementRef(device
->MixCount
);
1605 device
->ClockBase
+= nanoseconds
{seconds
{device
->SamplesDone
}} / device
->Frequency
;
1606 device
->SamplesDone
= 0;
1607 IncrementRef(device
->MixCount
);
1610 /* UpdateDeviceParams
1612 * Updates device parameters according to the attribute list (caller is
1613 * responsible for holding the list lock).
1615 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1617 HrtfRequestMode hrtf_userreq
{Hrtf_Default
};
1618 HrtfRequestMode hrtf_appreq
{Hrtf_Default
};
1619 ALCenum gainLimiter
{device
->LimiterState
};
1620 const ALCuint old_sends
{device
->NumAuxSends
};
1621 ALCuint new_sends
{device
->NumAuxSends
};
1622 DevFmtChannels oldChans
;
1624 ALboolean update_failed
;
1625 ALCsizei hrtf_id
{-1};
1628 if((!attrList
|| !attrList
[0]) && device
->Type
== Loopback
)
1630 WARN("Missing attributes for loopback device\n");
1631 return ALC_INVALID_VALUE
;
1634 // Check for attributes
1635 if(attrList
&& attrList
[0])
1637 ALCenum alayout
{AL_NONE
};
1638 ALCenum ascale
{AL_NONE
};
1639 ALCenum schans
{AL_NONE
};
1640 ALCenum stype
{AL_NONE
};
1641 ALCsizei attrIdx
{0};
1645 ALuint numMono
{device
->NumMonoSources
};
1646 ALuint numStereo
{device
->NumStereoSources
};
1647 ALuint numSends
{old_sends
};
1649 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1650 while(attrList
[attrIdx
])
1652 switch(attrList
[attrIdx
])
1654 case ALC_FORMAT_CHANNELS_SOFT
:
1655 schans
= attrList
[attrIdx
+ 1];
1656 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1659 case ALC_FORMAT_TYPE_SOFT
:
1660 stype
= attrList
[attrIdx
+ 1];
1661 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1665 freq
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1666 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1669 case ALC_AMBISONIC_LAYOUT_SOFT
:
1670 alayout
= attrList
[attrIdx
+ 1];
1671 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1674 case ALC_AMBISONIC_SCALING_SOFT
:
1675 ascale
= attrList
[attrIdx
+ 1];
1676 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1679 case ALC_AMBISONIC_ORDER_SOFT
:
1680 aorder
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1681 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1684 case ALC_MONO_SOURCES
:
1685 numMono
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1686 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1687 if(numMono
> INT_MAX
) numMono
= 0;
1690 case ALC_STEREO_SOURCES
:
1691 numStereo
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1692 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1693 if(numStereo
> INT_MAX
) numStereo
= 0;
1696 case ALC_MAX_AUXILIARY_SENDS
:
1697 numSends
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1698 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1699 if(numSends
> INT_MAX
) numSends
= 0;
1700 else numSends
= minu(numSends
, MAX_SENDS
);
1704 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1705 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1706 hrtf_appreq
= Hrtf_Disable
;
1707 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1708 hrtf_appreq
= Hrtf_Enable
;
1710 hrtf_appreq
= Hrtf_Default
;
1713 case ALC_HRTF_ID_SOFT
:
1714 hrtf_id
= attrList
[attrIdx
+ 1];
1715 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1718 case ALC_OUTPUT_LIMITER_SOFT
:
1719 gainLimiter
= attrList
[attrIdx
+ 1];
1720 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1724 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1725 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1733 const bool loopback
{device
->Type
== Loopback
};
1736 if(!schans
|| !stype
|| !freq
)
1738 WARN("Missing format for loopback device\n");
1739 return ALC_INVALID_VALUE
;
1741 if(!IsValidALCChannels(schans
) || !IsValidALCType(stype
) || freq
< MIN_OUTPUT_RATE
)
1742 return ALC_INVALID_VALUE
;
1743 if(schans
== ALC_BFORMAT3D_SOFT
)
1745 if(!alayout
|| !ascale
|| !aorder
)
1747 WARN("Missing ambisonic info for loopback device\n");
1748 return ALC_INVALID_VALUE
;
1750 if(!IsValidAmbiLayout(alayout
) || !IsValidAmbiScaling(ascale
))
1751 return ALC_INVALID_VALUE
;
1752 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1753 return ALC_INVALID_VALUE
;
1754 if((alayout
== ALC_FUMA_SOFT
|| ascale
== ALC_FUMA_SOFT
) && aorder
> 3)
1755 return ALC_INVALID_VALUE
;
1759 /* If a context is already running on the device, stop playback so the
1760 * device attributes can be updated.
1762 if(device
->Flags
.get
<DeviceRunning
>())
1763 device
->Backend
->stop();
1764 device
->Flags
.unset
<DeviceRunning
>();
1766 UpdateClockBase(device
);
1768 const char *devname
{nullptr};
1771 devname
= device
->DeviceName
.c_str();
1773 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
1774 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
1775 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
1777 freq
= ConfigValueUInt(devname
, nullptr, "frequency").value_or(freq
);
1779 device
->Flags
.unset
<FrequencyRequest
>();
1782 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1784 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) /
1786 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) /
1789 device
->Frequency
= freq
;
1790 device
->Flags
.set
<FrequencyRequest
>();
1793 if(auto persizeopt
= ConfigValueUInt(devname
, nullptr, "period_size"))
1794 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
1796 if(auto peropt
= ConfigValueUInt(devname
, nullptr, "periods"))
1797 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
1799 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
1803 device
->Frequency
= freq
;
1804 device
->FmtChans
= static_cast<DevFmtChannels
>(schans
);
1805 device
->FmtType
= static_cast<DevFmtType
>(stype
);
1806 if(schans
== ALC_BFORMAT3D_SOFT
)
1808 device
->mAmbiOrder
= aorder
;
1809 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1810 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1814 if(numMono
> INT_MAX
-numStereo
)
1815 numMono
= INT_MAX
-numStereo
;
1816 numMono
+= numStereo
;
1817 if(auto srcsopt
= ConfigValueUInt(devname
, nullptr, "sources"))
1819 if(*srcsopt
<= 0) numMono
= 256;
1820 else numMono
= *srcsopt
;
1823 numMono
= maxu(numMono
, 256);
1824 numStereo
= minu(numStereo
, numMono
);
1825 numMono
-= numStereo
;
1826 device
->SourcesMax
= numMono
+ numStereo
;
1828 device
->NumMonoSources
= numMono
;
1829 device
->NumStereoSources
= numStereo
;
1831 if(auto sendsopt
= ConfigValueInt(devname
, nullptr, "sends"))
1832 new_sends
= minu(numSends
, static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
1834 new_sends
= numSends
;
1837 if(device
->Flags
.get
<DeviceRunning
>())
1838 return ALC_NO_ERROR
;
1840 device
->AvgSpeakerDist
= 0.0f
;
1841 device
->Uhj_Encoder
= nullptr;
1842 device
->AmbiDecoder
= nullptr;
1843 device
->Bs2b
= nullptr;
1844 device
->PostProcess
= nullptr;
1846 device
->Stablizer
= nullptr;
1847 device
->Limiter
= nullptr;
1848 device
->ChannelDelay
.clear();
1850 device
->Dry
.AmbiMap
.fill(BFChannelConfig
{});
1851 device
->Dry
.Buffer
= {};
1852 std::fill(std::begin(device
->NumChannelsPerOrder
), std::end(device
->NumChannelsPerOrder
), 0u);
1853 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1854 device
->RealOut
.Buffer
= {};
1855 device
->MixBuffer
.clear();
1856 device
->MixBuffer
.shrink_to_fit();
1858 UpdateClockBase(device
);
1859 device
->FixedLatency
= nanoseconds::zero();
1861 device
->DitherDepth
= 0.0f
;
1862 device
->DitherSeed
= DITHER_RNG_SEED
;
1864 /*************************************************************************
1865 * Update device format request if HRTF is requested
1867 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1868 if(device
->Type
!= Loopback
)
1870 if(auto hrtfopt
= ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf"))
1872 const char *hrtf
{hrtfopt
->c_str()};
1873 if(strcasecmp(hrtf
, "true") == 0)
1874 hrtf_userreq
= Hrtf_Enable
;
1875 else if(strcasecmp(hrtf
, "false") == 0)
1876 hrtf_userreq
= Hrtf_Disable
;
1877 else if(strcasecmp(hrtf
, "auto") != 0)
1878 ERR("Unexpected hrtf value: %s\n", hrtf
);
1881 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1883 HrtfEntry
*hrtf
{nullptr};
1884 if(device
->HrtfList
.empty())
1885 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
1886 if(!device
->HrtfList
.empty())
1888 if(hrtf_id
>= 0 && static_cast<ALuint
>(hrtf_id
) < device
->HrtfList
.size())
1889 hrtf
= GetLoadedHrtf(device
->HrtfList
[static_cast<ALuint
>(hrtf_id
)].hrtf
);
1891 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
1896 device
->FmtChans
= DevFmtStereo
;
1897 device
->Frequency
= hrtf
->sampleRate
;
1898 device
->Flags
.set
<ChannelsRequest
, FrequencyRequest
>();
1899 if(HrtfEntry
*oldhrtf
{device
->mHrtf
})
1901 device
->mHrtf
= hrtf
;
1905 hrtf_userreq
= Hrtf_Default
;
1906 hrtf_appreq
= Hrtf_Disable
;
1907 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
1912 oldFreq
= device
->Frequency
;
1913 oldChans
= device
->FmtChans
;
1914 oldType
= device
->FmtType
;
1916 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1917 device
->Flags
.get
<ChannelsRequest
>()?"*":"", DevFmtChannelsString(device
->FmtChans
),
1918 device
->Flags
.get
<SampleTypeRequest
>()?"*":"", DevFmtTypeString(device
->FmtType
),
1919 device
->Flags
.get
<FrequencyRequest
>()?"*":"", device
->Frequency
,
1920 device
->UpdateSize
, device
->BufferSize
);
1923 if(device
->Backend
->reset() == ALC_FALSE
)
1924 return ALC_INVALID_DEVICE
;
1926 catch(std::exception
&e
) {
1927 ERR("Device reset failed: %s\n", e
.what());
1928 return ALC_INVALID_DEVICE
;
1931 if(device
->FmtChans
!= oldChans
&& device
->Flags
.get
<ChannelsRequest
>())
1933 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1934 DevFmtChannelsString(device
->FmtChans
));
1935 device
->Flags
.unset
<ChannelsRequest
>();
1937 if(device
->FmtType
!= oldType
&& device
->Flags
.get
<SampleTypeRequest
>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1940 DevFmtTypeString(device
->FmtType
));
1941 device
->Flags
.unset
<SampleTypeRequest
>();
1943 if(device
->Frequency
!= oldFreq
&& device
->Flags
.get
<FrequencyRequest
>())
1945 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1946 device
->Flags
.unset
<FrequencyRequest
>();
1949 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1950 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
1951 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
1953 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
1955 device
->NumAuxSends
= new_sends
;
1956 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1957 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
1958 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
1960 /* Enable the stablizer only for formats that have front-left, front-right,
1961 * and front-center outputs.
1963 switch(device
->FmtChans
)
1969 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "front-stablizer", 0))
1971 auto stablizer
= al::make_unique
<FrontStablizer
>();
1972 /* Initialize band-splitting filters for the front-left and front-
1973 * right channels, with a crossover at 5khz (could be higher).
1975 const ALfloat scale
{5000.0f
/ static_cast<ALfloat
>(device
->Frequency
)};
1977 stablizer
->LFilter
.init(scale
);
1978 stablizer
->RFilter
= stablizer
->LFilter
;
1980 device
->Stablizer
= std::move(stablizer
);
1981 /* NOTE: Don't know why this has to be "copied" into a local static
1982 * constexpr variable to avoid a reference on
1983 * FrontStablizer::DelayLength...
1985 static constexpr size_t StablizerDelay
{FrontStablizer::DelayLength
};
1986 device
->FixedLatency
+= nanoseconds
{seconds
{StablizerDelay
}} / device
->Frequency
;
1995 TRACE("Front stablizer %s\n", device
->Stablizer
? "enabled" : "disabled");
1997 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2000 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth").value_or(0)};
2003 switch(device
->FmtType
)
2022 depth
= clampi(depth
, 2, 24);
2023 device
->DitherDepth
= std::pow(2.0f
, static_cast<ALfloat
>(depth
-1));
2026 if(!(device
->DitherDepth
> 0.0f
))
2027 TRACE("Dithering disabled\n");
2029 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2030 device
->DitherDepth
);
2032 device
->LimiterState
= gainLimiter
;
2033 if(auto limopt
= ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter"))
2034 gainLimiter
= *limopt
? ALC_TRUE
: ALC_FALSE
;
2036 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2037 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2038 * output (where samples must be clamped), and don't for floating-point
2039 * (which can take unclamped samples).
2041 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2043 switch(device
->FmtType
)
2051 gainLimiter
= ALC_TRUE
;
2054 gainLimiter
= ALC_FALSE
;
2058 if(gainLimiter
== ALC_FALSE
)
2059 TRACE("Output limiter disabled\n");
2062 ALfloat thrshld
= 1.0f
;
2063 switch(device
->FmtType
)
2067 thrshld
= 127.0f
/ 128.0f
;
2071 thrshld
= 32767.0f
/ 32768.0f
;
2078 if(device
->DitherDepth
> 0.0f
)
2079 thrshld
-= 1.0f
/ device
->DitherDepth
;
2081 const float thrshld_dB
{std::log10(thrshld
) * 20.0f
};
2082 auto limiter
= CreateDeviceLimiter(device
, thrshld_dB
);
2083 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2084 device
->FixedLatency
+= nanoseconds
{seconds
{limiter
->getLookAhead()}} / device
->Frequency
;
2085 device
->Limiter
= std::move(limiter
);
2086 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB
);
2089 TRACE("Fixed device latency: %" PRId64
"ns\n", int64_t{device
->FixedLatency
.count()});
2091 /* Need to delay returning failure until replacement Send arrays have been
2092 * allocated with the appropriate size.
2094 update_failed
= AL_FALSE
;
2095 FPUCtl mixer_mode
{};
2096 for(ALCcontext
*context
: *device
->mContexts
.load())
2098 if(context
->mDefaultSlot
)
2100 ALeffectslot
*slot
= context
->mDefaultSlot
.get();
2101 aluInitEffectPanning(slot
, device
);
2103 EffectState
*state
{slot
->Effect
.State
};
2104 state
->mOutTarget
= device
->Dry
.Buffer
;
2105 if(state
->deviceUpdate(device
) == AL_FALSE
)
2106 update_failed
= AL_TRUE
;
2108 UpdateEffectSlotProps(slot
, context
);
2111 std::unique_lock
<std::mutex
> proplock
{context
->mPropLock
};
2112 std::unique_lock
<std::mutex
> slotlock
{context
->mEffectSlotLock
};
2113 for(auto &sublist
: context
->mEffectSlotList
)
2115 uint64_t usemask
= ~sublist
.FreeMask
;
2118 ALsizei idx
= CTZ64(usemask
);
2119 ALeffectslot
*slot
= sublist
.EffectSlots
+ idx
;
2121 usemask
&= ~(1_u64
<< idx
);
2123 aluInitEffectPanning(slot
, device
);
2125 EffectState
*state
{slot
->Effect
.State
};
2126 state
->mOutTarget
= device
->Dry
.Buffer
;
2127 if(state
->deviceUpdate(device
) == AL_FALSE
)
2128 update_failed
= AL_TRUE
;
2130 UpdateEffectSlotProps(slot
, context
);
2135 std::unique_lock
<std::mutex
> srclock
{context
->mSourceLock
};
2136 for(auto &sublist
: context
->mSourceList
)
2138 uint64_t usemask
= ~sublist
.FreeMask
;
2141 ALsizei idx
= CTZ64(usemask
);
2142 ALsource
*source
= sublist
.Sources
+ idx
;
2144 usemask
&= ~(1_u64
<< idx
);
2146 if(old_sends
!= device
->NumAuxSends
)
2148 if(source
->Send
.size() > static_cast<ALuint
>(device
->NumAuxSends
))
2149 std::for_each(source
->Send
.begin()+device
->NumAuxSends
, source
->Send
.end(),
2150 [](ALsource::SendData
&send
) -> void
2153 DecrementRef(send
.Slot
->ref
);
2154 send
.Slot
= nullptr;
2157 source
->Send
.resize(static_cast<ALuint
>(device
->NumAuxSends
),
2158 ALsource::SendData
{nullptr, 1.0f
, 1.0f
, LOWPASSFREQREF
, 1.0f
, HIGHPASSFREQREF
});
2159 source
->Send
.shrink_to_fit();
2162 source
->PropsClean
.clear(std::memory_order_release
);
2166 /* Clear any pre-existing voice property structs, in case the number of
2167 * auxiliary sends is changing. Active sources will have updates
2168 * respecified in UpdateAllSourceProps.
2170 ALvoiceProps
*vprops
{context
->mFreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2173 ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2178 if(device
->NumAuxSends
< old_sends
)
2180 const ALuint num_sends
{device
->NumAuxSends
};
2181 /* Clear extraneous property set sends. */
2182 auto clear_sends
= [num_sends
](ALvoice
&voice
) -> void
2184 std::fill(std::begin(voice
.mProps
.Send
)+num_sends
, std::end(voice
.mProps
.Send
),
2185 ALvoiceProps::SendData
{});
2187 std::fill(voice
.mSend
.begin()+num_sends
, voice
.mSend
.end(), ALvoice::SendData
{});
2188 auto clear_chan_sends
= [num_sends
](ALvoice::ChannelData
&chandata
) -> void
2190 std::fill(chandata
.mWetParams
.begin()+num_sends
, chandata
.mWetParams
.end(),
2193 std::for_each(voice
.mChans
.begin(), voice
.mChans
.end(), clear_chan_sends
);
2195 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), clear_sends
);
2197 auto reset_voice
= [device
](ALvoice
&voice
) -> void
2199 delete voice
.mUpdate
.exchange(nullptr, std::memory_order_acq_rel
);
2201 /* Force the voice to stopped if it was stopping. */
2202 ALvoice::State vstate
{ALvoice::Stopping
};
2203 voice
.mPlayState
.compare_exchange_strong(vstate
, ALvoice::Stopped
,
2204 std::memory_order_acquire
, std::memory_order_acquire
);
2205 if(voice
.mSourceID
.load(std::memory_order_relaxed
) == 0u)
2208 if(device
->AvgSpeakerDist
> 0.0f
)
2210 /* Reinitialize the NFC filters for new parameters. */
2211 const ALfloat w1
{SPEEDOFSOUNDMETRESPERSEC
/
2212 (device
->AvgSpeakerDist
* device
->Frequency
)};
2213 auto init_nfc
= [w1
](ALvoice::ChannelData
&chandata
) -> void
2214 { chandata
.mDryParams
.NFCtrlFilter
.init(w1
); };
2215 std::for_each(voice
.mChans
.begin(), voice
.mChans
.begin()+voice
.mNumChannels
,
2219 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), reset_voice
);
2222 context
->mPropsClean
.test_and_set(std::memory_order_release
);
2223 UpdateContextProps(context
);
2224 context
->mListener
.PropsClean
.test_and_set(std::memory_order_release
);
2225 UpdateListenerProps(context
);
2226 UpdateAllSourceProps(context
);
2230 return ALC_INVALID_DEVICE
;
2232 if(!device
->Flags
.get
<DevicePaused
>())
2234 if(device
->Backend
->start() == ALC_FALSE
)
2235 return ALC_INVALID_DEVICE
;
2236 device
->Flags
.set
<DeviceRunning
>();
2239 return ALC_NO_ERROR
;
2243 ALCdevice::ALCdevice(DeviceType type
) : Type
{type
}, mContexts
{&EmptyContextArray
}
2247 /* ALCdevice::~ALCdevice
2249 * Frees the device structure, and destroys any objects the app failed to
2250 * delete. Called once there's no more references on the device.
2252 ALCdevice::~ALCdevice()
2254 TRACE("Freeing device %p\n", this);
2258 size_t count
{std::accumulate(BufferList
.cbegin(), BufferList
.cend(), size_t{0u},
2259 [](size_t cur
, const BufferSubList
&sublist
) noexcept
-> size_t
2260 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2263 WARN("%zu Buffer%s not deleted\n", count
, (count
==1)?"":"s");
2265 count
= std::accumulate(EffectList
.cbegin(), EffectList
.cend(), size_t{0u},
2266 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
2267 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2270 WARN("%zu Effect%s not deleted\n", count
, (count
==1)?"":"s");
2272 count
= std::accumulate(FilterList
.cbegin(), FilterList
.cend(), size_t{0u},
2273 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
2274 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2277 WARN("%zu Filter%s not deleted\n", count
, (count
==1)?"":"s");
2283 auto *oldarray
= mContexts
.exchange(nullptr, std::memory_order_relaxed
);
2284 if(oldarray
!= &EmptyContextArray
) delete oldarray
;
2290 * Checks if the device handle is valid, and returns a new reference if so.
2292 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2294 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2295 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
);
2296 if(iter
!= DeviceList
.cend() && *iter
== device
)
2302 ALCcontext::ALCcontext(al::intrusive_ptr
<ALCdevice
> device
) : mDevice
{std::move(device
)}
2304 mPropsClean
.test_and_set(std::memory_order_relaxed
);
2307 ALCcontext::~ALCcontext()
2309 TRACE("Freeing context %p\n", this);
2311 ALcontextProps
*cprops
{mUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
2314 TRACE("Freed unapplied context update %p\n", cprops
);
2318 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
2321 ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2326 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
2328 count
= std::accumulate(mSourceList
.cbegin(), mSourceList
.cend(), size_t{0u},
2329 [](size_t cur
, const SourceSubList
&sublist
) noexcept
-> size_t
2330 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2333 WARN("%zu Source%s not deleted\n", count
, (count
==1)?"":"s");
2334 mSourceList
.clear();
2338 ALeffectslotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
2341 ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2342 if(eprops
->State
) eprops
->State
->release();
2347 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2349 delete mActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
);
2350 mDefaultSlot
= nullptr;
2352 count
= std::accumulate(mEffectSlotList
.cbegin(), mEffectSlotList
.cend(), size_t{0u},
2353 [](size_t cur
, const EffectSlotSubList
&sublist
) noexcept
-> size_t
2354 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2357 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count
, (count
==1)?"":"s");
2358 mEffectSlotList
.clear();
2359 mNumEffectSlots
= 0;
2362 ALvoiceProps
*vprops
{mFreeVoiceProps
.exchange(nullptr, std::memory_order_acquire
)};
2365 ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2370 TRACE("Freed %zu voice property object%s\n", count
, (count
==1)?"":"s");
2374 ALlistenerProps
*lprops
{mListener
.Params
.Update
.exchange(nullptr, std::memory_order_relaxed
)};
2377 TRACE("Freed unapplied listener update %p\n", lprops
);
2381 lprops
= mFreeListenerProps
.exchange(nullptr, std::memory_order_acquire
);
2384 ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2389 TRACE("Freed %zu listener property object%s\n", count
, (count
==1)?"":"s");
2394 auto evt_vec
= mAsyncEvents
->getReadVector();
2395 if(evt_vec
.first
.len
> 0)
2397 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.first
.buf
), evt_vec
.first
.len
);
2398 count
+= evt_vec
.first
.len
;
2400 if(evt_vec
.second
.len
> 0)
2402 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.second
.buf
), evt_vec
.second
.len
);
2403 count
+= evt_vec
.second
.len
;
2406 TRACE("Destructed %zu orphaned event%s\n", count
, (count
==1)?"":"s");
2407 mAsyncEvents
->readAdvance(count
);
2411 void ALCcontext::init()
2413 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& mDevice
->Type
== Playback
)
2415 mDefaultSlot
= std::unique_ptr
<ALeffectslot
>{new ALeffectslot
{}};
2416 if(InitEffectSlot(mDefaultSlot
.get()) == AL_NO_ERROR
)
2417 aluInitEffectPanning(mDefaultSlot
.get(), mDevice
.get());
2420 mDefaultSlot
= nullptr;
2421 ERR("Failed to initialize the default effect slot\n");
2425 ALeffectslotArray
*auxslots
;
2427 auxslots
= ALeffectslot::CreatePtrArray(0);
2430 auxslots
= ALeffectslot::CreatePtrArray(1);
2431 (*auxslots
)[0] = mDefaultSlot
.get();
2433 mActiveAuxSlots
.store(auxslots
, std::memory_order_relaxed
);
2435 mExtensionList
= alExtList
;
2438 mListener
.Params
.Matrix
= alu::Matrix::Identity();
2439 mListener
.Params
.Velocity
= alu::Vector
{};
2440 mListener
.Params
.Gain
= mListener
.Gain
;
2441 mListener
.Params
.MetersPerUnit
= mListener
.mMetersPerUnit
;
2442 mListener
.Params
.DopplerFactor
= mDopplerFactor
;
2443 mListener
.Params
.SpeedOfSound
= mSpeedOfSound
* mDopplerVelocity
;
2444 mListener
.Params
.SourceDistanceModel
= mSourceDistanceModel
;
2445 mListener
.Params
.mDistanceModel
= mDistanceModel
;
2448 mAsyncEvents
= CreateRingBuffer(511, sizeof(AsyncEvent
), false);
2449 StartEventThrd(this);
2452 mVoices
.reserve(256);
2456 bool ALCcontext::deinit()
2458 if(LocalContext
.get() == this)
2460 WARN("%p released while current on thread\n", this);
2461 LocalContext
.set(nullptr);
2465 ALCcontext
*origctx
{this};
2466 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2470 /* First make sure this context exists in the device's list. */
2471 auto *oldarray
= mDevice
->mContexts
.load(std::memory_order_acquire
);
2472 if(auto toremove
= static_cast<size_t>(std::count(oldarray
->begin(), oldarray
->end(), this)))
2474 using ContextArray
= al::FlexArray
<ALCcontext
*>;
2475 auto alloc_ctx_array
= [](const size_t count
) -> ContextArray
*
2477 if(count
== 0) return &EmptyContextArray
;
2478 return ContextArray::Create(count
).release();
2480 auto *newarray
= alloc_ctx_array(oldarray
->size() - toremove
);
2482 /* Copy the current/old context handles to the new array, excluding the
2485 std::copy_if(oldarray
->begin(), oldarray
->end(), newarray
->begin(),
2486 std::bind(std::not_equal_to
<ALCcontext
*>{}, _1
, this));
2488 /* Store the new context array in the device. Wait for any current mix
2489 * to finish before deleting the old array.
2491 mDevice
->mContexts
.store(newarray
);
2492 if(oldarray
!= &EmptyContextArray
)
2494 while((mDevice
->MixCount
.load(std::memory_order_acquire
)&1))
2495 std::this_thread::yield();
2499 ret
= !newarray
->empty();
2502 ret
= !oldarray
->empty();
2504 StopEventThrd(this);
2512 * Checks if the given context is valid, returning a new reference to it if so.
2514 static ContextRef
VerifyContext(ALCcontext
*context
)
2516 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2517 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
);
2518 if(iter
!= ContextList
.cend() && *iter
== context
)
2525 * Returns a new reference to the currently active context for this thread.
2527 ContextRef
GetContextRef(void)
2529 ALCcontext
*context
{LocalContext
.get()};
2534 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2535 context
= GlobalContext
.load(std::memory_order_acquire
);
2536 if(context
) context
->add_ref();
2538 return ContextRef
{context
};
2542 /************************************************
2543 * Standard ALC functions
2544 ************************************************/
2548 * Return last ALC generated error code for the given device
2550 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2553 DeviceRef dev
{VerifyDevice(device
)};
2554 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2555 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2560 /* alcSuspendContext
2562 * Suspends updates for the given context
2564 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2570 ContextRef ctx
{VerifyContext(context
)};
2572 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2574 ctx
->deferUpdates();
2578 /* alcProcessContext
2580 * Resumes processing updates for the given context
2582 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2588 ContextRef ctx
{VerifyContext(context
)};
2590 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2592 ctx
->processUpdates();
2599 * Returns information about the device, and error strings
2601 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2604 const ALCchar
*value
= nullptr;
2612 case ALC_INVALID_ENUM
:
2613 value
= alcErrInvalidEnum
;
2616 case ALC_INVALID_VALUE
:
2617 value
= alcErrInvalidValue
;
2620 case ALC_INVALID_DEVICE
:
2621 value
= alcErrInvalidDevice
;
2624 case ALC_INVALID_CONTEXT
:
2625 value
= alcErrInvalidContext
;
2628 case ALC_OUT_OF_MEMORY
:
2629 value
= alcErrOutOfMemory
;
2632 case ALC_DEVICE_SPECIFIER
:
2633 value
= alcDefaultName
;
2636 case ALC_ALL_DEVICES_SPECIFIER
:
2637 if(DeviceRef dev
{VerifyDevice(Device
)})
2638 value
= dev
->DeviceName
.c_str();
2641 ProbeAllDevicesList();
2642 value
= alcAllDevicesList
.c_str();
2646 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2647 if(DeviceRef dev
{VerifyDevice(Device
)})
2648 value
= dev
->DeviceName
.c_str();
2651 ProbeCaptureDeviceList();
2652 value
= alcCaptureDeviceList
.c_str();
2656 /* Default devices are always first in the list */
2657 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2658 value
= alcDefaultName
;
2661 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2662 if(alcAllDevicesList
.empty())
2663 ProbeAllDevicesList();
2665 /* Copy first entry as default. */
2666 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2667 value
= alcDefaultAllDevicesSpecifier
.c_str();
2670 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2671 if(alcCaptureDeviceList
.empty())
2672 ProbeCaptureDeviceList();
2674 /* Copy first entry as default. */
2675 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2676 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2679 case ALC_EXTENSIONS
:
2680 if(VerifyDevice(Device
))
2681 value
= alcExtensionList
;
2683 value
= alcNoDeviceExtList
;
2686 case ALC_HRTF_SPECIFIER_SOFT
:
2687 if(DeviceRef dev
{VerifyDevice(Device
)})
2689 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
2690 value
= (dev
->mHrtf
? dev
->HrtfName
.c_str() : "");
2693 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2697 alcSetError(VerifyDevice(Device
).get(), ALC_INVALID_ENUM
);
2706 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2708 if(device
->Type
== Capture
) return 9;
2709 if(device
->Type
!= Loopback
) return 29;
2710 if(device
->FmtChans
== DevFmtAmbi3D
)
2715 static size_t GetIntegerv(ALCdevice
*device
, ALCenum param
, const al::span
<ALCint
> values
)
2721 alcSetError(device
, ALC_INVALID_VALUE
);
2729 case ALC_MAJOR_VERSION
:
2730 values
[0] = alcMajorVersion
;
2732 case ALC_MINOR_VERSION
:
2733 values
[0] = alcMinorVersion
;
2736 case ALC_ATTRIBUTES_SIZE
:
2737 case ALC_ALL_ATTRIBUTES
:
2741 case ALC_MONO_SOURCES
:
2742 case ALC_STEREO_SOURCES
:
2743 case ALC_CAPTURE_SAMPLES
:
2744 case ALC_FORMAT_CHANNELS_SOFT
:
2745 case ALC_FORMAT_TYPE_SOFT
:
2746 case ALC_AMBISONIC_LAYOUT_SOFT
:
2747 case ALC_AMBISONIC_SCALING_SOFT
:
2748 case ALC_AMBISONIC_ORDER_SOFT
:
2749 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
2750 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2754 alcSetError(nullptr, ALC_INVALID_ENUM
);
2760 if(device
->Type
== Capture
)
2764 case ALC_ATTRIBUTES_SIZE
:
2765 values
[0] = NumAttrsForDevice(device
);
2768 case ALC_ALL_ATTRIBUTES
:
2770 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2771 alcSetError(device
, ALC_INVALID_VALUE
);
2774 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2775 values
[i
++] = ALC_MAJOR_VERSION
;
2776 values
[i
++] = alcMajorVersion
;
2777 values
[i
++] = ALC_MINOR_VERSION
;
2778 values
[i
++] = alcMinorVersion
;
2779 values
[i
++] = ALC_CAPTURE_SAMPLES
;
2780 values
[i
++] = static_cast<int>(device
->Backend
->availableSamples());
2781 values
[i
++] = ALC_CONNECTED
;
2782 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
2787 case ALC_MAJOR_VERSION
:
2788 values
[0] = alcMajorVersion
;
2790 case ALC_MINOR_VERSION
:
2791 values
[0] = alcMinorVersion
;
2794 case ALC_CAPTURE_SAMPLES
:
2796 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2797 values
[0] = static_cast<int>(device
->Backend
->availableSamples());
2803 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2804 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2809 alcSetError(device
, ALC_INVALID_ENUM
);
2817 case ALC_ATTRIBUTES_SIZE
:
2818 values
[0] = NumAttrsForDevice(device
);
2821 case ALC_ALL_ATTRIBUTES
:
2823 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2824 alcSetError(device
, ALC_INVALID_VALUE
);
2827 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2828 values
[i
++] = ALC_MAJOR_VERSION
;
2829 values
[i
++] = alcMajorVersion
;
2830 values
[i
++] = ALC_MINOR_VERSION
;
2831 values
[i
++] = alcMinorVersion
;
2832 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
2833 values
[i
++] = alcEFXMajorVersion
;
2834 values
[i
++] = ALC_EFX_MINOR_VERSION
;
2835 values
[i
++] = alcEFXMinorVersion
;
2837 values
[i
++] = ALC_FREQUENCY
;
2838 values
[i
++] = static_cast<int>(device
->Frequency
);
2839 if(device
->Type
!= Loopback
)
2841 values
[i
++] = ALC_REFRESH
;
2842 values
[i
++] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2844 values
[i
++] = ALC_SYNC
;
2845 values
[i
++] = ALC_FALSE
;
2849 if(device
->FmtChans
== DevFmtAmbi3D
)
2851 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
2852 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
2854 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
2855 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
2857 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
2858 values
[i
++] = static_cast<ALCint
>(device
->mAmbiOrder
);
2861 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2862 values
[i
++] = device
->FmtChans
;
2864 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2865 values
[i
++] = device
->FmtType
;
2868 values
[i
++] = ALC_MONO_SOURCES
;
2869 values
[i
++] = static_cast<int>(device
->NumMonoSources
);
2871 values
[i
++] = ALC_STEREO_SOURCES
;
2872 values
[i
++] = static_cast<int>(device
->NumStereoSources
);
2874 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2875 values
[i
++] = static_cast<ALCint
>(device
->NumAuxSends
);
2877 values
[i
++] = ALC_HRTF_SOFT
;
2878 values
[i
++] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
2880 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
2881 values
[i
++] = device
->HrtfStatus
;
2883 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
2884 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
2886 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
2887 values
[i
++] = MAX_AMBI_ORDER
;
2893 case ALC_MAJOR_VERSION
:
2894 values
[0] = alcMajorVersion
;
2897 case ALC_MINOR_VERSION
:
2898 values
[0] = alcMinorVersion
;
2901 case ALC_EFX_MAJOR_VERSION
:
2902 values
[0] = alcEFXMajorVersion
;
2905 case ALC_EFX_MINOR_VERSION
:
2906 values
[0] = alcEFXMinorVersion
;
2910 values
[0] = static_cast<int>(device
->Frequency
);
2914 if(device
->Type
== Loopback
)
2916 alcSetError(device
, ALC_INVALID_DEVICE
);
2920 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2921 values
[0] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2926 if(device
->Type
== Loopback
)
2928 alcSetError(device
, ALC_INVALID_DEVICE
);
2931 values
[0] = ALC_FALSE
;
2934 case ALC_FORMAT_CHANNELS_SOFT
:
2935 if(device
->Type
!= Loopback
)
2937 alcSetError(device
, ALC_INVALID_DEVICE
);
2940 values
[0] = device
->FmtChans
;
2943 case ALC_FORMAT_TYPE_SOFT
:
2944 if(device
->Type
!= Loopback
)
2946 alcSetError(device
, ALC_INVALID_DEVICE
);
2949 values
[0] = device
->FmtType
;
2952 case ALC_AMBISONIC_LAYOUT_SOFT
:
2953 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2955 alcSetError(device
, ALC_INVALID_DEVICE
);
2958 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
2961 case ALC_AMBISONIC_SCALING_SOFT
:
2962 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2964 alcSetError(device
, ALC_INVALID_DEVICE
);
2967 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
2970 case ALC_AMBISONIC_ORDER_SOFT
:
2971 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2973 alcSetError(device
, ALC_INVALID_DEVICE
);
2976 values
[0] = static_cast<int>(device
->mAmbiOrder
);
2979 case ALC_MONO_SOURCES
:
2980 values
[0] = static_cast<int>(device
->NumMonoSources
);
2983 case ALC_STEREO_SOURCES
:
2984 values
[0] = static_cast<int>(device
->NumStereoSources
);
2987 case ALC_MAX_AUXILIARY_SENDS
:
2988 values
[0] = static_cast<ALCint
>(device
->NumAuxSends
);
2993 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2994 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2999 values
[0] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3002 case ALC_HRTF_STATUS_SOFT
:
3003 values
[0] = device
->HrtfStatus
;
3006 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3008 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3009 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3010 values
[0] = static_cast<ALCint
>(minz(device
->HrtfList
.size(),
3011 std::numeric_limits
<ALCint
>::max()));
3015 case ALC_OUTPUT_LIMITER_SOFT
:
3016 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3019 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3020 values
[0] = MAX_AMBI_ORDER
;
3024 alcSetError(device
, ALC_INVALID_ENUM
);
3031 * Returns information about the device and the version of OpenAL
3033 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3036 DeviceRef dev
{VerifyDevice(device
)};
3037 if(size
<= 0 || values
== nullptr)
3038 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3040 GetIntegerv(dev
.get(), param
, {values
, values
+size
});
3044 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3047 DeviceRef dev
{VerifyDevice(device
)};
3048 if(size
<= 0 || values
== nullptr)
3049 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3050 else if(!dev
|| dev
->Type
== Capture
)
3052 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3053 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3054 std::copy_n(ivals
.begin(), got
, values
);
3060 case ALC_ATTRIBUTES_SIZE
:
3061 *values
= NumAttrsForDevice(dev
.get())+4;
3064 case ALC_ALL_ATTRIBUTES
:
3065 if(size
< NumAttrsForDevice(dev
.get())+4)
3066 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3070 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3071 values
[i
++] = ALC_FREQUENCY
;
3072 values
[i
++] = dev
->Frequency
;
3074 if(dev
->Type
!= Loopback
)
3076 values
[i
++] = ALC_REFRESH
;
3077 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3079 values
[i
++] = ALC_SYNC
;
3080 values
[i
++] = ALC_FALSE
;
3084 if(dev
->FmtChans
== DevFmtAmbi3D
)
3086 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3087 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiLayout
);
3089 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3090 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiScale
);
3092 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3093 values
[i
++] = dev
->mAmbiOrder
;
3096 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3097 values
[i
++] = dev
->FmtChans
;
3099 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3100 values
[i
++] = dev
->FmtType
;
3103 values
[i
++] = ALC_MONO_SOURCES
;
3104 values
[i
++] = dev
->NumMonoSources
;
3106 values
[i
++] = ALC_STEREO_SOURCES
;
3107 values
[i
++] = dev
->NumStereoSources
;
3109 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3110 values
[i
++] = dev
->NumAuxSends
;
3112 values
[i
++] = ALC_HRTF_SOFT
;
3113 values
[i
++] = (dev
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3115 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3116 values
[i
++] = dev
->HrtfStatus
;
3118 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3119 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3121 ClockLatency clock
{GetClockLatency(dev
.get())};
3122 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3123 values
[i
++] = clock
.ClockTime
.count();
3125 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3126 values
[i
++] = clock
.Latency
.count();
3132 case ALC_DEVICE_CLOCK_SOFT
:
3133 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3134 nanoseconds basecount
;
3138 while(((refcount
=ReadRef(dev
->MixCount
))&1) != 0)
3139 std::this_thread::yield();
3140 basecount
= dev
->ClockBase
;
3141 samplecount
= dev
->SamplesDone
;
3142 } while(refcount
!= ReadRef(dev
->MixCount
));
3143 basecount
+= nanoseconds
{seconds
{samplecount
}} / dev
->Frequency
;
3144 *values
= basecount
.count();
3148 case ALC_DEVICE_LATENCY_SOFT
:
3149 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3150 ClockLatency clock
{GetClockLatency(dev
.get())};
3151 *values
= clock
.Latency
.count();
3155 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3157 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3160 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3161 ClockLatency clock
{GetClockLatency(dev
.get())};
3162 values
[0] = clock
.ClockTime
.count();
3163 values
[1] = clock
.Latency
.count();
3168 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3169 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3170 std::copy_n(ivals
.begin(), got
, values
);
3177 /* alcIsExtensionPresent
3179 * Determines if there is support for a particular extension
3181 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3184 DeviceRef dev
{VerifyDevice(device
)};
3186 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3189 size_t len
= strlen(extName
);
3190 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3193 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3194 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3197 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3201 } while(isspace(*ptr
));
3210 /* alcGetProcAddress
3212 * Retrieves the function address for a particular extension function
3214 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3219 DeviceRef dev
{VerifyDevice(device
)};
3220 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3224 for(const auto &func
: alcFunctions
)
3226 if(strcmp(func
.funcName
, funcName
) == 0)
3227 return func
.address
;
3237 * Get the value for a particular ALC enumeration name
3239 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3244 DeviceRef dev
{VerifyDevice(device
)};
3245 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3249 for(const auto &enm
: alcEnumerations
)
3251 if(strcmp(enm
.enumName
, enumName
) == 0)
3262 * Create and attach a context to the given device.
3264 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3267 /* Explicitly hold the list lock while taking the StateLock in case the
3268 * device is asynchronously destroyed, to ensure this new context is
3269 * properly cleaned up after being made.
3271 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3272 DeviceRef dev
{VerifyDevice(device
)};
3273 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3276 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3279 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3282 dev
->LastError
.store(ALC_NO_ERROR
);
3284 ALCenum err
{UpdateDeviceParams(dev
.get(), attrList
)};
3285 if(err
!= ALC_NO_ERROR
)
3287 alcSetError(dev
.get(), err
);
3288 if(err
== ALC_INVALID_DEVICE
)
3289 aluHandleDisconnect(dev
.get(), "Device update failure");
3293 ContextRef context
{new ALCcontext
{dev
}};
3296 if(auto volopt
= ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust"))
3298 const ALfloat valf
{*volopt
};
3299 if(!std::isfinite(valf
))
3300 ERR("volume-adjust must be finite: %f\n", valf
);
3303 const ALfloat db
{clampf(valf
, -24.0f
, 24.0f
)};
3305 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3306 context
->mGainBoost
= std::pow(10.0f
, db
/20.0f
);
3307 TRACE("volume-adjust gain: %f\n", context
->mGainBoost
);
3310 UpdateListenerProps(context
.get());
3313 using ContextArray
= al::FlexArray
<ALCcontext
*>;
3315 /* Allocate a new context array, which holds 1 more than the current/
3318 auto *oldarray
= device
->mContexts
.load();
3319 const size_t newcount
{oldarray
->size()+1};
3320 std::unique_ptr
<ContextArray
> newarray
{ContextArray::Create(newcount
)};
3322 /* Copy the current/old context handles to the new array, appending the
3325 auto iter
= std::copy(oldarray
->begin(), oldarray
->end(), newarray
->begin());
3326 *iter
= context
.get();
3328 /* Store the new context array in the device. Wait for any current mix
3329 * to finish before deleting the old array.
3331 dev
->mContexts
.store(newarray
.release());
3332 if(oldarray
!= &EmptyContextArray
)
3334 while((dev
->MixCount
.load(std::memory_order_acquire
)&1))
3335 std::this_thread::yield();
3342 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3343 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
.get());
3344 ContextList
.emplace(iter
, context
);
3347 if(context
->mDefaultSlot
)
3349 if(InitializeEffect(context
.get(), context
->mDefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3350 UpdateEffectSlotProps(context
->mDefaultSlot
.get(), context
.get());
3352 ERR("Failed to initialize the default effect\n");
3355 TRACE("Created context %p\n", context
.get());
3356 return context
.get();
3360 /* alcDestroyContext
3362 * Remove a context from its device
3364 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3367 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3368 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
3369 if(iter
== ContextList
.end() || *iter
!= context
)
3372 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3375 /* Hold an extra reference to this context so it remains valid until the
3376 * ListLock is released.
3378 ContextRef ctx
{std::move(*iter
)};
3379 ContextList
.erase(iter
);
3381 ALCdevice
*Device
{ctx
->mDevice
.get()};
3383 std::lock_guard
<std::mutex
> _
{Device
->StateLock
};
3384 if(!ctx
->deinit() && Device
->Flags
.get
<DeviceRunning
>())
3386 Device
->Backend
->stop();
3387 Device
->Flags
.unset
<DeviceRunning
>();
3393 /* alcGetCurrentContext
3395 * Returns the currently active context on the calling thread
3397 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3400 ALCcontext
*Context
{LocalContext
.get()};
3401 if(!Context
) Context
= GlobalContext
.load();
3406 /* alcGetThreadContext
3408 * Returns the currently active thread-local context
3410 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3412 { return LocalContext
.get(); }
3415 /* alcMakeContextCurrent
3417 * Makes the given context the active process-wide context, and removes the
3418 * thread-local context for the calling thread.
3420 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3423 /* context must be valid or nullptr */
3427 ctx
= VerifyContext(context
);
3430 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3434 /* Release this reference (if any) to store it in the GlobalContext
3435 * pointer. Take ownership of the reference (if any) that was previously
3438 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3440 /* Reset (decrement) the previous global reference by replacing it with the
3441 * thread-local context. Take ownership of the thread-local context
3442 * reference (if any), clearing the storage to null.
3444 ctx
= ContextRef
{LocalContext
.get()};
3445 if(ctx
) LocalContext
.set(nullptr);
3446 /* Reset (decrement) the previous thread-local reference. */
3452 /* alcSetThreadContext
3454 * Makes the given context the active context for the current thread
3456 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3459 /* context must be valid or nullptr */
3463 ctx
= VerifyContext(context
);
3466 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3470 /* context's reference count is already incremented */
3471 ContextRef old
{LocalContext
.get()};
3472 LocalContext
.set(ctx
.release());
3479 /* alcGetContextsDevice
3481 * Returns the device that a particular context is attached to
3483 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3486 ContextRef ctx
{VerifyContext(Context
)};
3489 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3492 return ctx
->mDevice
.get();
3499 * Opens the named device.
3501 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3506 if(!PlaybackFactory
)
3508 alcSetError(nullptr, ALC_INVALID_VALUE
);
3512 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3514 /* Some old Windows apps hardcode these expecting OpenAL to use a
3515 * specific audio API, even when they're not enumerated. Creative's
3516 * router effectively ignores them too.
3518 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3519 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3522 deviceName
= nullptr;
3524 DeviceRef device
{new ALCdevice
{Playback
}};
3526 /* Set output format */
3527 device
->FmtChans
= DevFmtChannelsDefault
;
3528 device
->FmtType
= DevFmtTypeDefault
;
3529 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3530 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
3531 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
3533 device
->SourcesMax
= 256;
3534 device
->AuxiliaryEffectSlotMax
= 64;
3535 device
->NumAuxSends
= DEFAULT_SENDS
;
3538 /* Create the device backend. */
3539 device
->Backend
= PlaybackFactory
->createBackend(device
.get(), BackendType::Playback
);
3541 /* Find a playback device to open */
3542 ALCenum err
{device
->Backend
->open(deviceName
)};
3543 if(err
!= ALC_NO_ERROR
)
3545 alcSetError(nullptr, err
);
3549 catch(al::backend_exception
&e
) {
3550 WARN("Failed to open playback device: %s\n", e
.what());
3551 alcSetError(nullptr, e
.errorCode());
3555 deviceName
= device
->DeviceName
.c_str();
3556 if(auto chanopt
= ConfigValueStr(deviceName
, nullptr, "channels"))
3558 static constexpr struct ChannelMap
{
3559 const char name
[16];
3560 DevFmtChannels chans
;
3563 { "mono", DevFmtMono
, 0 },
3564 { "stereo", DevFmtStereo
, 0 },
3565 { "quad", DevFmtQuad
, 0 },
3566 { "surround51", DevFmtX51
, 0 },
3567 { "surround61", DevFmtX61
, 0 },
3568 { "surround71", DevFmtX71
, 0 },
3569 { "surround51rear", DevFmtX51Rear
, 0 },
3570 { "ambi1", DevFmtAmbi3D
, 1 },
3571 { "ambi2", DevFmtAmbi3D
, 2 },
3572 { "ambi3", DevFmtAmbi3D
, 3 },
3575 const ALCchar
*fmt
{chanopt
->c_str()};
3576 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3577 [fmt
](const ChannelMap
&entry
) -> bool
3578 { return strcasecmp(entry
.name
, fmt
) == 0; }
3580 if(iter
== std::end(chanlist
))
3581 ERR("Unsupported channels: %s\n", fmt
);
3584 device
->FmtChans
= iter
->chans
;
3585 device
->mAmbiOrder
= iter
->order
;
3586 device
->Flags
.set
<ChannelsRequest
>();
3589 if(auto typeopt
= ConfigValueStr(deviceName
, nullptr, "sample-type"))
3591 static constexpr struct TypeMap
{
3592 const char name
[16];
3595 { "int8", DevFmtByte
},
3596 { "uint8", DevFmtUByte
},
3597 { "int16", DevFmtShort
},
3598 { "uint16", DevFmtUShort
},
3599 { "int32", DevFmtInt
},
3600 { "uint32", DevFmtUInt
},
3601 { "float32", DevFmtFloat
},
3604 const ALCchar
*fmt
{typeopt
->c_str()};
3605 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3606 [fmt
](const TypeMap
&entry
) -> bool
3607 { return strcasecmp(entry
.name
, fmt
) == 0; }
3609 if(iter
== std::end(typelist
))
3610 ERR("Unsupported sample-type: %s\n", fmt
);
3613 device
->FmtType
= iter
->type
;
3614 device
->Flags
.set
<SampleTypeRequest
>();
3618 if(ALuint freq
{ConfigValueUInt(deviceName
, nullptr, "frequency").value_or(0)})
3620 if(freq
< MIN_OUTPUT_RATE
)
3622 ERR("%uhz request clamped to %uhz minimum\n", freq
, MIN_OUTPUT_RATE
);
3623 freq
= MIN_OUTPUT_RATE
;
3625 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3626 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3627 device
->Frequency
= freq
;
3628 device
->Flags
.set
<FrequencyRequest
>();
3631 if(auto persizeopt
= ConfigValueUInt(deviceName
, nullptr, "period_size"))
3632 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
3634 if(auto peropt
= ConfigValueUInt(deviceName
, nullptr, "periods"))
3635 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
3637 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
3639 if(auto srcsopt
= ConfigValueUInt(deviceName
, nullptr, "sources"))
3641 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3644 if(auto slotsopt
= ConfigValueUInt(deviceName
, nullptr, "slots"))
3647 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3650 if(auto sendsopt
= ConfigValueInt(deviceName
, nullptr, "sends"))
3651 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3652 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3654 device
->NumStereoSources
= 1;
3655 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3657 if(auto ambiopt
= ConfigValueStr(deviceName
, nullptr, "ambi-format"))
3659 const ALCchar
*fmt
{ambiopt
->c_str()};
3660 if(strcasecmp(fmt
, "fuma") == 0)
3662 if(device
->mAmbiOrder
> 3)
3663 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3665 (((device
->mAmbiOrder
%100)/10) == 1) ? "th" :
3666 ((device
->mAmbiOrder
%10) == 1) ? "st" :
3667 ((device
->mAmbiOrder
%10) == 2) ? "nd" :
3668 ((device
->mAmbiOrder
%10) == 3) ? "rd" : "th");
3671 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3672 device
->mAmbiScale
= AmbiNorm::FuMa
;
3675 else if(strcasecmp(fmt
, "ambix") == 0 || strcasecmp(fmt
, "acn+sn3d") == 0)
3677 device
->mAmbiLayout
= AmbiLayout::ACN
;
3678 device
->mAmbiScale
= AmbiNorm::SN3D
;
3680 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3682 device
->mAmbiLayout
= AmbiLayout::ACN
;
3683 device
->mAmbiScale
= AmbiNorm::N3D
;
3686 ERR("Unsupported ambi-format: %s\n", fmt
);
3690 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3691 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3692 DeviceList
.emplace(iter
, device
);
3695 TRACE("Created device %p, \"%s\"\n", device
.get(), device
->DeviceName
.c_str());
3696 return device
.get();
3702 * Closes the given device.
3704 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3707 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3708 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3709 if(iter
== DeviceList
.end() || *iter
!= device
)
3711 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3714 if((*iter
)->Type
== Capture
)
3716 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3720 /* Erase the device, and any remaining contexts left on it, from their
3723 DeviceRef dev
{std::move(*iter
)};
3724 DeviceList
.erase(iter
);
3726 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3727 al::vector
<ContextRef
> orphanctxs
;
3728 for(ALCcontext
*ctx
: *dev
->mContexts
.load())
3730 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), ctx
);
3731 if(iter
!= ContextList
.end() && *iter
== ctx
)
3733 orphanctxs
.emplace_back(std::move(*iter
));
3734 ContextList
.erase(iter
);
3739 for(ContextRef
&context
: orphanctxs
)
3741 WARN("Releasing orphaned context %p\n", context
.get());
3746 if(dev
->Flags
.get
<DeviceRunning
>())
3747 dev
->Backend
->stop();
3748 dev
->Flags
.unset
<DeviceRunning
>();
3755 /************************************************
3756 * ALC capture functions
3757 ************************************************/
3758 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3765 alcSetError(nullptr, ALC_INVALID_VALUE
);
3771 alcSetError(nullptr, ALC_INVALID_VALUE
);
3775 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
3776 deviceName
= nullptr;
3778 DeviceRef device
{new ALCdevice
{Capture
}};
3780 auto decompfmt
= DecomposeDevFormat(format
);
3783 alcSetError(nullptr, ALC_INVALID_ENUM
);
3787 device
->Frequency
= frequency
;
3788 device
->FmtChans
= decompfmt
->chans
;
3789 device
->FmtType
= decompfmt
->type
;
3790 device
->Flags
.set
<FrequencyRequest
, ChannelsRequest
, SampleTypeRequest
>();
3792 device
->UpdateSize
= static_cast<ALuint
>(samples
);
3793 device
->BufferSize
= static_cast<ALuint
>(samples
);
3796 device
->Backend
= CaptureFactory
->createBackend(device
.get(), BackendType::Capture
);
3798 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3799 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
3800 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
3801 ALCenum err
{device
->Backend
->open(deviceName
)};
3802 if(err
!= ALC_NO_ERROR
)
3804 alcSetError(nullptr, err
);
3808 catch(al::backend_exception
&e
) {
3809 WARN("Failed to open capture device: %s\n", e
.what());
3810 alcSetError(nullptr, e
.errorCode());
3815 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3816 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3817 DeviceList
.emplace(iter
, device
);
3820 TRACE("Created device %p, \"%s\"\n", device
.get(), device
->DeviceName
.c_str());
3821 return device
.get();
3825 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3828 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3829 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3830 if(iter
== DeviceList
.end() || *iter
!= device
)
3832 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3835 if((*iter
)->Type
!= Capture
)
3837 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3841 DeviceRef dev
{std::move(*iter
)};
3842 DeviceList
.erase(iter
);
3845 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3846 if(dev
->Flags
.get
<DeviceRunning
>())
3847 dev
->Backend
->stop();
3848 dev
->Flags
.unset
<DeviceRunning
>();
3854 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3857 DeviceRef dev
{VerifyDevice(device
)};
3858 if(!dev
|| dev
->Type
!= Capture
)
3860 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3864 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3865 if(!dev
->Connected
.load(std::memory_order_acquire
))
3866 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3867 else if(!dev
->Flags
.get
<DeviceRunning
>())
3869 if(dev
->Backend
->start())
3870 dev
->Flags
.set
<DeviceRunning
>();
3873 aluHandleDisconnect(dev
.get(), "Device start failure");
3874 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3880 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3883 DeviceRef dev
{VerifyDevice(device
)};
3884 if(!dev
|| dev
->Type
!= Capture
)
3885 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3888 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3889 if(dev
->Flags
.get
<DeviceRunning
>())
3890 dev
->Backend
->stop();
3891 dev
->Flags
.unset
<DeviceRunning
>();
3896 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3899 DeviceRef dev
{VerifyDevice(device
)};
3900 if(!dev
|| dev
->Type
!= Capture
)
3902 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3906 ALCenum err
{ALC_INVALID_VALUE
};
3907 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3908 BackendBase
*backend
{dev
->Backend
.get()};
3909 if(samples
>= 0 && backend
->availableSamples() >= static_cast<ALCuint
>(samples
))
3910 err
= backend
->captureSamples(buffer
, static_cast<ALuint
>(samples
));
3912 if(err
!= ALC_NO_ERROR
)
3913 alcSetError(dev
.get(), err
);
3918 /************************************************
3919 * ALC loopback functions
3920 ************************************************/
3922 /* alcLoopbackOpenDeviceSOFT
3924 * Open a loopback device, for manual rendering.
3926 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3931 /* Make sure the device name, if specified, is us. */
3932 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3934 alcSetError(nullptr, ALC_INVALID_VALUE
);
3938 DeviceRef device
{new ALCdevice
{Loopback
}};
3940 device
->SourcesMax
= 256;
3941 device
->AuxiliaryEffectSlotMax
= 64;
3942 device
->NumAuxSends
= DEFAULT_SENDS
;
3945 device
->BufferSize
= 0;
3946 device
->UpdateSize
= 0;
3948 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3949 device
->FmtChans
= DevFmtChannelsDefault
;
3950 device
->FmtType
= DevFmtTypeDefault
;
3952 if(auto srcsopt
= ConfigValueUInt(nullptr, nullptr, "sources"))
3954 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3957 if(auto slotsopt
= ConfigValueUInt(nullptr, nullptr, "slots"))
3960 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3963 if(auto sendsopt
= ConfigValueInt(nullptr, nullptr, "sends"))
3964 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3965 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3967 device
->NumStereoSources
= 1;
3968 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3971 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(device
.get(),
3972 BackendType::Playback
);
3974 // Open the "backend"
3975 device
->Backend
->open("Loopback");
3977 catch(al::backend_exception
&e
) {
3978 WARN("Failed to open loopback device: %s\n", e
.what());
3979 alcSetError(nullptr, e
.errorCode());
3984 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3985 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3986 DeviceList
.emplace(iter
, device
);
3989 TRACE("Created device %p\n", device
.get());
3990 return device
.get();
3994 /* alcIsRenderFormatSupportedSOFT
3996 * Determines if the loopback device supports the given format for rendering.
3998 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4001 DeviceRef dev
{VerifyDevice(device
)};
4002 if(!dev
|| dev
->Type
!= Loopback
)
4003 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4005 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4008 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4016 /* alcRenderSamplesSOFT
4018 * Renders some samples into a buffer, using the format last set by the
4019 * attributes given to alcCreateContext.
4021 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4024 DeviceRef dev
{VerifyDevice(device
)};
4025 if(!dev
|| dev
->Type
!= Loopback
)
4026 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4027 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4028 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4031 BackendLockGuard _
{*dev
->Backend
};
4032 aluMixData(dev
.get(), buffer
, static_cast<ALuint
>(samples
));
4038 /************************************************
4039 * ALC DSP pause/resume functions
4040 ************************************************/
4042 /* alcDevicePauseSOFT
4044 * Pause the DSP to stop audio processing.
4046 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4049 DeviceRef dev
{VerifyDevice(device
)};
4050 if(!dev
|| dev
->Type
!= Playback
)
4051 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4054 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4055 if(dev
->Flags
.get
<DeviceRunning
>())
4056 dev
->Backend
->stop();
4057 dev
->Flags
.unset
<DeviceRunning
>();
4058 dev
->Flags
.set
<DevicePaused
>();
4063 /* alcDeviceResumeSOFT
4065 * Resume the DSP to restart audio processing.
4067 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4070 DeviceRef dev
{VerifyDevice(device
)};
4071 if(!dev
|| dev
->Type
!= Playback
)
4073 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4077 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4078 if(!dev
->Flags
.get
<DevicePaused
>())
4080 dev
->Flags
.unset
<DevicePaused
>();
4081 if(dev
->mContexts
.load()->empty())
4084 if(dev
->Backend
->start() == ALC_FALSE
)
4086 aluHandleDisconnect(dev
.get(), "Device start failure");
4087 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4090 dev
->Flags
.set
<DeviceRunning
>();
4095 /************************************************
4096 * ALC HRTF functions
4097 ************************************************/
4099 /* alcGetStringiSOFT
4101 * Gets a string parameter at the given index.
4103 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4106 DeviceRef dev
{VerifyDevice(device
)};
4107 if(!dev
|| dev
->Type
== Capture
)
4108 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4109 else switch(paramName
)
4111 case ALC_HRTF_SPECIFIER_SOFT
:
4112 if(index
>= 0 && static_cast<size_t>(index
) < dev
->HrtfList
.size())
4113 return dev
->HrtfList
[static_cast<ALuint
>(index
)].name
.c_str();
4114 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4118 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4126 /* alcResetDeviceSOFT
4128 * Resets the given device output, using the specified attribute list.
4130 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4133 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4134 DeviceRef dev
{VerifyDevice(device
)};
4135 if(!dev
|| dev
->Type
== Capture
)
4138 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4141 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4144 /* Force the backend to stop mixing first since we're resetting. Also reset
4145 * the connected state so lost devices can attempt recover.
4147 if(dev
->Flags
.get
<DeviceRunning
>())
4148 dev
->Backend
->stop();
4149 dev
->Flags
.unset
<DeviceRunning
>();
4150 device
->Connected
.store(true);
4152 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4153 if LIKELY(err
== ALC_NO_ERROR
) return ALC_TRUE
;
4155 alcSetError(dev
.get(), err
);
4156 if(err
== ALC_INVALID_DEVICE
)
4157 aluHandleDisconnect(dev
.get(), "Device start failure");