2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
55 #include "al/auxeffectslot.h"
56 #include "al/effect.h"
58 #include "al/filter.h"
59 #include "al/listener.h"
60 #include "al/source.h"
64 #include "alcontext.h"
67 #include "alnumeric.h"
68 #include "aloptional.h"
74 #include "bformatdec.h"
78 #include "devformat.h"
79 #include "effects/base.h"
80 #include "filters/nfc.h"
81 #include "filters/splitter.h"
82 #include "fpu_modes.h"
84 #include "inprogext.h"
85 #include "intrusive_ptr.h"
87 #include "mastering.h"
88 #include "opthelpers.h"
89 #include "pragmadefs.h"
90 #include "ringbuffer.h"
93 #include "uhjfilter.h"
97 #include "backends/base.h"
98 #include "backends/null.h"
99 #include "backends/loopback.h"
101 #include "backends/jack.h"
103 #ifdef HAVE_PULSEAUDIO
104 #include "backends/pulseaudio.h"
107 #include "backends/alsa.h"
110 #include "backends/wasapi.h"
112 #ifdef HAVE_COREAUDIO
113 #include "backends/coreaudio.h"
116 #include "backends/opensl.h"
119 #include "backends/solaris.h"
122 #include "backends/sndio.h"
125 #include "backends/oss.h"
128 #include "backends/qsa.h"
131 #include "backends/dsound.h"
134 #include "backends/winmm.h"
136 #ifdef HAVE_PORTAUDIO
137 #include "backends/portaudio.h"
140 #include "backends/sdl2.h"
143 #include "backends/wave.h"
149 using namespace std::placeholders
;
150 using std::chrono::seconds
;
151 using std::chrono::nanoseconds
;
154 /************************************************
156 ************************************************/
159 BackendFactory
& (*getFactory
)(void);
162 BackendInfo BackendList
[] = {
164 { "jack", JackBackendFactory::getFactory
},
166 #ifdef HAVE_PULSEAUDIO
167 { "pulse", PulseBackendFactory::getFactory
},
170 { "alsa", AlsaBackendFactory::getFactory
},
173 { "wasapi", WasapiBackendFactory::getFactory
},
175 #ifdef HAVE_COREAUDIO
176 { "core", CoreAudioBackendFactory::getFactory
},
179 { "opensl", OSLBackendFactory::getFactory
},
182 { "solaris", SolarisBackendFactory::getFactory
},
185 { "sndio", SndIOBackendFactory::getFactory
},
188 { "oss", OSSBackendFactory::getFactory
},
191 { "qsa", QSABackendFactory::getFactory
},
194 { "dsound", DSoundBackendFactory::getFactory
},
197 { "winmm", WinMMBackendFactory::getFactory
},
199 #ifdef HAVE_PORTAUDIO
200 { "port", PortBackendFactory::getFactory
},
203 { "sdl2", SDL2BackendFactory::getFactory
},
206 { "null", NullBackendFactory::getFactory
},
208 { "wave", WaveBackendFactory::getFactory
},
211 auto BackendListEnd
= std::end(BackendList
);
213 BackendFactory
*PlaybackFactory
{};
214 BackendFactory
*CaptureFactory
{};
217 /************************************************
218 * Functions, enums, and errors
219 ************************************************/
220 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
222 const ALCchar
*funcName
;
225 DECL(alcCreateContext
),
226 DECL(alcMakeContextCurrent
),
227 DECL(alcProcessContext
),
228 DECL(alcSuspendContext
),
229 DECL(alcDestroyContext
),
230 DECL(alcGetCurrentContext
),
231 DECL(alcGetContextsDevice
),
233 DECL(alcCloseDevice
),
235 DECL(alcIsExtensionPresent
),
236 DECL(alcGetProcAddress
),
237 DECL(alcGetEnumValue
),
239 DECL(alcGetIntegerv
),
240 DECL(alcCaptureOpenDevice
),
241 DECL(alcCaptureCloseDevice
),
242 DECL(alcCaptureStart
),
243 DECL(alcCaptureStop
),
244 DECL(alcCaptureSamples
),
246 DECL(alcSetThreadContext
),
247 DECL(alcGetThreadContext
),
249 DECL(alcLoopbackOpenDeviceSOFT
),
250 DECL(alcIsRenderFormatSupportedSOFT
),
251 DECL(alcRenderSamplesSOFT
),
253 DECL(alcDevicePauseSOFT
),
254 DECL(alcDeviceResumeSOFT
),
256 DECL(alcGetStringiSOFT
),
257 DECL(alcResetDeviceSOFT
),
259 DECL(alcGetInteger64vSOFT
),
274 DECL(alIsExtensionPresent
),
275 DECL(alGetProcAddress
),
276 DECL(alGetEnumValue
),
283 DECL(alGetListenerf
),
284 DECL(alGetListener3f
),
285 DECL(alGetListenerfv
),
286 DECL(alGetListeneri
),
287 DECL(alGetListener3i
),
288 DECL(alGetListeneriv
),
290 DECL(alDeleteSources
),
306 DECL(alSourceRewindv
),
307 DECL(alSourcePausev
),
310 DECL(alSourceRewind
),
312 DECL(alSourceQueueBuffers
),
313 DECL(alSourceUnqueueBuffers
),
315 DECL(alDeleteBuffers
),
330 DECL(alDopplerFactor
),
331 DECL(alDopplerVelocity
),
332 DECL(alSpeedOfSound
),
333 DECL(alDistanceModel
),
336 DECL(alDeleteFilters
),
347 DECL(alDeleteEffects
),
357 DECL(alGenAuxiliaryEffectSlots
),
358 DECL(alDeleteAuxiliaryEffectSlots
),
359 DECL(alIsAuxiliaryEffectSlot
),
360 DECL(alAuxiliaryEffectSloti
),
361 DECL(alAuxiliaryEffectSlotiv
),
362 DECL(alAuxiliaryEffectSlotf
),
363 DECL(alAuxiliaryEffectSlotfv
),
364 DECL(alGetAuxiliaryEffectSloti
),
365 DECL(alGetAuxiliaryEffectSlotiv
),
366 DECL(alGetAuxiliaryEffectSlotf
),
367 DECL(alGetAuxiliaryEffectSlotfv
),
369 DECL(alDeferUpdatesSOFT
),
370 DECL(alProcessUpdatesSOFT
),
373 DECL(alSource3dSOFT
),
374 DECL(alSourcedvSOFT
),
375 DECL(alGetSourcedSOFT
),
376 DECL(alGetSource3dSOFT
),
377 DECL(alGetSourcedvSOFT
),
378 DECL(alSourcei64SOFT
),
379 DECL(alSource3i64SOFT
),
380 DECL(alSourcei64vSOFT
),
381 DECL(alGetSourcei64SOFT
),
382 DECL(alGetSource3i64SOFT
),
383 DECL(alGetSourcei64vSOFT
),
385 DECL(alGetStringiSOFT
),
387 DECL(alBufferStorageSOFT
),
388 DECL(alMapBufferSOFT
),
389 DECL(alUnmapBufferSOFT
),
390 DECL(alFlushMappedBufferSOFT
),
392 DECL(alEventControlSOFT
),
393 DECL(alEventCallbackSOFT
),
394 DECL(alGetPointerSOFT
),
395 DECL(alGetPointervSOFT
),
399 #define DECL(x) { #x, (x) }
401 const ALCchar
*enumName
;
403 } alcEnumerations
[] = {
408 DECL(ALC_MAJOR_VERSION
),
409 DECL(ALC_MINOR_VERSION
),
410 DECL(ALC_ATTRIBUTES_SIZE
),
411 DECL(ALC_ALL_ATTRIBUTES
),
412 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
413 DECL(ALC_DEVICE_SPECIFIER
),
414 DECL(ALC_ALL_DEVICES_SPECIFIER
),
415 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
416 DECL(ALC_EXTENSIONS
),
420 DECL(ALC_MONO_SOURCES
),
421 DECL(ALC_STEREO_SOURCES
),
422 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
423 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
424 DECL(ALC_CAPTURE_SAMPLES
),
427 DECL(ALC_EFX_MAJOR_VERSION
),
428 DECL(ALC_EFX_MINOR_VERSION
),
429 DECL(ALC_MAX_AUXILIARY_SENDS
),
431 DECL(ALC_FORMAT_CHANNELS_SOFT
),
432 DECL(ALC_FORMAT_TYPE_SOFT
),
435 DECL(ALC_STEREO_SOFT
),
437 DECL(ALC_5POINT1_SOFT
),
438 DECL(ALC_6POINT1_SOFT
),
439 DECL(ALC_7POINT1_SOFT
),
440 DECL(ALC_BFORMAT3D_SOFT
),
443 DECL(ALC_UNSIGNED_BYTE_SOFT
),
444 DECL(ALC_SHORT_SOFT
),
445 DECL(ALC_UNSIGNED_SHORT_SOFT
),
447 DECL(ALC_UNSIGNED_INT_SOFT
),
448 DECL(ALC_FLOAT_SOFT
),
451 DECL(ALC_DONT_CARE_SOFT
),
452 DECL(ALC_HRTF_STATUS_SOFT
),
453 DECL(ALC_HRTF_DISABLED_SOFT
),
454 DECL(ALC_HRTF_ENABLED_SOFT
),
455 DECL(ALC_HRTF_DENIED_SOFT
),
456 DECL(ALC_HRTF_REQUIRED_SOFT
),
457 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
458 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
459 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
460 DECL(ALC_HRTF_SPECIFIER_SOFT
),
461 DECL(ALC_HRTF_ID_SOFT
),
463 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
464 DECL(ALC_AMBISONIC_SCALING_SOFT
),
465 DECL(ALC_AMBISONIC_ORDER_SOFT
),
471 DECL(ALC_OUTPUT_LIMITER_SOFT
),
474 DECL(ALC_INVALID_DEVICE
),
475 DECL(ALC_INVALID_CONTEXT
),
476 DECL(ALC_INVALID_ENUM
),
477 DECL(ALC_INVALID_VALUE
),
478 DECL(ALC_OUT_OF_MEMORY
),
486 DECL(AL_SOURCE_RELATIVE
),
487 DECL(AL_CONE_INNER_ANGLE
),
488 DECL(AL_CONE_OUTER_ANGLE
),
498 DECL(AL_ORIENTATION
),
499 DECL(AL_REFERENCE_DISTANCE
),
500 DECL(AL_ROLLOFF_FACTOR
),
501 DECL(AL_CONE_OUTER_GAIN
),
502 DECL(AL_MAX_DISTANCE
),
504 DECL(AL_SAMPLE_OFFSET
),
505 DECL(AL_BYTE_OFFSET
),
506 DECL(AL_SOURCE_TYPE
),
509 DECL(AL_UNDETERMINED
),
510 DECL(AL_METERS_PER_UNIT
),
511 DECL(AL_LOOP_POINTS_SOFT
),
512 DECL(AL_DIRECT_CHANNELS_SOFT
),
514 DECL(AL_DIRECT_FILTER
),
515 DECL(AL_AUXILIARY_SEND_FILTER
),
516 DECL(AL_AIR_ABSORPTION_FACTOR
),
517 DECL(AL_ROOM_ROLLOFF_FACTOR
),
518 DECL(AL_CONE_OUTER_GAINHF
),
519 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
520 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
521 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
523 DECL(AL_SOURCE_STATE
),
529 DECL(AL_BUFFERS_QUEUED
),
530 DECL(AL_BUFFERS_PROCESSED
),
532 DECL(AL_FORMAT_MONO8
),
533 DECL(AL_FORMAT_MONO16
),
534 DECL(AL_FORMAT_MONO_FLOAT32
),
535 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
536 DECL(AL_FORMAT_STEREO8
),
537 DECL(AL_FORMAT_STEREO16
),
538 DECL(AL_FORMAT_STEREO_FLOAT32
),
539 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
540 DECL(AL_FORMAT_MONO_IMA4
),
541 DECL(AL_FORMAT_STEREO_IMA4
),
542 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
543 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
544 DECL(AL_FORMAT_QUAD8_LOKI
),
545 DECL(AL_FORMAT_QUAD16_LOKI
),
546 DECL(AL_FORMAT_QUAD8
),
547 DECL(AL_FORMAT_QUAD16
),
548 DECL(AL_FORMAT_QUAD32
),
549 DECL(AL_FORMAT_51CHN8
),
550 DECL(AL_FORMAT_51CHN16
),
551 DECL(AL_FORMAT_51CHN32
),
552 DECL(AL_FORMAT_61CHN8
),
553 DECL(AL_FORMAT_61CHN16
),
554 DECL(AL_FORMAT_61CHN32
),
555 DECL(AL_FORMAT_71CHN8
),
556 DECL(AL_FORMAT_71CHN16
),
557 DECL(AL_FORMAT_71CHN32
),
558 DECL(AL_FORMAT_REAR8
),
559 DECL(AL_FORMAT_REAR16
),
560 DECL(AL_FORMAT_REAR32
),
561 DECL(AL_FORMAT_MONO_MULAW
),
562 DECL(AL_FORMAT_MONO_MULAW_EXT
),
563 DECL(AL_FORMAT_STEREO_MULAW
),
564 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
565 DECL(AL_FORMAT_QUAD_MULAW
),
566 DECL(AL_FORMAT_51CHN_MULAW
),
567 DECL(AL_FORMAT_61CHN_MULAW
),
568 DECL(AL_FORMAT_71CHN_MULAW
),
569 DECL(AL_FORMAT_REAR_MULAW
),
570 DECL(AL_FORMAT_MONO_ALAW_EXT
),
571 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
573 DECL(AL_FORMAT_BFORMAT2D_8
),
574 DECL(AL_FORMAT_BFORMAT2D_16
),
575 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
576 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
577 DECL(AL_FORMAT_BFORMAT3D_8
),
578 DECL(AL_FORMAT_BFORMAT3D_16
),
579 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
580 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
586 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
587 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
589 DECL(AL_SOURCE_RADIUS
),
591 DECL(AL_STEREO_ANGLES
),
598 DECL(AL_INVALID_NAME
),
599 DECL(AL_INVALID_ENUM
),
600 DECL(AL_INVALID_VALUE
),
601 DECL(AL_INVALID_OPERATION
),
602 DECL(AL_OUT_OF_MEMORY
),
609 DECL(AL_DOPPLER_FACTOR
),
610 DECL(AL_DOPPLER_VELOCITY
),
611 DECL(AL_DISTANCE_MODEL
),
612 DECL(AL_SPEED_OF_SOUND
),
613 DECL(AL_SOURCE_DISTANCE_MODEL
),
614 DECL(AL_DEFERRED_UPDATES_SOFT
),
615 DECL(AL_GAIN_LIMIT_SOFT
),
617 DECL(AL_INVERSE_DISTANCE
),
618 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
619 DECL(AL_LINEAR_DISTANCE
),
620 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
621 DECL(AL_EXPONENT_DISTANCE
),
622 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
624 DECL(AL_FILTER_TYPE
),
625 DECL(AL_FILTER_NULL
),
626 DECL(AL_FILTER_LOWPASS
),
627 DECL(AL_FILTER_HIGHPASS
),
628 DECL(AL_FILTER_BANDPASS
),
630 DECL(AL_LOWPASS_GAIN
),
631 DECL(AL_LOWPASS_GAINHF
),
633 DECL(AL_HIGHPASS_GAIN
),
634 DECL(AL_HIGHPASS_GAINLF
),
636 DECL(AL_BANDPASS_GAIN
),
637 DECL(AL_BANDPASS_GAINHF
),
638 DECL(AL_BANDPASS_GAINLF
),
640 DECL(AL_EFFECT_TYPE
),
641 DECL(AL_EFFECT_NULL
),
642 DECL(AL_EFFECT_REVERB
),
643 DECL(AL_EFFECT_EAXREVERB
),
644 DECL(AL_EFFECT_CHORUS
),
645 DECL(AL_EFFECT_DISTORTION
),
646 DECL(AL_EFFECT_ECHO
),
647 DECL(AL_EFFECT_FLANGER
),
648 DECL(AL_EFFECT_PITCH_SHIFTER
),
649 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
650 DECL(AL_EFFECT_VOCAL_MORPHER
),
651 DECL(AL_EFFECT_RING_MODULATOR
),
652 DECL(AL_EFFECT_AUTOWAH
),
653 DECL(AL_EFFECT_COMPRESSOR
),
654 DECL(AL_EFFECT_EQUALIZER
),
655 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
656 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
658 DECL(AL_EFFECTSLOT_EFFECT
),
659 DECL(AL_EFFECTSLOT_GAIN
),
660 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
661 DECL(AL_EFFECTSLOT_NULL
),
663 DECL(AL_EAXREVERB_DENSITY
),
664 DECL(AL_EAXREVERB_DIFFUSION
),
665 DECL(AL_EAXREVERB_GAIN
),
666 DECL(AL_EAXREVERB_GAINHF
),
667 DECL(AL_EAXREVERB_GAINLF
),
668 DECL(AL_EAXREVERB_DECAY_TIME
),
669 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
670 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
671 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
672 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
673 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
674 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
675 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
676 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
677 DECL(AL_EAXREVERB_ECHO_TIME
),
678 DECL(AL_EAXREVERB_ECHO_DEPTH
),
679 DECL(AL_EAXREVERB_MODULATION_TIME
),
680 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
681 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
682 DECL(AL_EAXREVERB_HFREFERENCE
),
683 DECL(AL_EAXREVERB_LFREFERENCE
),
684 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
685 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
687 DECL(AL_REVERB_DENSITY
),
688 DECL(AL_REVERB_DIFFUSION
),
689 DECL(AL_REVERB_GAIN
),
690 DECL(AL_REVERB_GAINHF
),
691 DECL(AL_REVERB_DECAY_TIME
),
692 DECL(AL_REVERB_DECAY_HFRATIO
),
693 DECL(AL_REVERB_REFLECTIONS_GAIN
),
694 DECL(AL_REVERB_REFLECTIONS_DELAY
),
695 DECL(AL_REVERB_LATE_REVERB_GAIN
),
696 DECL(AL_REVERB_LATE_REVERB_DELAY
),
697 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
698 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
699 DECL(AL_REVERB_DECAY_HFLIMIT
),
701 DECL(AL_CHORUS_WAVEFORM
),
702 DECL(AL_CHORUS_PHASE
),
703 DECL(AL_CHORUS_RATE
),
704 DECL(AL_CHORUS_DEPTH
),
705 DECL(AL_CHORUS_FEEDBACK
),
706 DECL(AL_CHORUS_DELAY
),
708 DECL(AL_DISTORTION_EDGE
),
709 DECL(AL_DISTORTION_GAIN
),
710 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
711 DECL(AL_DISTORTION_EQCENTER
),
712 DECL(AL_DISTORTION_EQBANDWIDTH
),
715 DECL(AL_ECHO_LRDELAY
),
716 DECL(AL_ECHO_DAMPING
),
717 DECL(AL_ECHO_FEEDBACK
),
718 DECL(AL_ECHO_SPREAD
),
720 DECL(AL_FLANGER_WAVEFORM
),
721 DECL(AL_FLANGER_PHASE
),
722 DECL(AL_FLANGER_RATE
),
723 DECL(AL_FLANGER_DEPTH
),
724 DECL(AL_FLANGER_FEEDBACK
),
725 DECL(AL_FLANGER_DELAY
),
727 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
728 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
729 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
731 DECL(AL_RING_MODULATOR_FREQUENCY
),
732 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
733 DECL(AL_RING_MODULATOR_WAVEFORM
),
735 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
736 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
738 DECL(AL_COMPRESSOR_ONOFF
),
740 DECL(AL_EQUALIZER_LOW_GAIN
),
741 DECL(AL_EQUALIZER_LOW_CUTOFF
),
742 DECL(AL_EQUALIZER_MID1_GAIN
),
743 DECL(AL_EQUALIZER_MID1_CENTER
),
744 DECL(AL_EQUALIZER_MID1_WIDTH
),
745 DECL(AL_EQUALIZER_MID2_GAIN
),
746 DECL(AL_EQUALIZER_MID2_CENTER
),
747 DECL(AL_EQUALIZER_MID2_WIDTH
),
748 DECL(AL_EQUALIZER_HIGH_GAIN
),
749 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
751 DECL(AL_DEDICATED_GAIN
),
753 DECL(AL_AUTOWAH_ATTACK_TIME
),
754 DECL(AL_AUTOWAH_RELEASE_TIME
),
755 DECL(AL_AUTOWAH_RESONANCE
),
756 DECL(AL_AUTOWAH_PEAK_GAIN
),
758 DECL(AL_VOCAL_MORPHER_PHONEMEA
),
759 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
760 DECL(AL_VOCAL_MORPHER_PHONEMEB
),
761 DECL(AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING
),
762 DECL(AL_VOCAL_MORPHER_WAVEFORM
),
763 DECL(AL_VOCAL_MORPHER_RATE
),
765 DECL(AL_NUM_RESAMPLERS_SOFT
),
766 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
767 DECL(AL_SOURCE_RESAMPLER_SOFT
),
768 DECL(AL_RESAMPLER_NAME_SOFT
),
770 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
773 DECL(AL_MAP_READ_BIT_SOFT
),
774 DECL(AL_MAP_WRITE_BIT_SOFT
),
775 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
776 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
778 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
779 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
780 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
781 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
782 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
783 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
784 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
788 constexpr ALCchar alcNoError
[] = "No Error";
789 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
790 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
791 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
792 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
793 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
796 /************************************************
798 ************************************************/
800 /* Enumerated device names */
801 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
803 std::string alcAllDevicesList
;
804 std::string alcCaptureDeviceList
;
806 /* Default is always the first in the list */
807 al::string alcDefaultAllDevicesSpecifier
;
808 al::string alcCaptureDefaultDeviceSpecifier
;
810 /* Default context extensions */
811 constexpr ALchar alExtList
[] =
815 "AL_EXT_EXPONENT_DISTANCE "
818 "AL_EXT_LINEAR_DISTANCE "
821 "AL_EXT_MULAW_BFORMAT "
822 "AL_EXT_MULAW_MCFORMATS "
824 "AL_EXT_source_distance_model "
825 "AL_EXT_SOURCE_RADIUS "
826 "AL_EXT_STEREO_ANGLES "
827 "AL_LOKI_quadriphonic "
828 "AL_SOFT_block_alignment "
829 "AL_SOFT_deferred_updates "
830 "AL_SOFT_direct_channels "
831 "AL_SOFTX_effect_chain "
833 "AL_SOFTX_filter_gain_ex "
834 "AL_SOFT_gain_clamp_ex "
835 "AL_SOFT_loop_points "
836 "AL_SOFTX_map_buffer "
838 "AL_SOFT_source_latency "
839 "AL_SOFT_source_length "
840 "AL_SOFT_source_resampler "
841 "AL_SOFT_source_spatialize";
843 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
845 /* Thread-local current context */
847 ALCcontext
*ctx
{nullptr};
854 const bool result
{ctx
->releaseIfNoDelete()};
855 ERR("Context %p current for thread being destroyed%s!\n",
856 decltype(std::declval
<void*>()){ctx
}, result
? "" : ", leak detected");
860 ALCcontext
*get() const noexcept
{ return ctx
; }
861 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
863 thread_local ThreadCtx LocalContext
;
864 /* Process-wide current context */
865 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
867 /* Flag to trap ALC device errors */
868 bool TrapALCError
{false};
870 /* One-time configuration init control */
871 std::once_flag alc_config_once
{};
873 /* Default effect that applies to sources that don't have an effect on send 0 */
874 ALeffect DefaultEffect
;
876 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
879 bool SuspendDefers
{true};
881 /* Initial seed for dithering. */
882 constexpr ALuint DitherRNGSeed
{22222u};
885 /************************************************
887 ************************************************/
888 constexpr ALCchar alcNoDeviceExtList
[] =
889 "ALC_ENUMERATE_ALL_EXT "
890 "ALC_ENUMERATION_EXT "
892 "ALC_EXT_thread_local_context "
894 constexpr ALCchar alcExtensionList
[] =
895 "ALC_ENUMERATE_ALL_EXT "
896 "ALC_ENUMERATION_EXT "
899 "ALC_EXT_disconnect "
901 "ALC_EXT_thread_local_context "
902 "ALC_SOFT_device_clock "
905 "ALC_SOFT_output_limiter "
906 "ALC_SOFT_pause_device";
907 constexpr ALCint alcMajorVersion
= 1;
908 constexpr ALCint alcMinorVersion
= 1;
910 constexpr ALCint alcEFXMajorVersion
= 1;
911 constexpr ALCint alcEFXMinorVersion
= 0;
914 /* To avoid extraneous allocations, a 0-sized FlexArray<ALCcontext*> is defined
915 * globally as a sharable object. MSVC warns that a zero-sized array will have
916 * zero objects here, so silence that.
919 msc_pragma(warning(disable
: 4815))
920 al::FlexArray
<ALCcontext
*> EmptyContextArray
{0u};
924 using DeviceRef
= al::intrusive_ptr
<ALCdevice
>;
927 /************************************************
929 ************************************************/
930 al::vector
<DeviceRef
> DeviceList
;
931 al::vector
<ContextRef
> ContextList
;
933 std::recursive_mutex ListLock
;
936 void alc_initconfig(void)
938 if(auto loglevel
= al::getenv("ALSOFT_LOGLEVEL"))
940 long lvl
= strtol(loglevel
->c_str(), nullptr, 0);
941 if(lvl
>= NoLog
&& lvl
<= LogRef
)
942 gLogLevel
= static_cast<LogLevel
>(lvl
);
945 if(auto logfile
= al::getenv("ALSOFT_LOGFILE"))
948 std::wstring wname
{utf8_to_wstr(logfile
->c_str())};
949 FILE *logf
{_wfopen(wname
.c_str(), L
"wt")};
951 FILE *logf
{fopen(logfile
->c_str(), "wt")};
953 if(logf
) gLogFile
= logf
;
954 else ERR("Failed to open log file '%s'\n", logfile
->c_str());
957 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
, ALSOFT_GIT_COMMIT_HASH
,
961 if(std::begin(BackendList
) == BackendListEnd
)
965 const al::span
<const BackendInfo
> infos
{std::begin(BackendList
), BackendListEnd
};
966 names
+= infos
[0].name
;
967 for(const auto &backend
: infos
.subspan(1))
970 names
+= backend
.name
;
973 TRACE("Supported backends: %s\n", names
.c_str());
977 if(auto suspendmode
= al::getenv("__ALSOFT_SUSPEND_CONTEXT"))
979 if(al::strcasecmp(suspendmode
->c_str(), "ignore") == 0)
981 SuspendDefers
= false;
982 TRACE("Selected context suspend behavior, \"ignore\"\n");
985 ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode
->c_str());
989 #if defined(HAVE_SSE4_1)
990 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
991 #elif defined(HAVE_SSE3)
992 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
993 #elif defined(HAVE_SSE2)
994 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
995 #elif defined(HAVE_SSE)
996 capfilter
|= CPU_CAP_SSE
;
999 capfilter
|= CPU_CAP_NEON
;
1001 if(auto cpuopt
= ConfigValueStr(nullptr, nullptr, "disable-cpu-exts"))
1003 const char *str
{cpuopt
->c_str()};
1004 if(al::strcasecmp(str
, "all") == 0)
1008 const char *next
= str
;
1011 while(isspace(str
[0]))
1013 next
= strchr(str
, ',');
1015 if(!str
[0] || str
[0] == ',')
1018 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1019 while(len
> 0 && isspace(str
[len
-1]))
1021 if(len
== 3 && al::strncasecmp(str
, "sse", len
) == 0)
1022 capfilter
&= ~CPU_CAP_SSE
;
1023 else if(len
== 4 && al::strncasecmp(str
, "sse2", len
) == 0)
1024 capfilter
&= ~CPU_CAP_SSE2
;
1025 else if(len
== 4 && al::strncasecmp(str
, "sse3", len
) == 0)
1026 capfilter
&= ~CPU_CAP_SSE3
;
1027 else if(len
== 6 && al::strncasecmp(str
, "sse4.1", len
) == 0)
1028 capfilter
&= ~CPU_CAP_SSE4_1
;
1029 else if(len
== 4 && al::strncasecmp(str
, "neon", len
) == 0)
1030 capfilter
&= ~CPU_CAP_NEON
;
1032 WARN("Invalid CPU extension \"%s\"\n", str
);
1036 FillCPUCaps(capfilter
);
1039 #define DEF_MIXER_PRIO 1
1041 #define DEF_MIXER_PRIO 0
1043 RTPrioLevel
= ConfigValueInt(nullptr, nullptr, "rt-prio").value_or(DEF_MIXER_PRIO
);
1044 #undef DEF_MIXER_PRIO
1049 auto traperr
= al::getenv("ALSOFT_TRAP_ERROR");
1050 if(traperr
&& (al::strcasecmp(traperr
->c_str(), "true") == 0
1051 || std::strtol(traperr
->c_str(), nullptr, 0) == 1))
1054 TrapALCError
= true;
1058 traperr
= al::getenv("ALSOFT_TRAP_AL_ERROR");
1060 TrapALError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1061 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1063 TrapALError
= !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false);
1065 traperr
= al::getenv("ALSOFT_TRAP_ALC_ERROR");
1067 TrapALCError
= al::strcasecmp(traperr
->c_str(), "true") == 0
1068 || strtol(traperr
->c_str(), nullptr, 0) == 1;
1070 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false);
1073 if(auto boostopt
= ConfigValueFloat(nullptr, "reverb", "boost"))
1075 const float valf
{std::isfinite(*boostopt
) ? clampf(*boostopt
, -24.0f
, 24.0f
) : 0.0f
};
1076 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1079 auto devopt
= al::getenv("ALSOFT_DRIVERS");
1080 if(devopt
|| (devopt
=ConfigValueStr(nullptr, nullptr, "drivers")))
1082 auto backendlist_cur
= std::begin(BackendList
);
1085 const char *next
{devopt
->c_str()};
1087 const char *devs
{next
};
1088 while(isspace(devs
[0]))
1090 next
= strchr(devs
, ',');
1092 const bool delitem
{devs
[0] == '-'};
1093 if(devs
[0] == '-') devs
++;
1095 if(!devs
[0] || devs
[0] == ',')
1102 size_t len
{next
? (static_cast<size_t>(next
-devs
)) : strlen(devs
)};
1103 while(len
> 0 && isspace(devs
[len
-1])) --len
;
1105 /* HACK: For backwards compatibility, convert backend references of
1106 * mmdevapi to wasapi. This should eventually be removed.
1108 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1115 auto find_backend
= [devs
,len
](const BackendInfo
&backend
) -> bool
1116 { return len
== strlen(backend
.name
) && strncmp(backend
.name
, devs
, len
) == 0; };
1117 auto this_backend
= std::find_if(std::begin(BackendList
), BackendListEnd
,
1120 if(this_backend
== BackendListEnd
)
1124 BackendListEnd
= std::move(this_backend
+1, BackendListEnd
, this_backend
);
1126 backendlist_cur
= std::rotate(backendlist_cur
, this_backend
, this_backend
+1);
1130 BackendListEnd
= backendlist_cur
;
1133 auto init_backend
= [](BackendInfo
&backend
) -> bool
1135 if(PlaybackFactory
&& CaptureFactory
)
1138 BackendFactory
&factory
= backend
.getFactory();
1141 WARN("Failed to initialize backend \"%s\"\n", backend
.name
);
1145 TRACE("Initialized backend \"%s\"\n", backend
.name
);
1146 if(!PlaybackFactory
&& factory
.querySupport(BackendType::Playback
))
1148 PlaybackFactory
= &factory
;
1149 TRACE("Added \"%s\" for playback\n", backend
.name
);
1151 if(!CaptureFactory
&& factory
.querySupport(BackendType::Capture
))
1153 CaptureFactory
= &factory
;
1154 TRACE("Added \"%s\" for capture\n", backend
.name
);
1158 BackendListEnd
= std::remove_if(std::begin(BackendList
), BackendListEnd
, init_backend
);
1160 LoopbackBackendFactory::getFactory().init();
1162 if(!PlaybackFactory
)
1163 WARN("No playback backend available!\n");
1165 WARN("No capture backend available!\n");
1167 if(auto exclopt
= ConfigValueStr(nullptr, nullptr, "excludefx"))
1169 const char *next
{exclopt
->c_str()};
1171 const char *str
{next
};
1172 next
= strchr(str
, ',');
1174 if(!str
[0] || next
== str
)
1177 size_t len
{next
? static_cast<size_t>(next
-str
) : strlen(str
)};
1178 for(const EffectList
&effectitem
: gEffectList
)
1180 if(len
== strlen(effectitem
.name
) &&
1181 strncmp(effectitem
.name
, str
, len
) == 0)
1182 DisabledEffects
[effectitem
.type
] = AL_TRUE
;
1187 InitEffect(&DefaultEffect
);
1188 auto defrevopt
= al::getenv("ALSOFT_DEFAULT_REVERB");
1189 if(defrevopt
|| (defrevopt
=ConfigValueStr(nullptr, nullptr, "default-reverb")))
1190 LoadReverbPreset(defrevopt
->c_str(), &DefaultEffect
);
1192 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1195 /************************************************
1196 * Device enumeration
1197 ************************************************/
1198 void ProbeAllDevicesList()
1202 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1203 alcAllDevicesList
.clear();
1205 PlaybackFactory
->probe(DevProbe::Playback
, &alcAllDevicesList
);
1207 void ProbeCaptureDeviceList()
1211 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1212 alcCaptureDeviceList
.clear();
1214 CaptureFactory
->probe(DevProbe::Capture
, &alcCaptureDeviceList
);
1219 /* Mixing thread piority level */
1222 FILE *gLogFile
{stderr
};
1224 LogLevel gLogLevel
{LogWarning
};
1226 LogLevel gLogLevel
{LogError
};
1229 /************************************************
1230 * Library initialization
1231 ************************************************/
1232 #if defined(_WIN32) && !defined(AL_LIBTYPE_STATIC)
1233 BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID
/*reserved*/)
1237 case DLL_PROCESS_ATTACH
:
1238 /* Pin the DLL so we won't get unloaded until the process terminates */
1239 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
1240 reinterpret_cast<WCHAR
*>(module
), &module
);
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar
*DevFmtTypeString(DevFmtType type
) noexcept
1254 case DevFmtByte
: return "Signed Byte";
1255 case DevFmtUByte
: return "Unsigned Byte";
1256 case DevFmtShort
: return "Signed Short";
1257 case DevFmtUShort
: return "Unsigned Short";
1258 case DevFmtInt
: return "Signed Int";
1259 case DevFmtUInt
: return "Unsigned Int";
1260 case DevFmtFloat
: return "Float";
1262 return "(unknown type)";
1264 const ALCchar
*DevFmtChannelsString(DevFmtChannels chans
) noexcept
1268 case DevFmtMono
: return "Mono";
1269 case DevFmtStereo
: return "Stereo";
1270 case DevFmtQuad
: return "Quadraphonic";
1271 case DevFmtX51
: return "5.1 Surround";
1272 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1273 case DevFmtX61
: return "6.1 Surround";
1274 case DevFmtX71
: return "7.1 Surround";
1275 case DevFmtAmbi3D
: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALuint
BytesFromDevFmt(DevFmtType type
) noexcept
1284 case DevFmtByte
: return sizeof(ALbyte
);
1285 case DevFmtUByte
: return sizeof(ALubyte
);
1286 case DevFmtShort
: return sizeof(ALshort
);
1287 case DevFmtUShort
: return sizeof(ALushort
);
1288 case DevFmtInt
: return sizeof(ALint
);
1289 case DevFmtUInt
: return sizeof(ALuint
);
1290 case DevFmtFloat
: return sizeof(ALfloat
);
1294 ALuint
ChannelsFromDevFmt(DevFmtChannels chans
, ALuint ambiorder
) noexcept
1298 case DevFmtMono
: return 1;
1299 case DevFmtStereo
: return 2;
1300 case DevFmtQuad
: return 4;
1301 case DevFmtX51
: return 6;
1302 case DevFmtX51Rear
: return 6;
1303 case DevFmtX61
: return 7;
1304 case DevFmtX71
: return 8;
1305 case DevFmtAmbi3D
: return (ambiorder
+1) * (ambiorder
+1);
1310 struct DevFmtPair
{ DevFmtChannels chans
; DevFmtType type
; };
1311 static al::optional
<DevFmtPair
> DecomposeDevFormat(ALenum format
)
1313 static const struct {
1315 DevFmtChannels channels
;
1318 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1319 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1320 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1322 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1323 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1324 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1326 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1327 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1328 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1330 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1331 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1332 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1334 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1335 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1336 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1338 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1339 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1340 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1343 for(const auto &item
: list
)
1345 if(item
.format
== format
)
1346 return al::make_optional(DevFmtPair
{item
.channels
, item
.type
});
1352 static ALCboolean
IsValidALCType(ALCenum type
)
1357 case ALC_UNSIGNED_BYTE_SOFT
:
1358 case ALC_SHORT_SOFT
:
1359 case ALC_UNSIGNED_SHORT_SOFT
:
1361 case ALC_UNSIGNED_INT_SOFT
:
1362 case ALC_FLOAT_SOFT
:
1368 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1373 case ALC_STEREO_SOFT
:
1375 case ALC_5POINT1_SOFT
:
1376 case ALC_6POINT1_SOFT
:
1377 case ALC_7POINT1_SOFT
:
1378 case ALC_BFORMAT3D_SOFT
:
1384 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1395 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1407 /************************************************
1408 * Miscellaneous ALC helpers
1409 ************************************************/
1411 /* SetDefaultWFXChannelOrder
1413 * Sets the default channel order used by WaveFormatEx.
1415 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1417 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1419 switch(device
->FmtChans
)
1422 device
->RealOut
.ChannelIndex
[FrontCenter
] = 0;
1425 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1426 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1429 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1430 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1431 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1432 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1435 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1436 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1437 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1438 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1439 device
->RealOut
.ChannelIndex
[SideLeft
] = 4;
1440 device
->RealOut
.ChannelIndex
[SideRight
] = 5;
1443 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1444 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1445 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1446 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1447 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1448 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1451 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1452 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1453 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1454 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1455 device
->RealOut
.ChannelIndex
[BackCenter
] = 4;
1456 device
->RealOut
.ChannelIndex
[SideLeft
] = 5;
1457 device
->RealOut
.ChannelIndex
[SideRight
] = 6;
1460 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1461 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1462 device
->RealOut
.ChannelIndex
[FrontCenter
] = 2;
1463 device
->RealOut
.ChannelIndex
[LFE
] = 3;
1464 device
->RealOut
.ChannelIndex
[BackLeft
] = 4;
1465 device
->RealOut
.ChannelIndex
[BackRight
] = 5;
1466 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1467 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1470 device
->RealOut
.ChannelIndex
[Aux0
] = 0;
1471 if(device
->mAmbiOrder
> 0)
1473 device
->RealOut
.ChannelIndex
[Aux1
] = 1;
1474 device
->RealOut
.ChannelIndex
[Aux2
] = 2;
1475 device
->RealOut
.ChannelIndex
[Aux3
] = 3;
1477 if(device
->mAmbiOrder
> 1)
1479 device
->RealOut
.ChannelIndex
[Aux4
] = 4;
1480 device
->RealOut
.ChannelIndex
[Aux5
] = 5;
1481 device
->RealOut
.ChannelIndex
[Aux6
] = 6;
1482 device
->RealOut
.ChannelIndex
[Aux7
] = 7;
1483 device
->RealOut
.ChannelIndex
[Aux8
] = 8;
1485 if(device
->mAmbiOrder
> 2)
1487 device
->RealOut
.ChannelIndex
[Aux9
] = 9;
1488 device
->RealOut
.ChannelIndex
[Aux10
] = 10;
1489 device
->RealOut
.ChannelIndex
[Aux11
] = 11;
1490 device
->RealOut
.ChannelIndex
[Aux12
] = 12;
1491 device
->RealOut
.ChannelIndex
[Aux13
] = 13;
1492 device
->RealOut
.ChannelIndex
[Aux14
] = 14;
1493 device
->RealOut
.ChannelIndex
[Aux15
] = 15;
1499 /* SetDefaultChannelOrder
1501 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1503 void SetDefaultChannelOrder(ALCdevice
*device
)
1505 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1507 switch(device
->FmtChans
)
1510 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1511 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1512 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1513 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1514 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1515 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1518 device
->RealOut
.ChannelIndex
[FrontLeft
] = 0;
1519 device
->RealOut
.ChannelIndex
[FrontRight
] = 1;
1520 device
->RealOut
.ChannelIndex
[BackLeft
] = 2;
1521 device
->RealOut
.ChannelIndex
[BackRight
] = 3;
1522 device
->RealOut
.ChannelIndex
[FrontCenter
] = 4;
1523 device
->RealOut
.ChannelIndex
[LFE
] = 5;
1524 device
->RealOut
.ChannelIndex
[SideLeft
] = 6;
1525 device
->RealOut
.ChannelIndex
[SideRight
] = 7;
1528 /* Same as WFX order */
1535 SetDefaultWFXChannelOrder(device
);
1541 void ALCcontext::processUpdates()
1543 std::lock_guard
<std::mutex
> _
{mPropLock
};
1544 if(mDeferUpdates
.exchange(false))
1546 /* Tell the mixer to stop applying updates, then wait for any active
1547 * updating to finish, before providing updates.
1549 mHoldUpdates
.store(true, std::memory_order_release
);
1550 while((mUpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1551 std::this_thread::yield();
1553 if(!mPropsClean
.test_and_set(std::memory_order_acq_rel
))
1554 UpdateContextProps(this);
1555 if(!mListener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1556 UpdateListenerProps(this);
1557 UpdateAllEffectSlotProps(this);
1558 UpdateAllSourceProps(this);
1560 /* Now with all updates declared, let the mixer continue applying them
1561 * so they all happen at once.
1563 mHoldUpdates
.store(false, std::memory_order_release
);
1570 * Stores the latest ALC device error
1572 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1574 WARN("Error generated on device %p, code 0x%04x\n", decltype(std::declval
<void*>()){device
},
1579 /* DebugBreak() will cause an exception if there is no debugger */
1580 if(IsDebuggerPresent())
1582 #elif defined(SIGTRAP)
1588 device
->LastError
.store(errorCode
);
1590 LastNullDeviceError
.store(errorCode
);
1594 static std::unique_ptr
<Compressor
> CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1596 return CompressorInit(static_cast<ALuint
>(device
->RealOut
.Buffer
.size()),
1597 static_cast<float>(device
->Frequency
), AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
,
1598 0.002f
, 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1603 * Updates the device's base clock time with however many samples have been
1604 * done. This is used so frequency changes on the device don't cause the time
1605 * to jump forward or back. Must not be called while the device is running/
1608 static inline void UpdateClockBase(ALCdevice
*device
)
1610 IncrementRef(device
->MixCount
);
1611 device
->ClockBase
+= nanoseconds
{seconds
{device
->SamplesDone
}} / device
->Frequency
;
1612 device
->SamplesDone
= 0;
1613 IncrementRef(device
->MixCount
);
1616 /* UpdateDeviceParams
1618 * Updates device parameters according to the attribute list (caller is
1619 * responsible for holding the list lock).
1621 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1623 HrtfRequestMode hrtf_userreq
{Hrtf_Default
};
1624 HrtfRequestMode hrtf_appreq
{Hrtf_Default
};
1625 ALCenum gainLimiter
{device
->LimiterState
};
1626 const ALCuint old_sends
{device
->NumAuxSends
};
1627 ALCuint new_sends
{device
->NumAuxSends
};
1628 DevFmtChannels oldChans
;
1630 ALboolean update_failed
;
1631 ALCsizei hrtf_id
{-1};
1634 if((!attrList
|| !attrList
[0]) && device
->Type
== Loopback
)
1636 WARN("Missing attributes for loopback device\n");
1637 return ALC_INVALID_VALUE
;
1640 // Check for attributes
1641 if(attrList
&& attrList
[0])
1643 ALCenum alayout
{AL_NONE
};
1644 ALCenum ascale
{AL_NONE
};
1645 ALCenum schans
{AL_NONE
};
1646 ALCenum stype
{AL_NONE
};
1647 ALCsizei attrIdx
{0};
1651 ALuint numMono
{device
->NumMonoSources
};
1652 ALuint numStereo
{device
->NumStereoSources
};
1653 ALuint numSends
{old_sends
};
1655 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1656 while(attrList
[attrIdx
])
1658 switch(attrList
[attrIdx
])
1660 case ALC_FORMAT_CHANNELS_SOFT
:
1661 schans
= attrList
[attrIdx
+ 1];
1662 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1665 case ALC_FORMAT_TYPE_SOFT
:
1666 stype
= attrList
[attrIdx
+ 1];
1667 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1671 freq
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1672 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1675 case ALC_AMBISONIC_LAYOUT_SOFT
:
1676 alayout
= attrList
[attrIdx
+ 1];
1677 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1680 case ALC_AMBISONIC_SCALING_SOFT
:
1681 ascale
= attrList
[attrIdx
+ 1];
1682 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1685 case ALC_AMBISONIC_ORDER_SOFT
:
1686 aorder
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1687 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1690 case ALC_MONO_SOURCES
:
1691 numMono
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1692 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1693 if(numMono
> INT_MAX
) numMono
= 0;
1696 case ALC_STEREO_SOURCES
:
1697 numStereo
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1698 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1699 if(numStereo
> INT_MAX
) numStereo
= 0;
1702 case ALC_MAX_AUXILIARY_SENDS
:
1703 numSends
= static_cast<ALuint
>(attrList
[attrIdx
+ 1]);
1704 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1705 if(numSends
> INT_MAX
) numSends
= 0;
1706 else numSends
= minu(numSends
, MAX_SENDS
);
1710 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1711 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1712 hrtf_appreq
= Hrtf_Disable
;
1713 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1714 hrtf_appreq
= Hrtf_Enable
;
1716 hrtf_appreq
= Hrtf_Default
;
1719 case ALC_HRTF_ID_SOFT
:
1720 hrtf_id
= attrList
[attrIdx
+ 1];
1721 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1724 case ALC_OUTPUT_LIMITER_SOFT
:
1725 gainLimiter
= attrList
[attrIdx
+ 1];
1726 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1730 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1731 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1739 const bool loopback
{device
->Type
== Loopback
};
1742 if(!schans
|| !stype
|| !freq
)
1744 WARN("Missing format for loopback device\n");
1745 return ALC_INVALID_VALUE
;
1747 if(!IsValidALCChannels(schans
) || !IsValidALCType(stype
) || freq
< MIN_OUTPUT_RATE
)
1748 return ALC_INVALID_VALUE
;
1749 if(schans
== ALC_BFORMAT3D_SOFT
)
1751 if(!alayout
|| !ascale
|| !aorder
)
1753 WARN("Missing ambisonic info for loopback device\n");
1754 return ALC_INVALID_VALUE
;
1756 if(!IsValidAmbiLayout(alayout
) || !IsValidAmbiScaling(ascale
))
1757 return ALC_INVALID_VALUE
;
1758 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1759 return ALC_INVALID_VALUE
;
1760 if((alayout
== ALC_FUMA_SOFT
|| ascale
== ALC_FUMA_SOFT
) && aorder
> 3)
1761 return ALC_INVALID_VALUE
;
1765 /* If a context is already running on the device, stop playback so the
1766 * device attributes can be updated.
1768 if(device
->Flags
.get
<DeviceRunning
>())
1769 device
->Backend
->stop();
1770 device
->Flags
.unset
<DeviceRunning
>();
1772 UpdateClockBase(device
);
1774 const char *devname
{nullptr};
1777 devname
= device
->DeviceName
.c_str();
1779 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
1780 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
1781 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
1783 freq
= ConfigValueUInt(devname
, nullptr, "frequency").value_or(freq
);
1785 device
->Flags
.unset
<FrequencyRequest
>();
1788 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1790 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) /
1792 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) /
1795 device
->Frequency
= freq
;
1796 device
->Flags
.set
<FrequencyRequest
>();
1799 if(auto persizeopt
= ConfigValueUInt(devname
, nullptr, "period_size"))
1800 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
1802 if(auto peropt
= ConfigValueUInt(devname
, nullptr, "periods"))
1803 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
1805 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
1809 device
->Frequency
= freq
;
1810 device
->FmtChans
= static_cast<DevFmtChannels
>(schans
);
1811 device
->FmtType
= static_cast<DevFmtType
>(stype
);
1812 if(schans
== ALC_BFORMAT3D_SOFT
)
1814 device
->mAmbiOrder
= aorder
;
1815 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1816 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1820 if(numMono
> INT_MAX
-numStereo
)
1821 numMono
= INT_MAX
-numStereo
;
1822 numMono
+= numStereo
;
1823 if(auto srcsopt
= ConfigValueUInt(devname
, nullptr, "sources"))
1825 if(*srcsopt
<= 0) numMono
= 256;
1826 else numMono
= *srcsopt
;
1829 numMono
= maxu(numMono
, 256);
1830 numStereo
= minu(numStereo
, numMono
);
1831 numMono
-= numStereo
;
1832 device
->SourcesMax
= numMono
+ numStereo
;
1834 device
->NumMonoSources
= numMono
;
1835 device
->NumStereoSources
= numStereo
;
1837 if(auto sendsopt
= ConfigValueInt(devname
, nullptr, "sends"))
1838 new_sends
= minu(numSends
, static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
1840 new_sends
= numSends
;
1843 if(device
->Flags
.get
<DeviceRunning
>())
1844 return ALC_NO_ERROR
;
1846 device
->AvgSpeakerDist
= 0.0f
;
1847 device
->Uhj_Encoder
= nullptr;
1848 device
->AmbiDecoder
= nullptr;
1849 device
->Bs2b
= nullptr;
1850 device
->PostProcess
= nullptr;
1852 device
->Stablizer
= nullptr;
1853 device
->Limiter
= nullptr;
1854 device
->ChannelDelay
.clear();
1856 device
->Dry
.AmbiMap
.fill(BFChannelConfig
{});
1857 device
->Dry
.Buffer
= {};
1858 std::fill(std::begin(device
->NumChannelsPerOrder
), std::end(device
->NumChannelsPerOrder
), 0u);
1859 device
->RealOut
.ChannelIndex
.fill(INVALID_CHANNEL_INDEX
);
1860 device
->RealOut
.Buffer
= {};
1861 device
->MixBuffer
.clear();
1862 device
->MixBuffer
.shrink_to_fit();
1864 UpdateClockBase(device
);
1865 device
->FixedLatency
= nanoseconds::zero();
1867 device
->DitherDepth
= 0.0f
;
1868 device
->DitherSeed
= DitherRNGSeed
;
1870 /*************************************************************************
1871 * Update device format request if HRTF is requested
1873 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1874 if(device
->Type
!= Loopback
)
1876 if(auto hrtfopt
= ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf"))
1878 const char *hrtf
{hrtfopt
->c_str()};
1879 if(al::strcasecmp(hrtf
, "true") == 0)
1880 hrtf_userreq
= Hrtf_Enable
;
1881 else if(al::strcasecmp(hrtf
, "false") == 0)
1882 hrtf_userreq
= Hrtf_Disable
;
1883 else if(al::strcasecmp(hrtf
, "auto") != 0)
1884 ERR("Unexpected hrtf value: %s\n", hrtf
);
1887 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1889 HrtfEntry
*hrtf
{nullptr};
1890 if(device
->HrtfList
.empty())
1891 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
1892 if(!device
->HrtfList
.empty())
1894 if(hrtf_id
>= 0 && static_cast<ALuint
>(hrtf_id
) < device
->HrtfList
.size())
1895 hrtf
= GetLoadedHrtf(device
->HrtfList
[static_cast<ALuint
>(hrtf_id
)].hrtf
);
1897 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
1902 device
->FmtChans
= DevFmtStereo
;
1903 device
->Frequency
= hrtf
->sampleRate
;
1904 device
->Flags
.set
<ChannelsRequest
, FrequencyRequest
>();
1905 if(HrtfEntry
*oldhrtf
{device
->mHrtf
})
1907 device
->mHrtf
= hrtf
;
1911 hrtf_userreq
= Hrtf_Default
;
1912 hrtf_appreq
= Hrtf_Disable
;
1913 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
1918 oldFreq
= device
->Frequency
;
1919 oldChans
= device
->FmtChans
;
1920 oldType
= device
->FmtType
;
1922 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
1923 device
->Flags
.get
<ChannelsRequest
>()?"*":"", DevFmtChannelsString(device
->FmtChans
),
1924 device
->Flags
.get
<SampleTypeRequest
>()?"*":"", DevFmtTypeString(device
->FmtType
),
1925 device
->Flags
.get
<FrequencyRequest
>()?"*":"", device
->Frequency
,
1926 device
->UpdateSize
, device
->BufferSize
);
1929 if(device
->Backend
->reset() == false)
1930 return ALC_INVALID_DEVICE
;
1932 catch(std::exception
&e
) {
1933 ERR("Device reset failed: %s\n", e
.what());
1934 return ALC_INVALID_DEVICE
;
1937 if(device
->FmtChans
!= oldChans
&& device
->Flags
.get
<ChannelsRequest
>())
1939 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1940 DevFmtChannelsString(device
->FmtChans
));
1941 device
->Flags
.unset
<ChannelsRequest
>();
1943 if(device
->FmtType
!= oldType
&& device
->Flags
.get
<SampleTypeRequest
>())
1945 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1946 DevFmtTypeString(device
->FmtType
));
1947 device
->Flags
.unset
<SampleTypeRequest
>();
1949 if(device
->Frequency
!= oldFreq
&& device
->Flags
.get
<FrequencyRequest
>())
1951 WARN("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1952 device
->Flags
.unset
<FrequencyRequest
>();
1955 TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
1956 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
1957 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
1959 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
1961 device
->NumAuxSends
= new_sends
;
1962 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
1963 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
1964 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
1966 /* Enable the stablizer only for formats that have front-left, front-right,
1967 * and front-center outputs.
1969 switch(device
->FmtChans
)
1975 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "front-stablizer", 0))
1977 auto stablizer
= al::make_unique
<FrontStablizer
>();
1978 /* Initialize band-splitting filters for the front-left and front-
1979 * right channels, with a crossover at 5khz (could be higher).
1981 const ALfloat scale
{5000.0f
/ static_cast<ALfloat
>(device
->Frequency
)};
1983 stablizer
->LFilter
.init(scale
);
1984 stablizer
->RFilter
= stablizer
->LFilter
;
1986 device
->Stablizer
= std::move(stablizer
);
1987 /* NOTE: Don't know why this has to be "copied" into a local static
1988 * constexpr variable to avoid a reference on
1989 * FrontStablizer::DelayLength...
1991 static constexpr size_t StablizerDelay
{FrontStablizer::DelayLength
};
1992 device
->FixedLatency
+= nanoseconds
{seconds
{StablizerDelay
}} / device
->Frequency
;
2001 TRACE("Front stablizer %s\n", device
->Stablizer
? "enabled" : "disabled");
2003 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2006 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth").value_or(0)};
2009 switch(device
->FmtType
)
2028 depth
= clampi(depth
, 2, 24);
2029 device
->DitherDepth
= std::pow(2.0f
, static_cast<ALfloat
>(depth
-1));
2032 if(!(device
->DitherDepth
> 0.0f
))
2033 TRACE("Dithering disabled\n");
2035 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2036 device
->DitherDepth
);
2038 device
->LimiterState
= gainLimiter
;
2039 if(auto limopt
= ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter"))
2040 gainLimiter
= *limopt
? ALC_TRUE
: ALC_FALSE
;
2042 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2043 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2044 * output (where samples must be clamped), and don't for floating-point
2045 * (which can take unclamped samples).
2047 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2049 switch(device
->FmtType
)
2057 gainLimiter
= ALC_TRUE
;
2060 gainLimiter
= ALC_FALSE
;
2064 if(gainLimiter
== ALC_FALSE
)
2065 TRACE("Output limiter disabled\n");
2068 ALfloat thrshld
= 1.0f
;
2069 switch(device
->FmtType
)
2073 thrshld
= 127.0f
/ 128.0f
;
2077 thrshld
= 32767.0f
/ 32768.0f
;
2084 if(device
->DitherDepth
> 0.0f
)
2085 thrshld
-= 1.0f
/ device
->DitherDepth
;
2087 const float thrshld_dB
{std::log10(thrshld
) * 20.0f
};
2088 auto limiter
= CreateDeviceLimiter(device
, thrshld_dB
);
2089 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2090 device
->FixedLatency
+= nanoseconds
{seconds
{limiter
->getLookAhead()}} / device
->Frequency
;
2091 device
->Limiter
= std::move(limiter
);
2092 TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB
);
2095 TRACE("Fixed device latency: %" PRId64
"ns\n", int64_t{device
->FixedLatency
.count()});
2097 /* Need to delay returning failure until replacement Send arrays have been
2098 * allocated with the appropriate size.
2100 update_failed
= AL_FALSE
;
2101 FPUCtl mixer_mode
{};
2102 for(ALCcontext
*context
: *device
->mContexts
.load())
2104 if(context
->mDefaultSlot
)
2106 ALeffectslot
*slot
= context
->mDefaultSlot
.get();
2107 aluInitEffectPanning(slot
, device
);
2109 EffectState
*state
{slot
->Effect
.State
};
2110 state
->mOutTarget
= device
->Dry
.Buffer
;
2111 if(state
->deviceUpdate(device
) == AL_FALSE
)
2112 update_failed
= AL_TRUE
;
2114 UpdateEffectSlotProps(slot
, context
);
2117 std::unique_lock
<std::mutex
> proplock
{context
->mPropLock
};
2118 std::unique_lock
<std::mutex
> slotlock
{context
->mEffectSlotLock
};
2119 for(auto &sublist
: context
->mEffectSlotList
)
2121 uint64_t usemask
= ~sublist
.FreeMask
;
2124 ALsizei idx
= CTZ64(usemask
);
2125 ALeffectslot
*slot
= sublist
.EffectSlots
+ idx
;
2127 usemask
&= ~(1_u64
<< idx
);
2129 aluInitEffectPanning(slot
, device
);
2131 EffectState
*state
{slot
->Effect
.State
};
2132 state
->mOutTarget
= device
->Dry
.Buffer
;
2133 if(state
->deviceUpdate(device
) == AL_FALSE
)
2134 update_failed
= AL_TRUE
;
2136 UpdateEffectSlotProps(slot
, context
);
2141 std::unique_lock
<std::mutex
> srclock
{context
->mSourceLock
};
2142 for(auto &sublist
: context
->mSourceList
)
2144 uint64_t usemask
= ~sublist
.FreeMask
;
2147 ALsizei idx
= CTZ64(usemask
);
2148 ALsource
*source
= sublist
.Sources
+ idx
;
2150 usemask
&= ~(1_u64
<< idx
);
2152 if(old_sends
!= device
->NumAuxSends
)
2154 if(source
->Send
.size() > device
->NumAuxSends
)
2156 auto clear_send
= [](ALsource::SendData
&send
) -> void
2159 DecrementRef(send
.Slot
->ref
);
2160 send
.Slot
= nullptr;
2162 auto send_begin
= source
->Send
.begin() +
2163 static_cast<ptrdiff_t>(device
->NumAuxSends
);
2164 std::for_each(send_begin
, source
->Send
.end(), clear_send
);
2167 source
->Send
.resize(device
->NumAuxSends
,
2168 {nullptr, 1.0f
, 1.0f
, LOWPASSFREQREF
, 1.0f
, HIGHPASSFREQREF
});
2169 source
->Send
.shrink_to_fit();
2172 source
->PropsClean
.clear(std::memory_order_release
);
2176 /* Clear any pre-existing voice property structs, in case the number of
2177 * auxiliary sends is changing. Active sources will have updates
2178 * respecified in UpdateAllSourceProps.
2180 ALvoiceProps
*vprops
{context
->mFreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2183 ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2188 if(device
->NumAuxSends
< old_sends
)
2190 const ALuint num_sends
{device
->NumAuxSends
};
2191 /* Clear extraneous property set sends. */
2192 auto clear_sends
= [num_sends
](ALvoice
&voice
) -> void
2194 std::fill(std::begin(voice
.mProps
.Send
)+num_sends
, std::end(voice
.mProps
.Send
),
2195 ALvoiceProps::SendData
{});
2197 std::fill(voice
.mSend
.begin()+num_sends
, voice
.mSend
.end(), ALvoice::TargetData
{});
2198 auto clear_chan_sends
= [num_sends
](ALvoice::ChannelData
&chandata
) -> void
2200 std::fill(chandata
.mWetParams
.begin()+num_sends
, chandata
.mWetParams
.end(),
2203 std::for_each(voice
.mChans
.begin(), voice
.mChans
.end(), clear_chan_sends
);
2205 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), clear_sends
);
2207 auto reset_voice
= [device
](ALvoice
&voice
) -> void
2209 delete voice
.mUpdate
.exchange(nullptr, std::memory_order_acq_rel
);
2211 /* Force the voice to stopped if it was stopping. */
2212 ALvoice::State vstate
{ALvoice::Stopping
};
2213 voice
.mPlayState
.compare_exchange_strong(vstate
, ALvoice::Stopped
,
2214 std::memory_order_acquire
, std::memory_order_acquire
);
2215 if(voice
.mSourceID
.load(std::memory_order_relaxed
) == 0u)
2218 if(device
->AvgSpeakerDist
> 0.0f
)
2220 /* Reinitialize the NFC filters for new parameters. */
2221 const ALfloat w1
{SPEEDOFSOUNDMETRESPERSEC
/
2222 (device
->AvgSpeakerDist
* static_cast<float>(device
->Frequency
))};
2223 auto init_nfc
= [w1
](ALvoice::ChannelData
&chandata
) -> void
2224 { chandata
.mDryParams
.NFCtrlFilter
.init(w1
); };
2225 std::for_each(voice
.mChans
.begin(), voice
.mChans
.begin()+voice
.mNumChannels
,
2229 std::for_each(context
->mVoices
.begin(), context
->mVoices
.end(), reset_voice
);
2232 context
->mPropsClean
.test_and_set(std::memory_order_release
);
2233 UpdateContextProps(context
);
2234 context
->mListener
.PropsClean
.test_and_set(std::memory_order_release
);
2235 UpdateListenerProps(context
);
2236 UpdateAllSourceProps(context
);
2240 return ALC_INVALID_DEVICE
;
2242 if(!device
->Flags
.get
<DevicePaused
>())
2245 auto backend
= device
->Backend
.get();
2246 if(!backend
->start())
2247 throw al::backend_exception
{ALC_INVALID_DEVICE
, "Backend error"};
2248 device
->Flags
.set
<DeviceRunning
>();
2250 catch(al::backend_exception
& e
) {
2251 WARN("Failed to start playback: %s\n", e
.what());
2252 return ALC_INVALID_DEVICE
;
2256 return ALC_NO_ERROR
;
2260 ALCdevice::ALCdevice(DeviceType type
) : Type
{type
}, mContexts
{&EmptyContextArray
}
2264 /* ALCdevice::~ALCdevice
2266 * Frees the device structure, and destroys any objects the app failed to
2267 * delete. Called once there's no more references on the device.
2269 ALCdevice::~ALCdevice()
2271 TRACE("Freeing device %p\n", decltype(std::declval
<void*>()){this});
2275 size_t count
{std::accumulate(BufferList
.cbegin(), BufferList
.cend(), size_t{0u},
2276 [](size_t cur
, const BufferSubList
&sublist
) noexcept
-> size_t
2277 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2280 WARN("%zu Buffer%s not deleted\n", count
, (count
==1)?"":"s");
2282 count
= std::accumulate(EffectList
.cbegin(), EffectList
.cend(), size_t{0u},
2283 [](size_t cur
, const EffectSubList
&sublist
) noexcept
-> size_t
2284 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2287 WARN("%zu Effect%s not deleted\n", count
, (count
==1)?"":"s");
2289 count
= std::accumulate(FilterList
.cbegin(), FilterList
.cend(), size_t{0u},
2290 [](size_t cur
, const FilterSubList
&sublist
) noexcept
-> size_t
2291 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2294 WARN("%zu Filter%s not deleted\n", count
, (count
==1)?"":"s");
2300 auto *oldarray
= mContexts
.exchange(nullptr, std::memory_order_relaxed
);
2301 if(oldarray
!= &EmptyContextArray
) delete oldarray
;
2307 * Checks if the device handle is valid, and returns a new reference if so.
2309 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2311 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2312 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
);
2313 if(iter
!= DeviceList
.cend() && *iter
== device
)
2319 ALCcontext::ALCcontext(al::intrusive_ptr
<ALCdevice
> device
) : mDevice
{std::move(device
)}
2321 mPropsClean
.test_and_set(std::memory_order_relaxed
);
2324 ALCcontext::~ALCcontext()
2326 TRACE("Freeing context %p\n", decltype(std::declval
<void*>()){this});
2329 ALcontextProps
*cprops
{mUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
2335 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
2338 ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2343 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
2345 count
= std::accumulate(mSourceList
.cbegin(), mSourceList
.cend(), size_t{0u},
2346 [](size_t cur
, const SourceSubList
&sublist
) noexcept
-> size_t
2347 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2350 WARN("%zu Source%s not deleted\n", count
, (count
==1)?"":"s");
2351 mSourceList
.clear();
2355 ALeffectslotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
2358 ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2359 if(eprops
->State
) eprops
->State
->release();
2364 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2366 delete mActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
);
2367 mDefaultSlot
= nullptr;
2369 count
= std::accumulate(mEffectSlotList
.cbegin(), mEffectSlotList
.cend(), size_t{0u},
2370 [](size_t cur
, const EffectSlotSubList
&sublist
) noexcept
-> size_t
2371 { return cur
+ static_cast<ALuint
>(POPCNT64(~sublist
.FreeMask
)); }
2374 WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count
, (count
==1)?"":"s");
2375 mEffectSlotList
.clear();
2376 mNumEffectSlots
= 0;
2379 ALvoiceProps
*vprops
{mFreeVoiceProps
.exchange(nullptr, std::memory_order_acquire
)};
2382 ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2387 TRACE("Freed %zu voice property object%s\n", count
, (count
==1)?"":"s");
2392 ALlistenerProps
*lprops
{mListener
.Params
.Update
.exchange(nullptr, std::memory_order_relaxed
)};
2398 lprops
= mFreeListenerProps
.exchange(nullptr, std::memory_order_acquire
);
2401 ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2406 TRACE("Freed %zu listener property object%s\n", count
, (count
==1)?"":"s");
2411 auto evt_vec
= mAsyncEvents
->getReadVector();
2412 if(evt_vec
.first
.len
> 0)
2414 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.first
.buf
), evt_vec
.first
.len
);
2415 count
+= evt_vec
.first
.len
;
2417 if(evt_vec
.second
.len
> 0)
2419 al::destroy_n(reinterpret_cast<AsyncEvent
*>(evt_vec
.second
.buf
), evt_vec
.second
.len
);
2420 count
+= evt_vec
.second
.len
;
2423 TRACE("Destructed %zu orphaned event%s\n", count
, (count
==1)?"":"s");
2424 mAsyncEvents
->readAdvance(count
);
2428 void ALCcontext::init()
2430 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& mDevice
->Type
== Playback
)
2432 mDefaultSlot
= std::unique_ptr
<ALeffectslot
>{new ALeffectslot
{}};
2433 if(InitEffectSlot(mDefaultSlot
.get()) == AL_NO_ERROR
)
2434 aluInitEffectPanning(mDefaultSlot
.get(), mDevice
.get());
2437 mDefaultSlot
= nullptr;
2438 ERR("Failed to initialize the default effect slot\n");
2442 ALeffectslotArray
*auxslots
;
2444 auxslots
= ALeffectslot::CreatePtrArray(0);
2447 auxslots
= ALeffectslot::CreatePtrArray(1);
2448 (*auxslots
)[0] = mDefaultSlot
.get();
2450 mActiveAuxSlots
.store(auxslots
, std::memory_order_relaxed
);
2452 mExtensionList
= alExtList
;
2455 mListener
.Params
.Matrix
= alu::Matrix::Identity();
2456 mListener
.Params
.Velocity
= alu::Vector
{};
2457 mListener
.Params
.Gain
= mListener
.Gain
;
2458 mListener
.Params
.MetersPerUnit
= mListener
.mMetersPerUnit
;
2459 mListener
.Params
.DopplerFactor
= mDopplerFactor
;
2460 mListener
.Params
.SpeedOfSound
= mSpeedOfSound
* mDopplerVelocity
;
2461 mListener
.Params
.SourceDistanceModel
= mSourceDistanceModel
;
2462 mListener
.Params
.mDistanceModel
= mDistanceModel
;
2465 mAsyncEvents
= CreateRingBuffer(511, sizeof(AsyncEvent
), false);
2466 StartEventThrd(this);
2469 mVoices
.reserve(256);
2473 bool ALCcontext::deinit()
2475 if(LocalContext
.get() == this)
2477 WARN("%p released while current on thread\n", decltype(std::declval
<void*>()){this});
2478 LocalContext
.set(nullptr);
2482 ALCcontext
*origctx
{this};
2483 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2487 /* First make sure this context exists in the device's list. */
2488 auto *oldarray
= mDevice
->mContexts
.load(std::memory_order_acquire
);
2489 if(auto toremove
= static_cast<size_t>(std::count(oldarray
->begin(), oldarray
->end(), this)))
2491 using ContextArray
= al::FlexArray
<ALCcontext
*>;
2492 auto alloc_ctx_array
= [](const size_t count
) -> ContextArray
*
2494 if(count
== 0) return &EmptyContextArray
;
2495 return ContextArray::Create(count
).release();
2497 auto *newarray
= alloc_ctx_array(oldarray
->size() - toremove
);
2499 /* Copy the current/old context handles to the new array, excluding the
2502 std::copy_if(oldarray
->begin(), oldarray
->end(), newarray
->begin(),
2503 std::bind(std::not_equal_to
<ALCcontext
*>{}, _1
, this));
2505 /* Store the new context array in the device. Wait for any current mix
2506 * to finish before deleting the old array.
2508 mDevice
->mContexts
.store(newarray
);
2509 if(oldarray
!= &EmptyContextArray
)
2511 while((mDevice
->MixCount
.load(std::memory_order_acquire
)&1))
2512 std::this_thread::yield();
2516 ret
= !newarray
->empty();
2519 ret
= !oldarray
->empty();
2521 StopEventThrd(this);
2529 * Checks if the given context is valid, returning a new reference to it if so.
2531 static ContextRef
VerifyContext(ALCcontext
*context
)
2533 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2534 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
);
2535 if(iter
!= ContextList
.cend() && *iter
== context
)
2542 * Returns a new reference to the currently active context for this thread.
2544 ContextRef
GetContextRef(void)
2546 ALCcontext
*context
{LocalContext
.get()};
2551 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2552 context
= GlobalContext
.load(std::memory_order_acquire
);
2553 if(context
) context
->add_ref();
2555 return ContextRef
{context
};
2559 /************************************************
2560 * Standard ALC functions
2561 ************************************************/
2565 * Return last ALC generated error code for the given device
2567 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2570 DeviceRef dev
{VerifyDevice(device
)};
2571 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2572 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2577 /* alcSuspendContext
2579 * Suspends updates for the given context
2581 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2587 ContextRef ctx
{VerifyContext(context
)};
2589 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2591 ctx
->deferUpdates();
2595 /* alcProcessContext
2597 * Resumes processing updates for the given context
2599 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2605 ContextRef ctx
{VerifyContext(context
)};
2607 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2609 ctx
->processUpdates();
2616 * Returns information about the device, and error strings
2618 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2621 const ALCchar
*value
= nullptr;
2629 case ALC_INVALID_ENUM
:
2630 value
= alcErrInvalidEnum
;
2633 case ALC_INVALID_VALUE
:
2634 value
= alcErrInvalidValue
;
2637 case ALC_INVALID_DEVICE
:
2638 value
= alcErrInvalidDevice
;
2641 case ALC_INVALID_CONTEXT
:
2642 value
= alcErrInvalidContext
;
2645 case ALC_OUT_OF_MEMORY
:
2646 value
= alcErrOutOfMemory
;
2649 case ALC_DEVICE_SPECIFIER
:
2650 value
= alcDefaultName
;
2653 case ALC_ALL_DEVICES_SPECIFIER
:
2654 if(DeviceRef dev
{VerifyDevice(Device
)})
2655 value
= dev
->DeviceName
.c_str();
2658 ProbeAllDevicesList();
2659 value
= alcAllDevicesList
.c_str();
2663 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2664 if(DeviceRef dev
{VerifyDevice(Device
)})
2665 value
= dev
->DeviceName
.c_str();
2668 ProbeCaptureDeviceList();
2669 value
= alcCaptureDeviceList
.c_str();
2673 /* Default devices are always first in the list */
2674 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2675 value
= alcDefaultName
;
2678 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2679 if(alcAllDevicesList
.empty())
2680 ProbeAllDevicesList();
2682 /* Copy first entry as default. */
2683 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2684 value
= alcDefaultAllDevicesSpecifier
.c_str();
2687 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2688 if(alcCaptureDeviceList
.empty())
2689 ProbeCaptureDeviceList();
2691 /* Copy first entry as default. */
2692 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2693 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
2696 case ALC_EXTENSIONS
:
2697 if(VerifyDevice(Device
))
2698 value
= alcExtensionList
;
2700 value
= alcNoDeviceExtList
;
2703 case ALC_HRTF_SPECIFIER_SOFT
:
2704 if(DeviceRef dev
{VerifyDevice(Device
)})
2706 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
2707 value
= (dev
->mHrtf
? dev
->HrtfName
.c_str() : "");
2710 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2714 alcSetError(VerifyDevice(Device
).get(), ALC_INVALID_ENUM
);
2723 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2725 if(device
->Type
== Capture
) return 9;
2726 if(device
->Type
!= Loopback
) return 29;
2727 if(device
->FmtChans
== DevFmtAmbi3D
)
2732 static size_t GetIntegerv(ALCdevice
*device
, ALCenum param
, const al::span
<ALCint
> values
)
2738 alcSetError(device
, ALC_INVALID_VALUE
);
2746 case ALC_MAJOR_VERSION
:
2747 values
[0] = alcMajorVersion
;
2749 case ALC_MINOR_VERSION
:
2750 values
[0] = alcMinorVersion
;
2753 case ALC_ATTRIBUTES_SIZE
:
2754 case ALC_ALL_ATTRIBUTES
:
2758 case ALC_MONO_SOURCES
:
2759 case ALC_STEREO_SOURCES
:
2760 case ALC_CAPTURE_SAMPLES
:
2761 case ALC_FORMAT_CHANNELS_SOFT
:
2762 case ALC_FORMAT_TYPE_SOFT
:
2763 case ALC_AMBISONIC_LAYOUT_SOFT
:
2764 case ALC_AMBISONIC_SCALING_SOFT
:
2765 case ALC_AMBISONIC_ORDER_SOFT
:
2766 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
2767 alcSetError(nullptr, ALC_INVALID_DEVICE
);
2771 alcSetError(nullptr, ALC_INVALID_ENUM
);
2777 if(device
->Type
== Capture
)
2781 case ALC_ATTRIBUTES_SIZE
:
2782 values
[0] = NumAttrsForDevice(device
);
2785 case ALC_ALL_ATTRIBUTES
:
2787 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2788 alcSetError(device
, ALC_INVALID_VALUE
);
2791 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2792 values
[i
++] = ALC_MAJOR_VERSION
;
2793 values
[i
++] = alcMajorVersion
;
2794 values
[i
++] = ALC_MINOR_VERSION
;
2795 values
[i
++] = alcMinorVersion
;
2796 values
[i
++] = ALC_CAPTURE_SAMPLES
;
2797 values
[i
++] = static_cast<int>(device
->Backend
->availableSamples());
2798 values
[i
++] = ALC_CONNECTED
;
2799 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
2804 case ALC_MAJOR_VERSION
:
2805 values
[0] = alcMajorVersion
;
2807 case ALC_MINOR_VERSION
:
2808 values
[0] = alcMinorVersion
;
2811 case ALC_CAPTURE_SAMPLES
:
2813 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2814 values
[0] = static_cast<int>(device
->Backend
->availableSamples());
2820 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2821 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
2826 alcSetError(device
, ALC_INVALID_ENUM
);
2834 case ALC_ATTRIBUTES_SIZE
:
2835 values
[0] = NumAttrsForDevice(device
);
2838 case ALC_ALL_ATTRIBUTES
:
2840 if(values
.size() < static_cast<size_t>(NumAttrsForDevice(device
)))
2841 alcSetError(device
, ALC_INVALID_VALUE
);
2844 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2845 values
[i
++] = ALC_MAJOR_VERSION
;
2846 values
[i
++] = alcMajorVersion
;
2847 values
[i
++] = ALC_MINOR_VERSION
;
2848 values
[i
++] = alcMinorVersion
;
2849 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
2850 values
[i
++] = alcEFXMajorVersion
;
2851 values
[i
++] = ALC_EFX_MINOR_VERSION
;
2852 values
[i
++] = alcEFXMinorVersion
;
2854 values
[i
++] = ALC_FREQUENCY
;
2855 values
[i
++] = static_cast<int>(device
->Frequency
);
2856 if(device
->Type
!= Loopback
)
2858 values
[i
++] = ALC_REFRESH
;
2859 values
[i
++] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2861 values
[i
++] = ALC_SYNC
;
2862 values
[i
++] = ALC_FALSE
;
2866 if(device
->FmtChans
== DevFmtAmbi3D
)
2868 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
2869 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
2871 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
2872 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
2874 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
2875 values
[i
++] = static_cast<ALCint
>(device
->mAmbiOrder
);
2878 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2879 values
[i
++] = device
->FmtChans
;
2881 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2882 values
[i
++] = device
->FmtType
;
2885 values
[i
++] = ALC_MONO_SOURCES
;
2886 values
[i
++] = static_cast<int>(device
->NumMonoSources
);
2888 values
[i
++] = ALC_STEREO_SOURCES
;
2889 values
[i
++] = static_cast<int>(device
->NumStereoSources
);
2891 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2892 values
[i
++] = static_cast<ALCint
>(device
->NumAuxSends
);
2894 values
[i
++] = ALC_HRTF_SOFT
;
2895 values
[i
++] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
2897 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
2898 values
[i
++] = device
->HrtfStatus
;
2900 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
2901 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
2903 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
2904 values
[i
++] = MAX_AMBI_ORDER
;
2910 case ALC_MAJOR_VERSION
:
2911 values
[0] = alcMajorVersion
;
2914 case ALC_MINOR_VERSION
:
2915 values
[0] = alcMinorVersion
;
2918 case ALC_EFX_MAJOR_VERSION
:
2919 values
[0] = alcEFXMajorVersion
;
2922 case ALC_EFX_MINOR_VERSION
:
2923 values
[0] = alcEFXMinorVersion
;
2927 values
[0] = static_cast<int>(device
->Frequency
);
2931 if(device
->Type
== Loopback
)
2933 alcSetError(device
, ALC_INVALID_DEVICE
);
2937 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
2938 values
[0] = static_cast<int>(device
->Frequency
/ device
->UpdateSize
);
2943 if(device
->Type
== Loopback
)
2945 alcSetError(device
, ALC_INVALID_DEVICE
);
2948 values
[0] = ALC_FALSE
;
2951 case ALC_FORMAT_CHANNELS_SOFT
:
2952 if(device
->Type
!= Loopback
)
2954 alcSetError(device
, ALC_INVALID_DEVICE
);
2957 values
[0] = device
->FmtChans
;
2960 case ALC_FORMAT_TYPE_SOFT
:
2961 if(device
->Type
!= Loopback
)
2963 alcSetError(device
, ALC_INVALID_DEVICE
);
2966 values
[0] = device
->FmtType
;
2969 case ALC_AMBISONIC_LAYOUT_SOFT
:
2970 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2972 alcSetError(device
, ALC_INVALID_DEVICE
);
2975 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
2978 case ALC_AMBISONIC_SCALING_SOFT
:
2979 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2981 alcSetError(device
, ALC_INVALID_DEVICE
);
2984 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
2987 case ALC_AMBISONIC_ORDER_SOFT
:
2988 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
2990 alcSetError(device
, ALC_INVALID_DEVICE
);
2993 values
[0] = static_cast<int>(device
->mAmbiOrder
);
2996 case ALC_MONO_SOURCES
:
2997 values
[0] = static_cast<int>(device
->NumMonoSources
);
3000 case ALC_STEREO_SOURCES
:
3001 values
[0] = static_cast<int>(device
->NumStereoSources
);
3004 case ALC_MAX_AUXILIARY_SENDS
:
3005 values
[0] = static_cast<ALCint
>(device
->NumAuxSends
);
3010 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3011 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3016 values
[0] = (device
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3019 case ALC_HRTF_STATUS_SOFT
:
3020 values
[0] = device
->HrtfStatus
;
3023 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3025 std::lock_guard
<std::mutex
> _
{device
->StateLock
};
3026 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3027 values
[0] = static_cast<ALCint
>(minz(device
->HrtfList
.size(),
3028 std::numeric_limits
<ALCint
>::max()));
3032 case ALC_OUTPUT_LIMITER_SOFT
:
3033 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3036 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3037 values
[0] = MAX_AMBI_ORDER
;
3041 alcSetError(device
, ALC_INVALID_ENUM
);
3048 * Returns information about the device and the version of OpenAL
3050 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3053 DeviceRef dev
{VerifyDevice(device
)};
3054 if(size
<= 0 || values
== nullptr)
3055 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3057 GetIntegerv(dev
.get(), param
, {values
, values
+size
});
3061 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3064 DeviceRef dev
{VerifyDevice(device
)};
3065 if(size
<= 0 || values
== nullptr)
3066 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3067 else if(!dev
|| dev
->Type
== Capture
)
3069 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3070 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3071 std::copy_n(ivals
.begin(), got
, values
);
3077 case ALC_ATTRIBUTES_SIZE
:
3078 *values
= NumAttrsForDevice(dev
.get())+4;
3081 case ALC_ALL_ATTRIBUTES
:
3082 if(size
< NumAttrsForDevice(dev
.get())+4)
3083 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3087 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3088 values
[i
++] = ALC_FREQUENCY
;
3089 values
[i
++] = dev
->Frequency
;
3091 if(dev
->Type
!= Loopback
)
3093 values
[i
++] = ALC_REFRESH
;
3094 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3096 values
[i
++] = ALC_SYNC
;
3097 values
[i
++] = ALC_FALSE
;
3101 if(dev
->FmtChans
== DevFmtAmbi3D
)
3103 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3104 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiLayout
);
3106 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3107 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiScale
);
3109 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3110 values
[i
++] = dev
->mAmbiOrder
;
3113 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3114 values
[i
++] = dev
->FmtChans
;
3116 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3117 values
[i
++] = dev
->FmtType
;
3120 values
[i
++] = ALC_MONO_SOURCES
;
3121 values
[i
++] = dev
->NumMonoSources
;
3123 values
[i
++] = ALC_STEREO_SOURCES
;
3124 values
[i
++] = dev
->NumStereoSources
;
3126 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3127 values
[i
++] = dev
->NumAuxSends
;
3129 values
[i
++] = ALC_HRTF_SOFT
;
3130 values
[i
++] = (dev
->mHrtf
? ALC_TRUE
: ALC_FALSE
);
3132 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3133 values
[i
++] = dev
->HrtfStatus
;
3135 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3136 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3138 ClockLatency clock
{GetClockLatency(dev
.get())};
3139 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3140 values
[i
++] = clock
.ClockTime
.count();
3142 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3143 values
[i
++] = clock
.Latency
.count();
3149 case ALC_DEVICE_CLOCK_SOFT
:
3150 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3151 nanoseconds basecount
;
3155 while(((refcount
=ReadRef(dev
->MixCount
))&1) != 0)
3156 std::this_thread::yield();
3157 basecount
= dev
->ClockBase
;
3158 samplecount
= dev
->SamplesDone
;
3159 } while(refcount
!= ReadRef(dev
->MixCount
));
3160 basecount
+= nanoseconds
{seconds
{samplecount
}} / dev
->Frequency
;
3161 *values
= basecount
.count();
3165 case ALC_DEVICE_LATENCY_SOFT
:
3166 { std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3167 ClockLatency clock
{GetClockLatency(dev
.get())};
3168 *values
= clock
.Latency
.count();
3172 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3174 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3177 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3178 ClockLatency clock
{GetClockLatency(dev
.get())};
3179 values
[0] = clock
.ClockTime
.count();
3180 values
[1] = clock
.Latency
.count();
3185 auto ivals
= al::vector
<ALCint
>(static_cast<ALuint
>(size
));
3186 size_t got
{GetIntegerv(dev
.get(), pname
, {ivals
.data(), ivals
.size()})};
3187 std::copy_n(ivals
.begin(), got
, values
);
3194 /* alcIsExtensionPresent
3196 * Determines if there is support for a particular extension
3198 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3201 DeviceRef dev
{VerifyDevice(device
)};
3203 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3206 size_t len
= strlen(extName
);
3207 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3210 if(al::strncasecmp(ptr
, extName
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3213 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3217 } while(isspace(*ptr
));
3226 /* alcGetProcAddress
3228 * Retrieves the function address for a particular extension function
3230 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3235 DeviceRef dev
{VerifyDevice(device
)};
3236 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3240 for(const auto &func
: alcFunctions
)
3242 if(strcmp(func
.funcName
, funcName
) == 0)
3243 return func
.address
;
3253 * Get the value for a particular ALC enumeration name
3255 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3260 DeviceRef dev
{VerifyDevice(device
)};
3261 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3265 for(const auto &enm
: alcEnumerations
)
3267 if(strcmp(enm
.enumName
, enumName
) == 0)
3278 * Create and attach a context to the given device.
3280 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3283 /* Explicitly hold the list lock while taking the StateLock in case the
3284 * device is asynchronously destroyed, to ensure this new context is
3285 * properly cleaned up after being made.
3287 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3288 DeviceRef dev
{VerifyDevice(device
)};
3289 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3292 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3295 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3298 dev
->LastError
.store(ALC_NO_ERROR
);
3300 ALCenum err
{UpdateDeviceParams(dev
.get(), attrList
)};
3301 if(err
!= ALC_NO_ERROR
)
3303 alcSetError(dev
.get(), err
);
3304 if(err
== ALC_INVALID_DEVICE
)
3305 aluHandleDisconnect(dev
.get(), "Device update failure");
3309 ContextRef context
{new ALCcontext
{dev
}};
3312 if(auto volopt
= ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust"))
3314 const ALfloat valf
{*volopt
};
3315 if(!std::isfinite(valf
))
3316 ERR("volume-adjust must be finite: %f\n", valf
);
3319 const ALfloat db
{clampf(valf
, -24.0f
, 24.0f
)};
3321 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3322 context
->mGainBoost
= std::pow(10.0f
, db
/20.0f
);
3323 TRACE("volume-adjust gain: %f\n", context
->mGainBoost
);
3326 UpdateListenerProps(context
.get());
3329 using ContextArray
= al::FlexArray
<ALCcontext
*>;
3331 /* Allocate a new context array, which holds 1 more than the current/
3334 auto *oldarray
= device
->mContexts
.load();
3335 const size_t newcount
{oldarray
->size()+1};
3336 std::unique_ptr
<ContextArray
> newarray
{ContextArray::Create(newcount
)};
3338 /* Copy the current/old context handles to the new array, appending the
3341 auto iter
= std::copy(oldarray
->begin(), oldarray
->end(), newarray
->begin());
3342 *iter
= context
.get();
3344 /* Store the new context array in the device. Wait for any current mix
3345 * to finish before deleting the old array.
3347 dev
->mContexts
.store(newarray
.release());
3348 if(oldarray
!= &EmptyContextArray
)
3350 while((dev
->MixCount
.load(std::memory_order_acquire
)&1))
3351 std::this_thread::yield();
3358 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3359 auto iter
= std::lower_bound(ContextList
.cbegin(), ContextList
.cend(), context
.get());
3360 ContextList
.emplace(iter
, context
);
3363 if(context
->mDefaultSlot
)
3365 if(InitializeEffect(context
.get(), context
->mDefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3366 UpdateEffectSlotProps(context
->mDefaultSlot
.get(), context
.get());
3368 ERR("Failed to initialize the default effect\n");
3371 TRACE("Created context %p\n", decltype(std::declval
<void*>()){context
.get()});
3372 return context
.get();
3376 /* alcDestroyContext
3378 * Remove a context from its device
3380 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3383 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3384 auto iter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), context
);
3385 if(iter
== ContextList
.end() || *iter
!= context
)
3388 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3391 /* Hold an extra reference to this context so it remains valid until the
3392 * ListLock is released.
3394 ContextRef ctx
{std::move(*iter
)};
3395 ContextList
.erase(iter
);
3397 ALCdevice
*Device
{ctx
->mDevice
.get()};
3399 std::lock_guard
<std::mutex
> _
{Device
->StateLock
};
3400 if(!ctx
->deinit() && Device
->Flags
.get
<DeviceRunning
>())
3402 Device
->Backend
->stop();
3403 Device
->Flags
.unset
<DeviceRunning
>();
3409 /* alcGetCurrentContext
3411 * Returns the currently active context on the calling thread
3413 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3416 ALCcontext
*Context
{LocalContext
.get()};
3417 if(!Context
) Context
= GlobalContext
.load();
3422 /* alcGetThreadContext
3424 * Returns the currently active thread-local context
3426 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3428 { return LocalContext
.get(); }
3431 /* alcMakeContextCurrent
3433 * Makes the given context the active process-wide context, and removes the
3434 * thread-local context for the calling thread.
3436 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3439 /* context must be valid or nullptr */
3443 ctx
= VerifyContext(context
);
3446 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3450 /* Release this reference (if any) to store it in the GlobalContext
3451 * pointer. Take ownership of the reference (if any) that was previously
3454 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3456 /* Reset (decrement) the previous global reference by replacing it with the
3457 * thread-local context. Take ownership of the thread-local context
3458 * reference (if any), clearing the storage to null.
3460 ctx
= ContextRef
{LocalContext
.get()};
3461 if(ctx
) LocalContext
.set(nullptr);
3462 /* Reset (decrement) the previous thread-local reference. */
3468 /* alcSetThreadContext
3470 * Makes the given context the active context for the current thread
3472 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3475 /* context must be valid or nullptr */
3479 ctx
= VerifyContext(context
);
3482 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3486 /* context's reference count is already incremented */
3487 ContextRef old
{LocalContext
.get()};
3488 LocalContext
.set(ctx
.release());
3495 /* alcGetContextsDevice
3497 * Returns the device that a particular context is attached to
3499 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3502 ContextRef ctx
{VerifyContext(Context
)};
3505 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3508 return ctx
->mDevice
.get();
3515 * Opens the named device.
3517 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3522 if(!PlaybackFactory
)
3524 alcSetError(nullptr, ALC_INVALID_VALUE
);
3530 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3532 /* Some old Windows apps hardcode these expecting OpenAL to use a
3533 * specific audio API, even when they're not enumerated. Creative's
3534 * router effectively ignores them too.
3536 || al::strcasecmp(deviceName
, "DirectSound3D") == 0
3537 || al::strcasecmp(deviceName
, "DirectSound") == 0
3538 || al::strcasecmp(deviceName
, "MMSYSTEM") == 0
3540 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3541 deviceName
= nullptr;
3544 DeviceRef device
{new ALCdevice
{Playback
}};
3546 /* Set output format */
3547 device
->FmtChans
= DevFmtChannelsDefault
;
3548 device
->FmtType
= DevFmtTypeDefault
;
3549 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3550 device
->UpdateSize
= DEFAULT_UPDATE_SIZE
;
3551 device
->BufferSize
= DEFAULT_UPDATE_SIZE
* DEFAULT_NUM_UPDATES
;
3553 device
->SourcesMax
= 256;
3554 device
->AuxiliaryEffectSlotMax
= 64;
3555 device
->NumAuxSends
= DEFAULT_SENDS
;
3558 auto backend
= PlaybackFactory
->createBackend(device
.get(), BackendType::Playback
);
3559 backend
->open(deviceName
);
3560 device
->Backend
= std::move(backend
);
3562 catch(al::backend_exception
&e
) {
3563 WARN("Failed to open playback device: %s\n", e
.what());
3564 alcSetError(nullptr, e
.errorCode());
3568 deviceName
= device
->DeviceName
.c_str();
3569 if(auto chanopt
= ConfigValueStr(deviceName
, nullptr, "channels"))
3571 static constexpr struct ChannelMap
{
3572 const char name
[16];
3573 DevFmtChannels chans
;
3576 { "mono", DevFmtMono
, 0 },
3577 { "stereo", DevFmtStereo
, 0 },
3578 { "quad", DevFmtQuad
, 0 },
3579 { "surround51", DevFmtX51
, 0 },
3580 { "surround61", DevFmtX61
, 0 },
3581 { "surround71", DevFmtX71
, 0 },
3582 { "surround51rear", DevFmtX51Rear
, 0 },
3583 { "ambi1", DevFmtAmbi3D
, 1 },
3584 { "ambi2", DevFmtAmbi3D
, 2 },
3585 { "ambi3", DevFmtAmbi3D
, 3 },
3588 const ALCchar
*fmt
{chanopt
->c_str()};
3589 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3590 [fmt
](const ChannelMap
&entry
) -> bool
3591 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3593 if(iter
== std::end(chanlist
))
3594 ERR("Unsupported channels: %s\n", fmt
);
3597 device
->FmtChans
= iter
->chans
;
3598 device
->mAmbiOrder
= iter
->order
;
3599 device
->Flags
.set
<ChannelsRequest
>();
3602 if(auto typeopt
= ConfigValueStr(deviceName
, nullptr, "sample-type"))
3604 static constexpr struct TypeMap
{
3605 const char name
[16];
3608 { "int8", DevFmtByte
},
3609 { "uint8", DevFmtUByte
},
3610 { "int16", DevFmtShort
},
3611 { "uint16", DevFmtUShort
},
3612 { "int32", DevFmtInt
},
3613 { "uint32", DevFmtUInt
},
3614 { "float32", DevFmtFloat
},
3617 const ALCchar
*fmt
{typeopt
->c_str()};
3618 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3619 [fmt
](const TypeMap
&entry
) -> bool
3620 { return al::strcasecmp(entry
.name
, fmt
) == 0; }
3622 if(iter
== std::end(typelist
))
3623 ERR("Unsupported sample-type: %s\n", fmt
);
3626 device
->FmtType
= iter
->type
;
3627 device
->Flags
.set
<SampleTypeRequest
>();
3631 if(ALuint freq
{ConfigValueUInt(deviceName
, nullptr, "frequency").value_or(0)})
3633 if(freq
< MIN_OUTPUT_RATE
)
3635 ERR("%uhz request clamped to %uhz minimum\n", freq
, MIN_OUTPUT_RATE
);
3636 freq
= MIN_OUTPUT_RATE
;
3638 device
->UpdateSize
= (device
->UpdateSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3639 device
->BufferSize
= (device
->BufferSize
*freq
+ device
->Frequency
/2) / device
->Frequency
;
3640 device
->Frequency
= freq
;
3641 device
->Flags
.set
<FrequencyRequest
>();
3644 if(auto persizeopt
= ConfigValueUInt(deviceName
, nullptr, "period_size"))
3645 device
->UpdateSize
= clampu(*persizeopt
, 64, 8192);
3647 if(auto peropt
= ConfigValueUInt(deviceName
, nullptr, "periods"))
3648 device
->BufferSize
= device
->UpdateSize
* clampu(*peropt
, 2, 16);
3650 device
->BufferSize
= maxu(device
->BufferSize
, device
->UpdateSize
*2);
3652 if(auto srcsopt
= ConfigValueUInt(deviceName
, nullptr, "sources"))
3654 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3657 if(auto slotsopt
= ConfigValueUInt(deviceName
, nullptr, "slots"))
3660 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3663 if(auto sendsopt
= ConfigValueInt(deviceName
, nullptr, "sends"))
3664 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3665 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3667 device
->NumStereoSources
= 1;
3668 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3670 if(auto ambiopt
= ConfigValueStr(deviceName
, nullptr, "ambi-format"))
3672 const ALCchar
*fmt
{ambiopt
->c_str()};
3673 if(al::strcasecmp(fmt
, "fuma") == 0)
3675 if(device
->mAmbiOrder
> 3)
3676 ERR("FuMa is incompatible with %d%s order ambisonics (up to third-order only)\n",
3678 (((device
->mAmbiOrder
%100)/10) == 1) ? "th" :
3679 ((device
->mAmbiOrder
%10) == 1) ? "st" :
3680 ((device
->mAmbiOrder
%10) == 2) ? "nd" :
3681 ((device
->mAmbiOrder
%10) == 3) ? "rd" : "th");
3684 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3685 device
->mAmbiScale
= AmbiNorm::FuMa
;
3688 else if(al::strcasecmp(fmt
, "ambix") == 0 || al::strcasecmp(fmt
, "acn+sn3d") == 0)
3690 device
->mAmbiLayout
= AmbiLayout::ACN
;
3691 device
->mAmbiScale
= AmbiNorm::SN3D
;
3693 else if(al::strcasecmp(fmt
, "acn+n3d") == 0)
3695 device
->mAmbiLayout
= AmbiLayout::ACN
;
3696 device
->mAmbiScale
= AmbiNorm::N3D
;
3699 ERR("Unsupported ambi-format: %s\n", fmt
);
3703 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3704 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3705 DeviceList
.emplace(iter
, device
);
3708 TRACE("Created device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3709 device
->DeviceName
.c_str());
3710 return device
.get();
3716 * Closes the given device.
3718 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3721 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3722 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3723 if(iter
== DeviceList
.end() || *iter
!= device
)
3725 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3728 if((*iter
)->Type
== Capture
)
3730 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3734 /* Erase the device, and any remaining contexts left on it, from their
3737 DeviceRef dev
{std::move(*iter
)};
3738 DeviceList
.erase(iter
);
3740 std::unique_lock
<std::mutex
> statelock
{dev
->StateLock
};
3741 al::vector
<ContextRef
> orphanctxs
;
3742 for(ALCcontext
*ctx
: *dev
->mContexts
.load())
3744 auto ctxiter
= std::lower_bound(ContextList
.begin(), ContextList
.end(), ctx
);
3745 if(ctxiter
!= ContextList
.end() && *ctxiter
== ctx
)
3747 orphanctxs
.emplace_back(std::move(*ctxiter
));
3748 ContextList
.erase(ctxiter
);
3753 for(ContextRef
&context
: orphanctxs
)
3755 WARN("Releasing orphaned context %p\n", decltype(std::declval
<void*>()){context
.get()});
3760 if(dev
->Flags
.get
<DeviceRunning
>())
3761 dev
->Backend
->stop();
3762 dev
->Flags
.unset
<DeviceRunning
>();
3769 /************************************************
3770 * ALC capture functions
3771 ************************************************/
3772 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3779 alcSetError(nullptr, ALC_INVALID_VALUE
);
3785 alcSetError(nullptr, ALC_INVALID_VALUE
);
3791 if(!deviceName
[0] || al::strcasecmp(deviceName
, alcDefaultName
) == 0
3792 || al::strcasecmp(deviceName
, "openal-soft") == 0)
3793 deviceName
= nullptr;
3796 DeviceRef device
{new ALCdevice
{Capture
}};
3798 auto decompfmt
= DecomposeDevFormat(format
);
3801 alcSetError(nullptr, ALC_INVALID_ENUM
);
3805 device
->Frequency
= frequency
;
3806 device
->FmtChans
= decompfmt
->chans
;
3807 device
->FmtType
= decompfmt
->type
;
3808 device
->Flags
.set
<FrequencyRequest
, ChannelsRequest
, SampleTypeRequest
>();
3810 device
->UpdateSize
= static_cast<ALuint
>(samples
);
3811 device
->BufferSize
= static_cast<ALuint
>(samples
);
3814 TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
3815 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
3816 device
->Frequency
, device
->UpdateSize
, device
->BufferSize
);
3818 auto backend
= CaptureFactory
->createBackend(device
.get(), BackendType::Capture
);
3819 backend
->open(deviceName
);
3820 device
->Backend
= std::move(backend
);
3822 catch(al::backend_exception
&e
) {
3823 WARN("Failed to open capture device: %s\n", e
.what());
3824 alcSetError(nullptr, e
.errorCode());
3829 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
3830 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
3831 DeviceList
.emplace(iter
, device
);
3834 TRACE("Created capture device %p, \"%s\"\n", decltype(std::declval
<void*>()){device
.get()},
3835 device
->DeviceName
.c_str());
3836 return device
.get();
3840 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3843 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3844 auto iter
= std::lower_bound(DeviceList
.begin(), DeviceList
.end(), device
);
3845 if(iter
== DeviceList
.end() || *iter
!= device
)
3847 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3850 if((*iter
)->Type
!= Capture
)
3852 alcSetError(iter
->get(), ALC_INVALID_DEVICE
);
3856 DeviceRef dev
{std::move(*iter
)};
3857 DeviceList
.erase(iter
);
3860 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3861 if(dev
->Flags
.get
<DeviceRunning
>())
3862 dev
->Backend
->stop();
3863 dev
->Flags
.unset
<DeviceRunning
>();
3869 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3872 DeviceRef dev
{VerifyDevice(device
)};
3873 if(!dev
|| dev
->Type
!= Capture
)
3875 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3879 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3880 if(!dev
->Connected
.load(std::memory_order_acquire
))
3881 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3882 else if(!dev
->Flags
.get
<DeviceRunning
>())
3885 auto backend
= dev
->Backend
.get();
3886 if(!backend
->start())
3887 throw al::backend_exception
{ALC_INVALID_DEVICE
, "Device start failure"};
3888 dev
->Flags
.set
<DeviceRunning
>();
3890 catch(al::backend_exception
& e
) {
3891 aluHandleDisconnect(dev
.get(), "%s", e
.what());
3892 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3898 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3901 DeviceRef dev
{VerifyDevice(device
)};
3902 if(!dev
|| dev
->Type
!= Capture
)
3903 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3906 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3907 if(dev
->Flags
.get
<DeviceRunning
>())
3908 dev
->Backend
->stop();
3909 dev
->Flags
.unset
<DeviceRunning
>();
3914 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3917 DeviceRef dev
{VerifyDevice(device
)};
3918 if(!dev
|| dev
->Type
!= Capture
)
3920 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3924 if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
3926 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3932 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
3933 BackendBase
*backend
{dev
->Backend
.get()};
3935 const auto usamples
= static_cast<ALCuint
>(samples
);
3936 if(usamples
> backend
->availableSamples())
3938 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3942 auto *bbuffer
= static_cast<al::byte
*>(buffer
);
3943 if(ALCenum err
{backend
->captureSamples(bbuffer
, usamples
)})
3944 alcSetError(dev
.get(), err
);
3949 /************************************************
3950 * ALC loopback functions
3951 ************************************************/
3953 /* alcLoopbackOpenDeviceSOFT
3955 * Open a loopback device, for manual rendering.
3957 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3962 /* Make sure the device name, if specified, is us. */
3963 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3965 alcSetError(nullptr, ALC_INVALID_VALUE
);
3969 DeviceRef device
{new ALCdevice
{Loopback
}};
3971 device
->SourcesMax
= 256;
3972 device
->AuxiliaryEffectSlotMax
= 64;
3973 device
->NumAuxSends
= DEFAULT_SENDS
;
3976 device
->BufferSize
= 0;
3977 device
->UpdateSize
= 0;
3979 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3980 device
->FmtChans
= DevFmtChannelsDefault
;
3981 device
->FmtType
= DevFmtTypeDefault
;
3983 if(auto srcsopt
= ConfigValueUInt(nullptr, nullptr, "sources"))
3985 if(*srcsopt
> 0) device
->SourcesMax
= *srcsopt
;
3988 if(auto slotsopt
= ConfigValueUInt(nullptr, nullptr, "slots"))
3991 device
->AuxiliaryEffectSlotMax
= minu(*slotsopt
, INT_MAX
);
3994 if(auto sendsopt
= ConfigValueInt(nullptr, nullptr, "sends"))
3995 device
->NumAuxSends
= clampu(DEFAULT_SENDS
, 0,
3996 static_cast<ALuint
>(clampi(*sendsopt
, 0, MAX_SENDS
)));
3998 device
->NumStereoSources
= 1;
3999 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4002 auto backend
= LoopbackBackendFactory::getFactory().createBackend(device
.get(),
4003 BackendType::Playback
);
4004 backend
->open("Loopback");
4005 device
->Backend
= std::move(backend
);
4007 catch(al::backend_exception
&e
) {
4008 WARN("Failed to open loopback device: %s\n", e
.what());
4009 alcSetError(nullptr, e
.errorCode());
4014 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
4015 auto iter
= std::lower_bound(DeviceList
.cbegin(), DeviceList
.cend(), device
.get());
4016 DeviceList
.emplace(iter
, device
);
4019 TRACE("Created loopback device %p\n", decltype(std::declval
<void*>()){device
.get()});
4020 return device
.get();
4024 /* alcIsRenderFormatSupportedSOFT
4026 * Determines if the loopback device supports the given format for rendering.
4028 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4031 DeviceRef dev
{VerifyDevice(device
)};
4032 if(!dev
|| dev
->Type
!= Loopback
)
4033 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4035 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4038 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4046 /* alcRenderSamplesSOFT
4048 * Renders some samples into a buffer, using the format last set by the
4049 * attributes given to alcCreateContext.
4051 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4054 DeviceRef dev
{VerifyDevice(device
)};
4055 if(!dev
|| dev
->Type
!= Loopback
)
4056 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4057 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4058 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4061 BackendLockGuard _
{*dev
->Backend
};
4062 aluMixData(dev
.get(), buffer
, static_cast<ALuint
>(samples
));
4068 /************************************************
4069 * ALC DSP pause/resume functions
4070 ************************************************/
4072 /* alcDevicePauseSOFT
4074 * Pause the DSP to stop audio processing.
4076 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4079 DeviceRef dev
{VerifyDevice(device
)};
4080 if(!dev
|| dev
->Type
!= Playback
)
4081 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4084 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4085 if(dev
->Flags
.get
<DeviceRunning
>())
4086 dev
->Backend
->stop();
4087 dev
->Flags
.unset
<DeviceRunning
>();
4088 dev
->Flags
.set
<DevicePaused
>();
4093 /* alcDeviceResumeSOFT
4095 * Resume the DSP to restart audio processing.
4097 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4100 DeviceRef dev
{VerifyDevice(device
)};
4101 if(!dev
|| dev
->Type
!= Playback
)
4103 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4107 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4108 if(!dev
->Flags
.get
<DevicePaused
>())
4110 dev
->Flags
.unset
<DevicePaused
>();
4111 if(dev
->mContexts
.load()->empty())
4115 auto backend
= dev
->Backend
.get();
4116 if(!backend
->start())
4117 throw al::backend_exception
{ALC_INVALID_DEVICE
, "Device start failure"};
4118 dev
->Flags
.set
<DeviceRunning
>();
4120 catch(al::backend_exception
& e
) {
4121 aluHandleDisconnect(dev
.get(), "%s", e
.what());
4122 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4128 /************************************************
4129 * ALC HRTF functions
4130 ************************************************/
4132 /* alcGetStringiSOFT
4134 * Gets a string parameter at the given index.
4136 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4139 DeviceRef dev
{VerifyDevice(device
)};
4140 if(!dev
|| dev
->Type
== Capture
)
4141 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4142 else switch(paramName
)
4144 case ALC_HRTF_SPECIFIER_SOFT
:
4145 if(index
>= 0 && static_cast<size_t>(index
) < dev
->HrtfList
.size())
4146 return dev
->HrtfList
[static_cast<ALuint
>(index
)].name
.c_str();
4147 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4151 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4159 /* alcResetDeviceSOFT
4161 * Resets the given device output, using the specified attribute list.
4163 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4166 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4167 DeviceRef dev
{VerifyDevice(device
)};
4168 if(!dev
|| dev
->Type
== Capture
)
4171 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4174 std::lock_guard
<std::mutex
> _
{dev
->StateLock
};
4177 /* Force the backend to stop mixing first since we're resetting. Also reset
4178 * the connected state so lost devices can attempt recover.
4180 if(dev
->Flags
.get
<DeviceRunning
>())
4181 dev
->Backend
->stop();
4182 dev
->Flags
.unset
<DeviceRunning
>();
4183 device
->Connected
.store(true);
4185 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4186 if LIKELY(err
== ALC_NO_ERROR
) return ALC_TRUE
;
4188 alcSetError(dev
.get(), err
);
4189 if(err
== ALC_INVALID_DEVICE
)
4190 aluHandleDisconnect(dev
.get(), "Device start failure");