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
40 #include "alcontext.h"
42 #include "alListener.h"
47 #include "alAuxEffectSlot.h"
49 #include "mastering.h"
50 #include "bformatdec.h"
51 #include "uhjfilter.h"
54 #include "ringbuffer.h"
55 #include "filters/splitter.h"
58 #include "fpu_modes.h"
64 #include "backends/base.h"
65 #include "backends/null.h"
66 #include "backends/loopback.h"
68 #include "backends/jack.h"
70 #ifdef HAVE_PULSEAUDIO
71 #include "backends/pulseaudio.h"
74 #include "backends/alsa.h"
77 #include "backends/wasapi.h"
80 #include "backends/coreaudio.h"
83 #include "backends/opensl.h"
86 #include "backends/solaris.h"
89 #include "backends/sndio.h"
92 #include "backends/oss.h"
95 #include "backends/qsa.h"
98 #include "backends/dsound.h"
101 #include "backends/winmm.h"
103 #ifdef HAVE_PORTAUDIO
104 #include "backends/portaudio.h"
107 #include "backends/sdl2.h"
110 #include "backends/wave.h"
116 /************************************************
118 ************************************************/
121 BackendFactory
& (*getFactory
)(void);
124 struct BackendInfo BackendList
[] = {
126 { "jack", JackBackendFactory::getFactory
},
128 #ifdef HAVE_PULSEAUDIO
129 { "pulse", PulseBackendFactory::getFactory
},
132 { "alsa", AlsaBackendFactory::getFactory
},
135 { "wasapi", WasapiBackendFactory::getFactory
},
137 #ifdef HAVE_COREAUDIO
138 { "core", CoreAudioBackendFactory::getFactory
},
141 { "opensl", OSLBackendFactory::getFactory
},
144 { "solaris", SolarisBackendFactory::getFactory
},
147 { "sndio", SndIOBackendFactory::getFactory
},
150 { "oss", OSSBackendFactory::getFactory
},
153 { "qsa", QSABackendFactory::getFactory
},
156 { "dsound", DSoundBackendFactory::getFactory
},
159 { "winmm", WinMMBackendFactory::getFactory
},
161 #ifdef HAVE_PORTAUDIO
162 { "port", PortBackendFactory::getFactory
},
165 { "sdl2", SDL2BackendFactory::getFactory
},
168 { "null", NullBackendFactory::getFactory
},
170 { "wave", WaveBackendFactory::getFactory
},
173 ALsizei BackendListSize
= COUNTOF(BackendList
);
175 struct BackendInfo PlaybackBackend
;
176 struct BackendInfo CaptureBackend
;
179 /************************************************
180 * Functions, enums, and errors
181 ************************************************/
182 #define DECL(x) { #x, (ALCvoid*)(x) }
184 const ALCchar
*funcName
;
187 DECL(alcCreateContext
),
188 DECL(alcMakeContextCurrent
),
189 DECL(alcProcessContext
),
190 DECL(alcSuspendContext
),
191 DECL(alcDestroyContext
),
192 DECL(alcGetCurrentContext
),
193 DECL(alcGetContextsDevice
),
195 DECL(alcCloseDevice
),
197 DECL(alcIsExtensionPresent
),
198 DECL(alcGetProcAddress
),
199 DECL(alcGetEnumValue
),
201 DECL(alcGetIntegerv
),
202 DECL(alcCaptureOpenDevice
),
203 DECL(alcCaptureCloseDevice
),
204 DECL(alcCaptureStart
),
205 DECL(alcCaptureStop
),
206 DECL(alcCaptureSamples
),
208 DECL(alcSetThreadContext
),
209 DECL(alcGetThreadContext
),
211 DECL(alcLoopbackOpenDeviceSOFT
),
212 DECL(alcIsRenderFormatSupportedSOFT
),
213 DECL(alcRenderSamplesSOFT
),
215 DECL(alcDevicePauseSOFT
),
216 DECL(alcDeviceResumeSOFT
),
218 DECL(alcGetStringiSOFT
),
219 DECL(alcResetDeviceSOFT
),
221 DECL(alcGetInteger64vSOFT
),
236 DECL(alIsExtensionPresent
),
237 DECL(alGetProcAddress
),
238 DECL(alGetEnumValue
),
245 DECL(alGetListenerf
),
246 DECL(alGetListener3f
),
247 DECL(alGetListenerfv
),
248 DECL(alGetListeneri
),
249 DECL(alGetListener3i
),
250 DECL(alGetListeneriv
),
252 DECL(alDeleteSources
),
268 DECL(alSourceRewindv
),
269 DECL(alSourcePausev
),
272 DECL(alSourceRewind
),
274 DECL(alSourceQueueBuffers
),
275 DECL(alSourceUnqueueBuffers
),
277 DECL(alDeleteBuffers
),
292 DECL(alDopplerFactor
),
293 DECL(alDopplerVelocity
),
294 DECL(alSpeedOfSound
),
295 DECL(alDistanceModel
),
298 DECL(alDeleteFilters
),
309 DECL(alDeleteEffects
),
319 DECL(alGenAuxiliaryEffectSlots
),
320 DECL(alDeleteAuxiliaryEffectSlots
),
321 DECL(alIsAuxiliaryEffectSlot
),
322 DECL(alAuxiliaryEffectSloti
),
323 DECL(alAuxiliaryEffectSlotiv
),
324 DECL(alAuxiliaryEffectSlotf
),
325 DECL(alAuxiliaryEffectSlotfv
),
326 DECL(alGetAuxiliaryEffectSloti
),
327 DECL(alGetAuxiliaryEffectSlotiv
),
328 DECL(alGetAuxiliaryEffectSlotf
),
329 DECL(alGetAuxiliaryEffectSlotfv
),
331 DECL(alDeferUpdatesSOFT
),
332 DECL(alProcessUpdatesSOFT
),
335 DECL(alSource3dSOFT
),
336 DECL(alSourcedvSOFT
),
337 DECL(alGetSourcedSOFT
),
338 DECL(alGetSource3dSOFT
),
339 DECL(alGetSourcedvSOFT
),
340 DECL(alSourcei64SOFT
),
341 DECL(alSource3i64SOFT
),
342 DECL(alSourcei64vSOFT
),
343 DECL(alGetSourcei64SOFT
),
344 DECL(alGetSource3i64SOFT
),
345 DECL(alGetSourcei64vSOFT
),
347 DECL(alGetStringiSOFT
),
349 DECL(alBufferStorageSOFT
),
350 DECL(alMapBufferSOFT
),
351 DECL(alUnmapBufferSOFT
),
352 DECL(alFlushMappedBufferSOFT
),
354 DECL(alEventControlSOFT
),
355 DECL(alEventCallbackSOFT
),
356 DECL(alGetPointerSOFT
),
357 DECL(alGetPointervSOFT
),
361 #define DECL(x) { #x, (x) }
363 const ALCchar
*enumName
;
365 } alcEnumerations
[] = {
370 DECL(ALC_MAJOR_VERSION
),
371 DECL(ALC_MINOR_VERSION
),
372 DECL(ALC_ATTRIBUTES_SIZE
),
373 DECL(ALC_ALL_ATTRIBUTES
),
374 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
375 DECL(ALC_DEVICE_SPECIFIER
),
376 DECL(ALC_ALL_DEVICES_SPECIFIER
),
377 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
378 DECL(ALC_EXTENSIONS
),
382 DECL(ALC_MONO_SOURCES
),
383 DECL(ALC_STEREO_SOURCES
),
384 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
385 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
386 DECL(ALC_CAPTURE_SAMPLES
),
389 DECL(ALC_EFX_MAJOR_VERSION
),
390 DECL(ALC_EFX_MINOR_VERSION
),
391 DECL(ALC_MAX_AUXILIARY_SENDS
),
393 DECL(ALC_FORMAT_CHANNELS_SOFT
),
394 DECL(ALC_FORMAT_TYPE_SOFT
),
397 DECL(ALC_STEREO_SOFT
),
399 DECL(ALC_5POINT1_SOFT
),
400 DECL(ALC_6POINT1_SOFT
),
401 DECL(ALC_7POINT1_SOFT
),
402 DECL(ALC_BFORMAT3D_SOFT
),
405 DECL(ALC_UNSIGNED_BYTE_SOFT
),
406 DECL(ALC_SHORT_SOFT
),
407 DECL(ALC_UNSIGNED_SHORT_SOFT
),
409 DECL(ALC_UNSIGNED_INT_SOFT
),
410 DECL(ALC_FLOAT_SOFT
),
413 DECL(ALC_DONT_CARE_SOFT
),
414 DECL(ALC_HRTF_STATUS_SOFT
),
415 DECL(ALC_HRTF_DISABLED_SOFT
),
416 DECL(ALC_HRTF_ENABLED_SOFT
),
417 DECL(ALC_HRTF_DENIED_SOFT
),
418 DECL(ALC_HRTF_REQUIRED_SOFT
),
419 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
420 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
421 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
422 DECL(ALC_HRTF_SPECIFIER_SOFT
),
423 DECL(ALC_HRTF_ID_SOFT
),
425 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
426 DECL(ALC_AMBISONIC_SCALING_SOFT
),
427 DECL(ALC_AMBISONIC_ORDER_SOFT
),
433 DECL(ALC_OUTPUT_LIMITER_SOFT
),
436 DECL(ALC_INVALID_DEVICE
),
437 DECL(ALC_INVALID_CONTEXT
),
438 DECL(ALC_INVALID_ENUM
),
439 DECL(ALC_INVALID_VALUE
),
440 DECL(ALC_OUT_OF_MEMORY
),
448 DECL(AL_SOURCE_RELATIVE
),
449 DECL(AL_CONE_INNER_ANGLE
),
450 DECL(AL_CONE_OUTER_ANGLE
),
460 DECL(AL_ORIENTATION
),
461 DECL(AL_REFERENCE_DISTANCE
),
462 DECL(AL_ROLLOFF_FACTOR
),
463 DECL(AL_CONE_OUTER_GAIN
),
464 DECL(AL_MAX_DISTANCE
),
466 DECL(AL_SAMPLE_OFFSET
),
467 DECL(AL_BYTE_OFFSET
),
468 DECL(AL_SOURCE_TYPE
),
471 DECL(AL_UNDETERMINED
),
472 DECL(AL_METERS_PER_UNIT
),
473 DECL(AL_LOOP_POINTS_SOFT
),
474 DECL(AL_DIRECT_CHANNELS_SOFT
),
476 DECL(AL_DIRECT_FILTER
),
477 DECL(AL_AUXILIARY_SEND_FILTER
),
478 DECL(AL_AIR_ABSORPTION_FACTOR
),
479 DECL(AL_ROOM_ROLLOFF_FACTOR
),
480 DECL(AL_CONE_OUTER_GAINHF
),
481 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
482 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
483 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
485 DECL(AL_SOURCE_STATE
),
491 DECL(AL_BUFFERS_QUEUED
),
492 DECL(AL_BUFFERS_PROCESSED
),
494 DECL(AL_FORMAT_MONO8
),
495 DECL(AL_FORMAT_MONO16
),
496 DECL(AL_FORMAT_MONO_FLOAT32
),
497 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
498 DECL(AL_FORMAT_STEREO8
),
499 DECL(AL_FORMAT_STEREO16
),
500 DECL(AL_FORMAT_STEREO_FLOAT32
),
501 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
502 DECL(AL_FORMAT_MONO_IMA4
),
503 DECL(AL_FORMAT_STEREO_IMA4
),
504 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
505 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
506 DECL(AL_FORMAT_QUAD8_LOKI
),
507 DECL(AL_FORMAT_QUAD16_LOKI
),
508 DECL(AL_FORMAT_QUAD8
),
509 DECL(AL_FORMAT_QUAD16
),
510 DECL(AL_FORMAT_QUAD32
),
511 DECL(AL_FORMAT_51CHN8
),
512 DECL(AL_FORMAT_51CHN16
),
513 DECL(AL_FORMAT_51CHN32
),
514 DECL(AL_FORMAT_61CHN8
),
515 DECL(AL_FORMAT_61CHN16
),
516 DECL(AL_FORMAT_61CHN32
),
517 DECL(AL_FORMAT_71CHN8
),
518 DECL(AL_FORMAT_71CHN16
),
519 DECL(AL_FORMAT_71CHN32
),
520 DECL(AL_FORMAT_REAR8
),
521 DECL(AL_FORMAT_REAR16
),
522 DECL(AL_FORMAT_REAR32
),
523 DECL(AL_FORMAT_MONO_MULAW
),
524 DECL(AL_FORMAT_MONO_MULAW_EXT
),
525 DECL(AL_FORMAT_STEREO_MULAW
),
526 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
527 DECL(AL_FORMAT_QUAD_MULAW
),
528 DECL(AL_FORMAT_51CHN_MULAW
),
529 DECL(AL_FORMAT_61CHN_MULAW
),
530 DECL(AL_FORMAT_71CHN_MULAW
),
531 DECL(AL_FORMAT_REAR_MULAW
),
532 DECL(AL_FORMAT_MONO_ALAW_EXT
),
533 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
535 DECL(AL_FORMAT_BFORMAT2D_8
),
536 DECL(AL_FORMAT_BFORMAT2D_16
),
537 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
538 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
539 DECL(AL_FORMAT_BFORMAT3D_8
),
540 DECL(AL_FORMAT_BFORMAT3D_16
),
541 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
542 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
548 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
549 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
551 DECL(AL_SOURCE_RADIUS
),
553 DECL(AL_STEREO_ANGLES
),
560 DECL(AL_INVALID_NAME
),
561 DECL(AL_INVALID_ENUM
),
562 DECL(AL_INVALID_VALUE
),
563 DECL(AL_INVALID_OPERATION
),
564 DECL(AL_OUT_OF_MEMORY
),
571 DECL(AL_DOPPLER_FACTOR
),
572 DECL(AL_DOPPLER_VELOCITY
),
573 DECL(AL_DISTANCE_MODEL
),
574 DECL(AL_SPEED_OF_SOUND
),
575 DECL(AL_SOURCE_DISTANCE_MODEL
),
576 DECL(AL_DEFERRED_UPDATES_SOFT
),
577 DECL(AL_GAIN_LIMIT_SOFT
),
579 DECL(AL_INVERSE_DISTANCE
),
580 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
581 DECL(AL_LINEAR_DISTANCE
),
582 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
583 DECL(AL_EXPONENT_DISTANCE
),
584 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
586 DECL(AL_FILTER_TYPE
),
587 DECL(AL_FILTER_NULL
),
588 DECL(AL_FILTER_LOWPASS
),
589 DECL(AL_FILTER_HIGHPASS
),
590 DECL(AL_FILTER_BANDPASS
),
592 DECL(AL_LOWPASS_GAIN
),
593 DECL(AL_LOWPASS_GAINHF
),
595 DECL(AL_HIGHPASS_GAIN
),
596 DECL(AL_HIGHPASS_GAINLF
),
598 DECL(AL_BANDPASS_GAIN
),
599 DECL(AL_BANDPASS_GAINHF
),
600 DECL(AL_BANDPASS_GAINLF
),
602 DECL(AL_EFFECT_TYPE
),
603 DECL(AL_EFFECT_NULL
),
604 DECL(AL_EFFECT_REVERB
),
605 DECL(AL_EFFECT_EAXREVERB
),
606 DECL(AL_EFFECT_CHORUS
),
607 DECL(AL_EFFECT_DISTORTION
),
608 DECL(AL_EFFECT_ECHO
),
609 DECL(AL_EFFECT_FLANGER
),
610 DECL(AL_EFFECT_PITCH_SHIFTER
),
611 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
613 DECL(AL_EFFECT_VOCAL_MORPHER
),
615 DECL(AL_EFFECT_RING_MODULATOR
),
616 DECL(AL_EFFECT_AUTOWAH
),
617 DECL(AL_EFFECT_COMPRESSOR
),
618 DECL(AL_EFFECT_EQUALIZER
),
619 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
620 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
622 DECL(AL_EFFECTSLOT_EFFECT
),
623 DECL(AL_EFFECTSLOT_GAIN
),
624 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
625 DECL(AL_EFFECTSLOT_NULL
),
627 DECL(AL_EAXREVERB_DENSITY
),
628 DECL(AL_EAXREVERB_DIFFUSION
),
629 DECL(AL_EAXREVERB_GAIN
),
630 DECL(AL_EAXREVERB_GAINHF
),
631 DECL(AL_EAXREVERB_GAINLF
),
632 DECL(AL_EAXREVERB_DECAY_TIME
),
633 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
634 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
635 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
636 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
637 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
638 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
639 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
640 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
641 DECL(AL_EAXREVERB_ECHO_TIME
),
642 DECL(AL_EAXREVERB_ECHO_DEPTH
),
643 DECL(AL_EAXREVERB_MODULATION_TIME
),
644 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
645 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
646 DECL(AL_EAXREVERB_HFREFERENCE
),
647 DECL(AL_EAXREVERB_LFREFERENCE
),
648 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
649 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
651 DECL(AL_REVERB_DENSITY
),
652 DECL(AL_REVERB_DIFFUSION
),
653 DECL(AL_REVERB_GAIN
),
654 DECL(AL_REVERB_GAINHF
),
655 DECL(AL_REVERB_DECAY_TIME
),
656 DECL(AL_REVERB_DECAY_HFRATIO
),
657 DECL(AL_REVERB_REFLECTIONS_GAIN
),
658 DECL(AL_REVERB_REFLECTIONS_DELAY
),
659 DECL(AL_REVERB_LATE_REVERB_GAIN
),
660 DECL(AL_REVERB_LATE_REVERB_DELAY
),
661 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
662 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
663 DECL(AL_REVERB_DECAY_HFLIMIT
),
665 DECL(AL_CHORUS_WAVEFORM
),
666 DECL(AL_CHORUS_PHASE
),
667 DECL(AL_CHORUS_RATE
),
668 DECL(AL_CHORUS_DEPTH
),
669 DECL(AL_CHORUS_FEEDBACK
),
670 DECL(AL_CHORUS_DELAY
),
672 DECL(AL_DISTORTION_EDGE
),
673 DECL(AL_DISTORTION_GAIN
),
674 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
675 DECL(AL_DISTORTION_EQCENTER
),
676 DECL(AL_DISTORTION_EQBANDWIDTH
),
679 DECL(AL_ECHO_LRDELAY
),
680 DECL(AL_ECHO_DAMPING
),
681 DECL(AL_ECHO_FEEDBACK
),
682 DECL(AL_ECHO_SPREAD
),
684 DECL(AL_FLANGER_WAVEFORM
),
685 DECL(AL_FLANGER_PHASE
),
686 DECL(AL_FLANGER_RATE
),
687 DECL(AL_FLANGER_DEPTH
),
688 DECL(AL_FLANGER_FEEDBACK
),
689 DECL(AL_FLANGER_DELAY
),
691 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
692 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
693 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
695 DECL(AL_RING_MODULATOR_FREQUENCY
),
696 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
697 DECL(AL_RING_MODULATOR_WAVEFORM
),
699 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
700 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
702 DECL(AL_COMPRESSOR_ONOFF
),
704 DECL(AL_EQUALIZER_LOW_GAIN
),
705 DECL(AL_EQUALIZER_LOW_CUTOFF
),
706 DECL(AL_EQUALIZER_MID1_GAIN
),
707 DECL(AL_EQUALIZER_MID1_CENTER
),
708 DECL(AL_EQUALIZER_MID1_WIDTH
),
709 DECL(AL_EQUALIZER_MID2_GAIN
),
710 DECL(AL_EQUALIZER_MID2_CENTER
),
711 DECL(AL_EQUALIZER_MID2_WIDTH
),
712 DECL(AL_EQUALIZER_HIGH_GAIN
),
713 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
715 DECL(AL_DEDICATED_GAIN
),
717 DECL(AL_AUTOWAH_ATTACK_TIME
),
718 DECL(AL_AUTOWAH_RELEASE_TIME
),
719 DECL(AL_AUTOWAH_RESONANCE
),
720 DECL(AL_AUTOWAH_PEAK_GAIN
),
722 DECL(AL_NUM_RESAMPLERS_SOFT
),
723 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
724 DECL(AL_SOURCE_RESAMPLER_SOFT
),
725 DECL(AL_RESAMPLER_NAME_SOFT
),
727 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
730 DECL(AL_MAP_READ_BIT_SOFT
),
731 DECL(AL_MAP_WRITE_BIT_SOFT
),
732 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
733 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
735 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
736 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
737 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
738 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
739 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
740 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
741 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
745 constexpr ALCchar alcNoError
[] = "No Error";
746 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
747 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
748 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
749 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
750 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
753 /************************************************
755 ************************************************/
757 /* Enumerated device names */
758 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
760 std::string alcAllDevicesList
;
761 std::string alcCaptureDeviceList
;
763 /* Default is always the first in the list */
764 std::string alcDefaultAllDevicesSpecifier
;
765 std::string alcCaptureDefaultDeviceSpecifier
;
767 /* Default context extensions */
768 constexpr ALchar alExtList
[] =
772 "AL_EXT_EXPONENT_DISTANCE "
775 "AL_EXT_LINEAR_DISTANCE "
778 "AL_EXT_MULAW_BFORMAT "
779 "AL_EXT_MULAW_MCFORMATS "
781 "AL_EXT_source_distance_model "
782 "AL_EXT_SOURCE_RADIUS "
783 "AL_EXT_STEREO_ANGLES "
784 "AL_LOKI_quadriphonic "
785 "AL_SOFT_block_alignment "
786 "AL_SOFT_deferred_updates "
787 "AL_SOFT_direct_channels "
789 "AL_SOFTX_filter_gain_ex "
790 "AL_SOFT_gain_clamp_ex "
791 "AL_SOFT_loop_points "
792 "AL_SOFTX_map_buffer "
794 "AL_SOFT_source_latency "
795 "AL_SOFT_source_length "
796 "AL_SOFT_source_resampler "
797 "AL_SOFT_source_spatialize";
799 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
801 /* Thread-local current context */
802 std::atomic
<void(*)(ALCcontext
*)> ThreadCtxProc
{nullptr};
804 ALCcontext
*ctx
{nullptr};
809 auto destruct
= ThreadCtxProc
.load();
815 ALCcontext
*get() const noexcept
{ return ctx
; }
816 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
818 thread_local ThreadCtx LocalContext
;
819 /* Process-wide current context */
820 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
822 /* Flag to trap ALC device errors */
823 bool TrapALCError
{false};
825 /* One-time configuration init control */
826 std::once_flag alc_config_once
{};
828 /* Default effect that applies to sources that don't have an effect on send 0 */
829 ALeffect DefaultEffect
;
831 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
834 bool SuspendDefers
{true};
837 /************************************************
839 ************************************************/
840 constexpr ALCchar alcNoDeviceExtList
[] =
841 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
842 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
843 constexpr ALCchar alcExtensionList
[] =
844 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
845 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
846 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
847 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
848 constexpr ALCint alcMajorVersion
= 1;
849 constexpr ALCint alcMinorVersion
= 1;
851 constexpr ALCint alcEFXMajorVersion
= 1;
852 constexpr ALCint alcEFXMinorVersion
= 0;
855 /************************************************
857 ************************************************/
858 std::atomic
<ALCdevice
*> DeviceList
{nullptr};
860 std::recursive_mutex ListLock
;
864 /* Mixing thread piority level */
869 enum LogLevel LogLevel
= LogWarning
;
871 enum LogLevel LogLevel
= LogError
;
874 /************************************************
875 * Library initialization
876 ************************************************/
878 static void alc_init(void);
879 static void alc_deinit(void);
880 static void alc_deinit_safe(void);
882 #ifndef AL_LIBTYPE_STATIC
883 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
887 case DLL_PROCESS_ATTACH
:
888 /* Pin the DLL so we won't get unloaded until the process terminates */
889 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
890 (WCHAR
*)hModule
, &hModule
);
894 case DLL_PROCESS_DETACH
:
903 #elif defined(_MSC_VER)
904 #pragma section(".CRT$XCU",read)
905 static void alc_constructor(void);
906 static void alc_destructor(void);
907 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
909 static void alc_constructor(void)
911 atexit(alc_destructor
);
915 static void alc_destructor(void)
919 #elif defined(HAVE_GCC_DESTRUCTOR)
920 static void alc_init(void) __attribute__((constructor
));
921 static void alc_deinit(void) __attribute__((destructor
));
923 #error "No static initialization available on this platform!"
926 #elif defined(HAVE_GCC_DESTRUCTOR)
928 static void alc_init(void) __attribute__((constructor
));
929 static void alc_deinit(void) __attribute__((destructor
));
932 #error "No global initialization available on this platform!"
935 static void ReleaseThreadCtx(ALCcontext
*ctx
);
936 static void alc_init(void)
940 const char *str
{getenv("__ALSOFT_HALF_ANGLE_CONES")};
941 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
944 str
= getenv("__ALSOFT_REVERSE_Z");
945 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
948 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
949 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
950 OverrideReverbSpeedOfSound
= AL_TRUE
;
952 ThreadCtxProc
= ReleaseThreadCtx
;
955 static void alc_initconfig(void)
957 const char *devs
, *str
;
962 str
= getenv("ALSOFT_LOGLEVEL");
965 long lvl
= strtol(str
, nullptr, 0);
966 if(lvl
>= NoLog
&& lvl
<= LogRef
)
967 LogLevel
= static_cast<enum LogLevel
>(lvl
);
970 str
= getenv("ALSOFT_LOGFILE");
974 std::wstring wname
{utf8_to_wstr(str
)};
975 FILE *logfile
= _wfopen(wname
.c_str(), L
"wt");
977 FILE *logfile
= fopen(str
, "wt");
979 if(logfile
) LogFile
= logfile
;
980 else ERR("Failed to open log file '%s'\n", str
);
983 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
984 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
987 if(BackendListSize
> 0)
988 names
+= BackendList
[0].name
;
989 for(i
= 1;i
< BackendListSize
;i
++)
992 names
+= BackendList
[i
].name
;
994 TRACE("Supported backends: %s\n", names
.c_str());
998 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
1001 if(strcasecmp(str
, "ignore") == 0)
1003 SuspendDefers
= false;
1004 TRACE("Selected context suspend behavior, \"ignore\"\n");
1007 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
1011 #if defined(HAVE_SSE4_1)
1012 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1013 #elif defined(HAVE_SSE3)
1014 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1015 #elif defined(HAVE_SSE2)
1016 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1017 #elif defined(HAVE_SSE)
1018 capfilter
|= CPU_CAP_SSE
;
1021 capfilter
|= CPU_CAP_NEON
;
1023 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str
))
1025 if(strcasecmp(str
, "all") == 0)
1030 const char *next
= str
;
1034 while(isspace(str
[0]))
1036 next
= strchr(str
, ',');
1038 if(!str
[0] || str
[0] == ',')
1041 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1042 while(len
> 0 && isspace(str
[len
-1]))
1044 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
1045 capfilter
&= ~CPU_CAP_SSE
;
1046 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
1047 capfilter
&= ~CPU_CAP_SSE2
;
1048 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
1049 capfilter
&= ~CPU_CAP_SSE3
;
1050 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
1051 capfilter
&= ~CPU_CAP_SSE4_1
;
1052 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
1053 capfilter
&= ~CPU_CAP_NEON
;
1055 WARN("Invalid CPU extension \"%s\"\n", str
);
1059 FillCPUCaps(capfilter
);
1066 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel
);
1071 str
= getenv("ALSOFT_TRAP_ERROR");
1072 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1074 TrapALError
= AL_TRUE
;
1075 TrapALCError
= true;
1079 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1080 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1081 TrapALError
= AL_TRUE
;
1082 TrapALError
= GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError
);
1084 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1085 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1086 TrapALCError
= true;
1087 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError
);
1090 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf
))
1091 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1093 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1094 ConfigValueStr(nullptr, nullptr, "drivers", &devs
))
1098 const char *next
= devs
;
1099 int endlist
, delitem
;
1104 while(isspace(devs
[0]))
1106 next
= strchr(devs
, ',');
1108 delitem
= (devs
[0] == '-');
1109 if(devs
[0] == '-') devs
++;
1111 if(!devs
[0] || devs
[0] == ',')
1118 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1119 while(len
> 0 && isspace(devs
[len
-1]))
1122 /* HACK: For backwards compatibility, convert backend references of
1123 * mmdevapi to wasapi. This should eventually be removed.
1125 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1131 for(n
= i
;n
< BackendListSize
;n
++)
1133 if(len
== strlen(BackendList
[n
].name
) &&
1134 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1138 for(;n
+1 < BackendListSize
;n
++)
1139 BackendList
[n
] = BackendList
[n
+1];
1144 struct BackendInfo Bkp
= BackendList
[n
];
1146 BackendList
[n
] = BackendList
[n
-1];
1147 BackendList
[n
] = Bkp
;
1157 BackendListSize
= i
;
1160 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1162 BackendList
[n
] = BackendList
[i
];
1164 BackendFactory
&factory
= BackendList
[n
].getFactory();
1167 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1171 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1172 if(!PlaybackBackend
.name
&& factory
.querySupport(ALCbackend_Playback
))
1174 PlaybackBackend
= BackendList
[n
];
1175 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1177 if(!CaptureBackend
.name
&& factory
.querySupport(ALCbackend_Capture
))
1179 CaptureBackend
= BackendList
[n
];
1180 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1184 BackendListSize
= n
;
1186 LoopbackBackendFactory::getFactory().init();
1188 if(!PlaybackBackend
.name
)
1189 WARN("No playback backend available!\n");
1190 if(!CaptureBackend
.name
)
1191 WARN("No capture backend available!\n");
1193 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str
))
1196 const char *next
= str
;
1200 next
= strchr(str
, ',');
1202 if(!str
[0] || next
== str
)
1205 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1206 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1208 if(len
== strlen(EffectList
[n
].name
) &&
1209 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1210 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1215 InitEffect(&DefaultEffect
);
1216 str
= getenv("ALSOFT_DEFAULT_REVERB");
1217 if((str
&& str
[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str
))
1218 LoadReverbPreset(str
, &DefaultEffect
);
1220 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1223 /************************************************
1224 * Library deinitialization
1225 ************************************************/
1226 static void alc_cleanup(void)
1228 alcAllDevicesList
.clear();
1229 alcCaptureDeviceList
.clear();
1231 alcDefaultAllDevicesSpecifier
.clear();
1232 alcCaptureDefaultDeviceSpecifier
.clear();
1234 if(ALCdevice
*dev
{DeviceList
.exchange(nullptr)})
1239 dev
= dev
->next
.load(std::memory_order_relaxed
);
1240 } while(dev
!= nullptr);
1241 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1245 static void alc_deinit_safe(void)
1252 ThreadCtxProc
= nullptr;
1254 if(LogFile
!= stderr
)
1259 static void alc_deinit(void)
1265 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1266 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1268 for(i
= 0;i
< BackendListSize
;i
++)
1269 BackendList
[i
].getFactory().deinit();
1271 LoopbackBackendFactory::getFactory().deinit();
1277 /************************************************
1278 * Device enumeration
1279 ************************************************/
1280 static void ProbeDevices(std::string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1284 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1286 if(backendinfo
->getFactory
)
1287 backendinfo
->getFactory().probe(type
, list
);
1289 static void ProbeAllDevicesList(void)
1290 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1291 static void ProbeCaptureDeviceList(void)
1292 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1295 /************************************************
1296 * Device format information
1297 ************************************************/
1298 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1302 case DevFmtByte
: return "Signed Byte";
1303 case DevFmtUByte
: return "Unsigned Byte";
1304 case DevFmtShort
: return "Signed Short";
1305 case DevFmtUShort
: return "Unsigned Short";
1306 case DevFmtInt
: return "Signed Int";
1307 case DevFmtUInt
: return "Unsigned Int";
1308 case DevFmtFloat
: return "Float";
1310 return "(unknown type)";
1312 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1316 case DevFmtMono
: return "Mono";
1317 case DevFmtStereo
: return "Stereo";
1318 case DevFmtQuad
: return "Quadraphonic";
1319 case DevFmtX51
: return "5.1 Surround";
1320 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1321 case DevFmtX61
: return "6.1 Surround";
1322 case DevFmtX71
: return "7.1 Surround";
1323 case DevFmtAmbi3D
: return "Ambisonic 3D";
1325 return "(unknown channels)";
1328 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1332 case DevFmtByte
: return sizeof(ALbyte
);
1333 case DevFmtUByte
: return sizeof(ALubyte
);
1334 case DevFmtShort
: return sizeof(ALshort
);
1335 case DevFmtUShort
: return sizeof(ALushort
);
1336 case DevFmtInt
: return sizeof(ALint
);
1337 case DevFmtUInt
: return sizeof(ALuint
);
1338 case DevFmtFloat
: return sizeof(ALfloat
);
1342 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1346 case DevFmtMono
: return 1;
1347 case DevFmtStereo
: return 2;
1348 case DevFmtQuad
: return 4;
1349 case DevFmtX51
: return 6;
1350 case DevFmtX51Rear
: return 6;
1351 case DevFmtX61
: return 7;
1352 case DevFmtX71
: return 8;
1353 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1354 (ambiorder
== 2) ? 9 :
1355 (ambiorder
== 1) ? 4 : 1;
1360 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1361 enum DevFmtType
*type
)
1363 static const struct {
1365 enum DevFmtChannels channels
;
1366 enum DevFmtType type
;
1368 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1369 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1370 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1372 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1373 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1374 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1376 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1377 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1378 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1380 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1381 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1382 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1384 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1385 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1386 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1388 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1389 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1390 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1394 for(i
= 0;i
< COUNTOF(list
);i
++)
1396 if(list
[i
].format
== format
)
1398 *chans
= list
[i
].channels
;
1399 *type
= list
[i
].type
;
1407 static ALCboolean
IsValidALCType(ALCenum type
)
1412 case ALC_UNSIGNED_BYTE_SOFT
:
1413 case ALC_SHORT_SOFT
:
1414 case ALC_UNSIGNED_SHORT_SOFT
:
1416 case ALC_UNSIGNED_INT_SOFT
:
1417 case ALC_FLOAT_SOFT
:
1423 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1428 case ALC_STEREO_SOFT
:
1430 case ALC_5POINT1_SOFT
:
1431 case ALC_6POINT1_SOFT
:
1432 case ALC_7POINT1_SOFT
:
1433 case ALC_BFORMAT3D_SOFT
:
1439 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1450 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1462 /************************************************
1463 * Miscellaneous ALC helpers
1464 ************************************************/
1466 /* SetDefaultWFXChannelOrder
1468 * Sets the default channel order used by WaveFormatEx.
1470 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1474 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1475 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1477 switch(device
->FmtChans
)
1480 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1483 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1484 device
->RealOut
.ChannelName
[1] = FrontRight
;
1487 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1488 device
->RealOut
.ChannelName
[1] = FrontRight
;
1489 device
->RealOut
.ChannelName
[2] = BackLeft
;
1490 device
->RealOut
.ChannelName
[3] = BackRight
;
1493 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1494 device
->RealOut
.ChannelName
[1] = FrontRight
;
1495 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1496 device
->RealOut
.ChannelName
[3] = LFE
;
1497 device
->RealOut
.ChannelName
[4] = SideLeft
;
1498 device
->RealOut
.ChannelName
[5] = SideRight
;
1501 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1502 device
->RealOut
.ChannelName
[1] = FrontRight
;
1503 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1504 device
->RealOut
.ChannelName
[3] = LFE
;
1505 device
->RealOut
.ChannelName
[4] = BackLeft
;
1506 device
->RealOut
.ChannelName
[5] = BackRight
;
1509 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1510 device
->RealOut
.ChannelName
[1] = FrontRight
;
1511 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1512 device
->RealOut
.ChannelName
[3] = LFE
;
1513 device
->RealOut
.ChannelName
[4] = BackCenter
;
1514 device
->RealOut
.ChannelName
[5] = SideLeft
;
1515 device
->RealOut
.ChannelName
[6] = SideRight
;
1518 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1519 device
->RealOut
.ChannelName
[1] = FrontRight
;
1520 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1521 device
->RealOut
.ChannelName
[3] = LFE
;
1522 device
->RealOut
.ChannelName
[4] = BackLeft
;
1523 device
->RealOut
.ChannelName
[5] = BackRight
;
1524 device
->RealOut
.ChannelName
[6] = SideLeft
;
1525 device
->RealOut
.ChannelName
[7] = SideRight
;
1528 device
->RealOut
.ChannelName
[0] = Aux0
;
1529 if(device
->mAmbiOrder
> 0)
1531 device
->RealOut
.ChannelName
[1] = Aux1
;
1532 device
->RealOut
.ChannelName
[2] = Aux2
;
1533 device
->RealOut
.ChannelName
[3] = Aux3
;
1535 if(device
->mAmbiOrder
> 1)
1537 device
->RealOut
.ChannelName
[4] = Aux4
;
1538 device
->RealOut
.ChannelName
[5] = Aux5
;
1539 device
->RealOut
.ChannelName
[6] = Aux6
;
1540 device
->RealOut
.ChannelName
[7] = Aux7
;
1541 device
->RealOut
.ChannelName
[8] = Aux8
;
1543 if(device
->mAmbiOrder
> 2)
1545 device
->RealOut
.ChannelName
[9] = Aux9
;
1546 device
->RealOut
.ChannelName
[10] = Aux10
;
1547 device
->RealOut
.ChannelName
[11] = Aux11
;
1548 device
->RealOut
.ChannelName
[12] = Aux12
;
1549 device
->RealOut
.ChannelName
[13] = Aux13
;
1550 device
->RealOut
.ChannelName
[14] = Aux14
;
1551 device
->RealOut
.ChannelName
[15] = Aux15
;
1557 /* SetDefaultChannelOrder
1559 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1561 void SetDefaultChannelOrder(ALCdevice
*device
)
1565 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1566 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1568 switch(device
->FmtChans
)
1571 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1572 device
->RealOut
.ChannelName
[1] = FrontRight
;
1573 device
->RealOut
.ChannelName
[2] = BackLeft
;
1574 device
->RealOut
.ChannelName
[3] = BackRight
;
1575 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1576 device
->RealOut
.ChannelName
[5] = LFE
;
1579 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1580 device
->RealOut
.ChannelName
[1] = FrontRight
;
1581 device
->RealOut
.ChannelName
[2] = BackLeft
;
1582 device
->RealOut
.ChannelName
[3] = BackRight
;
1583 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1584 device
->RealOut
.ChannelName
[5] = LFE
;
1585 device
->RealOut
.ChannelName
[6] = SideLeft
;
1586 device
->RealOut
.ChannelName
[7] = SideRight
;
1589 /* Same as WFX order */
1596 SetDefaultWFXChannelOrder(device
);
1602 /* ALCcontext_DeferUpdates
1604 * Defers/suspends updates for the given context's listener and sources. This
1605 * does *NOT* stop mixing, but rather prevents certain property changes from
1608 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1610 context
->DeferUpdates
.store(true);
1613 /* ALCcontext_ProcessUpdates
1615 * Resumes update processing after being deferred.
1617 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1619 std::lock_guard
<almtx_t
> _
{context
->PropLock
};
1620 if(context
->DeferUpdates
.exchange(false))
1622 /* Tell the mixer to stop applying updates, then wait for any active
1623 * updating to finish, before providing updates.
1625 context
->HoldUpdates
.store(AL_TRUE
);
1626 while((context
->UpdateCount
.load(std::memory_order_acquire
)&1) != 0)
1629 if(!context
->PropsClean
.test_and_set(std::memory_order_acq_rel
))
1630 UpdateContextProps(context
);
1631 if(!context
->Listener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1632 UpdateListenerProps(context
);
1633 UpdateAllEffectSlotProps(context
);
1634 UpdateAllSourceProps(context
);
1636 /* Now with all updates declared, let the mixer continue applying them
1637 * so they all happen at once.
1639 context
->HoldUpdates
.store(AL_FALSE
);
1646 * Stores the latest ALC device error
1648 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1650 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1654 /* DebugBreak() will cause an exception if there is no debugger */
1655 if(IsDebuggerPresent())
1657 #elif defined(SIGTRAP)
1663 device
->LastError
.store(errorCode
);
1665 LastNullDeviceError
.store(errorCode
);
1669 static struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1671 return CompressorInit(device
->RealOut
.NumChannels
, device
->Frequency
,
1672 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
,
1673 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1678 * Updates the device's base clock time with however many samples have been
1679 * done. This is used so frequency changes on the device don't cause the time
1680 * to jump forward or back. Must not be called while the device is running/
1683 static inline void UpdateClockBase(ALCdevice
*device
)
1685 using std::chrono::seconds
;
1686 using std::chrono::nanoseconds
;
1687 using std::chrono::duration_cast
;
1689 IncrementRef(&device
->MixCount
);
1690 device
->ClockBase
+= duration_cast
<nanoseconds
>(seconds
{device
->SamplesDone
}) /
1692 device
->SamplesDone
= 0;
1693 IncrementRef(&device
->MixCount
);
1696 /* UpdateDeviceParams
1698 * Updates device parameters according to the attribute list (caller is
1699 * responsible for holding the list lock).
1701 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1703 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1704 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1705 ALCenum gainLimiter
= device
->LimiterState
;
1706 const ALsizei old_sends
= device
->NumAuxSends
;
1707 ALsizei new_sends
= device
->NumAuxSends
;
1708 enum DevFmtChannels oldChans
;
1709 enum DevFmtType oldType
;
1710 ALboolean update_failed
;
1711 ALCsizei hrtf_id
= -1;
1712 ALCcontext
*context
;
1716 // Check for attributes
1717 if(device
->Type
== Loopback
)
1719 ALCsizei numMono
, numStereo
, numSends
;
1720 ALCenum alayout
= AL_NONE
;
1721 ALCenum ascale
= AL_NONE
;
1722 ALCenum schans
= AL_NONE
;
1723 ALCenum stype
= AL_NONE
;
1724 ALCsizei attrIdx
= 0;
1725 ALCsizei aorder
= 0;
1730 WARN("Missing attributes for loopback device\n");
1731 return ALC_INVALID_VALUE
;
1734 numMono
= device
->NumMonoSources
;
1735 numStereo
= device
->NumStereoSources
;
1736 numSends
= old_sends
;
1738 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1739 while(attrList
[attrIdx
])
1741 switch(attrList
[attrIdx
])
1743 case ALC_FORMAT_CHANNELS_SOFT
:
1744 schans
= attrList
[attrIdx
+ 1];
1745 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1746 if(!IsValidALCChannels(schans
))
1747 return ALC_INVALID_VALUE
;
1750 case ALC_FORMAT_TYPE_SOFT
:
1751 stype
= attrList
[attrIdx
+ 1];
1752 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1753 if(!IsValidALCType(stype
))
1754 return ALC_INVALID_VALUE
;
1758 freq
= attrList
[attrIdx
+ 1];
1759 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1760 if(freq
< MIN_OUTPUT_RATE
)
1761 return ALC_INVALID_VALUE
;
1764 case ALC_AMBISONIC_LAYOUT_SOFT
:
1765 alayout
= attrList
[attrIdx
+ 1];
1766 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1767 if(!IsValidAmbiLayout(alayout
))
1768 return ALC_INVALID_VALUE
;
1771 case ALC_AMBISONIC_SCALING_SOFT
:
1772 ascale
= attrList
[attrIdx
+ 1];
1773 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1774 if(!IsValidAmbiScaling(ascale
))
1775 return ALC_INVALID_VALUE
;
1778 case ALC_AMBISONIC_ORDER_SOFT
:
1779 aorder
= attrList
[attrIdx
+ 1];
1780 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1781 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1782 return ALC_INVALID_VALUE
;
1785 case ALC_MONO_SOURCES
:
1786 numMono
= attrList
[attrIdx
+ 1];
1787 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1788 numMono
= maxi(numMono
, 0);
1791 case ALC_STEREO_SOURCES
:
1792 numStereo
= attrList
[attrIdx
+ 1];
1793 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1794 numStereo
= maxi(numStereo
, 0);
1797 case ALC_MAX_AUXILIARY_SENDS
:
1798 numSends
= attrList
[attrIdx
+ 1];
1799 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1800 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1804 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1805 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1806 hrtf_appreq
= Hrtf_Disable
;
1807 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1808 hrtf_appreq
= Hrtf_Enable
;
1810 hrtf_appreq
= Hrtf_Default
;
1813 case ALC_HRTF_ID_SOFT
:
1814 hrtf_id
= attrList
[attrIdx
+ 1];
1815 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1818 case ALC_OUTPUT_LIMITER_SOFT
:
1819 gainLimiter
= attrList
[attrIdx
+ 1];
1820 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1824 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1825 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1833 if(!schans
|| !stype
|| !freq
)
1835 WARN("Missing format for loopback device\n");
1836 return ALC_INVALID_VALUE
;
1838 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1840 WARN("Missing ambisonic info for loopback device\n");
1841 return ALC_INVALID_VALUE
;
1844 if((device
->Flags
&DEVICE_RUNNING
))
1845 V0(device
->Backend
,stop
)();
1846 device
->Flags
&= ~DEVICE_RUNNING
;
1848 UpdateClockBase(device
);
1850 device
->Frequency
= freq
;
1851 device
->FmtChans
= static_cast<enum DevFmtChannels
>(schans
);
1852 device
->FmtType
= static_cast<enum DevFmtType
>(stype
);
1853 if(schans
== ALC_BFORMAT3D_SOFT
)
1855 device
->mAmbiOrder
= aorder
;
1856 device
->mAmbiLayout
= static_cast<AmbiLayout
>(alayout
);
1857 device
->mAmbiScale
= static_cast<AmbiNorm
>(ascale
);
1860 if(numMono
> INT_MAX
-numStereo
)
1861 numMono
= INT_MAX
-numStereo
;
1862 numMono
+= numStereo
;
1863 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono
))
1869 numMono
= maxi(numMono
, 256);
1870 numStereo
= mini(numStereo
, numMono
);
1871 numMono
-= numStereo
;
1872 device
->SourcesMax
= numMono
+ numStereo
;
1874 device
->NumMonoSources
= numMono
;
1875 device
->NumStereoSources
= numStereo
;
1877 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends
))
1878 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1880 new_sends
= numSends
;
1882 else if(attrList
&& attrList
[0])
1884 ALCsizei numMono
, numStereo
, numSends
;
1885 ALCsizei attrIdx
= 0;
1888 /* If a context is already running on the device, stop playback so the
1889 * device attributes can be updated. */
1890 if((device
->Flags
&DEVICE_RUNNING
))
1891 V0(device
->Backend
,stop
)();
1892 device
->Flags
&= ~DEVICE_RUNNING
;
1894 UpdateClockBase(device
);
1896 freq
= device
->Frequency
;
1897 numMono
= device
->NumMonoSources
;
1898 numStereo
= device
->NumStereoSources
;
1899 numSends
= old_sends
;
1901 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1902 while(attrList
[attrIdx
])
1904 switch(attrList
[attrIdx
])
1907 freq
= attrList
[attrIdx
+ 1];
1908 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1909 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1912 case ALC_MONO_SOURCES
:
1913 numMono
= attrList
[attrIdx
+ 1];
1914 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1915 numMono
= maxi(numMono
, 0);
1918 case ALC_STEREO_SOURCES
:
1919 numStereo
= attrList
[attrIdx
+ 1];
1920 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1921 numStereo
= maxi(numStereo
, 0);
1924 case ALC_MAX_AUXILIARY_SENDS
:
1925 numSends
= attrList
[attrIdx
+ 1];
1926 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1927 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1931 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1932 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1933 hrtf_appreq
= Hrtf_Disable
;
1934 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1935 hrtf_appreq
= Hrtf_Enable
;
1937 hrtf_appreq
= Hrtf_Default
;
1940 case ALC_HRTF_ID_SOFT
:
1941 hrtf_id
= attrList
[attrIdx
+ 1];
1942 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1945 case ALC_OUTPUT_LIMITER_SOFT
:
1946 gainLimiter
= attrList
[attrIdx
+ 1];
1947 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1951 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1952 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1960 ConfigValueUInt(device
->DeviceName
.c_str(), nullptr, "frequency", &freq
);
1961 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1963 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1965 /* SSE and Neon do best with the update size being a multiple of 4 */
1966 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1967 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1969 device
->Frequency
= freq
;
1971 if(numMono
> INT_MAX
-numStereo
)
1972 numMono
= INT_MAX
-numStereo
;
1973 numMono
+= numStereo
;
1974 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sources", &numMono
))
1980 numMono
= maxi(numMono
, 256);
1981 numStereo
= mini(numStereo
, numMono
);
1982 numMono
-= numStereo
;
1983 device
->SourcesMax
= numMono
+ numStereo
;
1985 device
->NumMonoSources
= numMono
;
1986 device
->NumStereoSources
= numStereo
;
1988 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sends", &new_sends
))
1989 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1991 new_sends
= numSends
;
1994 if((device
->Flags
&DEVICE_RUNNING
))
1995 return ALC_NO_ERROR
;
1997 device
->Uhj_Encoder
= nullptr;
1998 device
->Bs2b
= nullptr;
2000 device
->ChannelDelay
.clear();
2001 device
->ChannelDelay
.shrink_to_fit();
2003 device
->Dry
.Buffer
= nullptr;
2004 device
->Dry
.NumChannels
= 0;
2005 device
->FOAOut
.Buffer
= nullptr;
2006 device
->FOAOut
.NumChannels
= 0;
2007 device
->RealOut
.Buffer
= nullptr;
2008 device
->RealOut
.NumChannels
= 0;
2009 device
->MixBuffer
.clear();
2010 device
->MixBuffer
.shrink_to_fit();
2012 UpdateClockBase(device
);
2013 device
->FixedLatency
= std::chrono::nanoseconds::zero();
2015 device
->DitherSeed
= DITHER_RNG_SEED
;
2017 /*************************************************************************
2018 * Update device format request if HRTF is requested
2020 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2021 if(device
->Type
!= Loopback
)
2024 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf", &hrtf
))
2026 if(strcasecmp(hrtf
, "true") == 0)
2027 hrtf_userreq
= Hrtf_Enable
;
2028 else if(strcasecmp(hrtf
, "false") == 0)
2029 hrtf_userreq
= Hrtf_Disable
;
2030 else if(strcasecmp(hrtf
, "auto") != 0)
2031 ERR("Unexpected hrtf value: %s\n", hrtf
);
2034 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2036 struct Hrtf
*hrtf
= nullptr;
2037 if(device
->HrtfList
.empty())
2038 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
2039 if(!device
->HrtfList
.empty())
2041 if(hrtf_id
>= 0 && (size_t)hrtf_id
< device
->HrtfList
.size())
2042 hrtf
= GetLoadedHrtf(device
->HrtfList
[hrtf_id
].hrtf
);
2044 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
2049 device
->FmtChans
= DevFmtStereo
;
2050 device
->Frequency
= hrtf
->sampleRate
;
2051 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2052 if(device
->HrtfHandle
)
2053 Hrtf_DecRef(device
->HrtfHandle
);
2054 device
->HrtfHandle
= hrtf
;
2058 hrtf_userreq
= Hrtf_Default
;
2059 hrtf_appreq
= Hrtf_Disable
;
2060 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2065 oldFreq
= device
->Frequency
;
2066 oldChans
= device
->FmtChans
;
2067 oldType
= device
->FmtType
;
2069 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2070 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2071 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2072 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2073 device
->UpdateSize
, device
->NumUpdates
2076 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2077 return ALC_INVALID_DEVICE
;
2079 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2081 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2082 DevFmtChannelsString(device
->FmtChans
));
2083 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2085 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2087 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2088 DevFmtTypeString(device
->FmtType
));
2089 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2091 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2093 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2094 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2097 if((device
->UpdateSize
&3) != 0)
2099 if((CPUCapFlags
&CPU_CAP_SSE
))
2100 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2101 if((CPUCapFlags
&CPU_CAP_NEON
))
2102 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2105 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2106 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2107 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2110 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2111 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2112 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2114 /* Allocate extra channels for any post-filter output. */
2115 ALsizei num_chans
{device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2116 device
->RealOut
.NumChannels
};
2118 TRACE("Allocating %d channels, " SZFMT
" bytes\n", num_chans
,
2119 num_chans
*sizeof(device
->MixBuffer
[0]));
2120 device
->MixBuffer
.resize(num_chans
);
2122 device
->Dry
.Buffer
= &reinterpret_cast<ALfloat(&)[BUFFERSIZE
]>(device
->MixBuffer
[0]);
2123 if(device
->RealOut
.NumChannels
!= 0)
2124 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2125 device
->FOAOut
.NumChannels
;
2128 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2129 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2132 if(device
->FOAOut
.NumChannels
!= 0)
2133 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2136 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2137 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2140 device
->NumAuxSends
= new_sends
;
2141 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2142 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2143 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2145 device
->DitherDepth
= 0.0f
;
2146 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2149 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth", &depth
);
2152 switch(device
->FmtType
)
2171 depth
= clampi(depth
, 2, 24);
2172 device
->DitherDepth
= std::pow(2.0f
, (ALfloat
)(depth
-1));
2175 if(!(device
->DitherDepth
> 0.0f
))
2176 TRACE("Dithering disabled\n");
2178 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2179 device
->DitherDepth
);
2181 device
->LimiterState
= gainLimiter
;
2182 if(ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter", &val
))
2183 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2185 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2186 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2187 * output (where samples must be clamped), and don't for floating-point
2188 * (which can take unclamped samples).
2190 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2192 switch(device
->FmtType
)
2200 gainLimiter
= ALC_TRUE
;
2203 gainLimiter
= ALC_FALSE
;
2207 if(gainLimiter
!= ALC_FALSE
)
2209 ALfloat thrshld
= 1.0f
;
2210 switch(device
->FmtType
)
2214 thrshld
= 127.0f
/ 128.0f
;
2218 thrshld
= 32767.0f
/ 32768.0f
;
2225 if(device
->DitherDepth
> 0.0f
)
2226 thrshld
-= 1.0f
/ device
->DitherDepth
;
2228 device
->Limiter
.reset(CreateDeviceLimiter(device
, std::log10(thrshld
) * 20.0f
));
2229 /* Convert the lookahead from samples to nanosamples to nanoseconds. */
2230 device
->FixedLatency
+= std::chrono::duration_cast
<std::chrono::nanoseconds
>(
2231 std::chrono::seconds(GetCompressorLookAhead(device
->Limiter
.get()))
2232 ) / device
->Frequency
;
2235 device
->Limiter
= nullptr;
2236 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2238 aluSelectPostProcess(device
);
2240 TRACE("Fixed device latency: %ldns\n", (long)device
->FixedLatency
.count());
2242 /* Need to delay returning failure until replacement Send arrays have been
2243 * allocated with the appropriate size.
2245 update_failed
= AL_FALSE
;
2246 FPUCtl mixer_mode
{};
2247 context
= device
->ContextList
.load();
2250 if(context
->DefaultSlot
)
2252 ALeffectslot
*slot
= context
->DefaultSlot
.get();
2253 EffectState
*state
= slot
->Effect
.State
;
2255 state
->mOutBuffer
= device
->Dry
.Buffer
;
2256 state
->mOutChannels
= device
->Dry
.NumChannels
;
2257 if(state
->deviceUpdate(device
) == AL_FALSE
)
2258 update_failed
= AL_TRUE
;
2260 UpdateEffectSlotProps(slot
, context
);
2263 std::unique_lock
<almtx_t
> proplock
{context
->PropLock
};
2264 std::unique_lock
<almtx_t
> slotlock
{context
->EffectSlotLock
};
2265 for(auto &slot
: context
->EffectSlotList
)
2267 EffectState
*state
= slot
->Effect
.State
;
2269 state
->mOutBuffer
= device
->Dry
.Buffer
;
2270 state
->mOutChannels
= device
->Dry
.NumChannels
;
2271 if(state
->deviceUpdate(device
) == AL_FALSE
)
2272 update_failed
= AL_TRUE
;
2274 UpdateEffectSlotProps(slot
.get(), context
);
2278 std::unique_lock
<almtx_t
> srclock
{context
->SourceLock
};
2279 for(auto &sublist
: context
->SourceList
)
2281 uint64_t usemask
= ~sublist
.FreeMask
;
2284 ALsizei idx
= CTZ64(usemask
);
2285 ALsource
*source
= sublist
.Sources
+ idx
;
2287 usemask
&= ~(U64(1) << idx
);
2289 if(old_sends
!= device
->NumAuxSends
)
2292 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2294 if(source
->Send
[s
].Slot
)
2295 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2296 source
->Send
[s
].Slot
= nullptr;
2298 source
->Send
.resize(device
->NumAuxSends
);
2299 source
->Send
.shrink_to_fit();
2300 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2302 source
->Send
[s
].Slot
= nullptr;
2303 source
->Send
[s
].Gain
= 1.0f
;
2304 source
->Send
[s
].GainHF
= 1.0f
;
2305 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2306 source
->Send
[s
].GainLF
= 1.0f
;
2307 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2311 source
->PropsClean
.clear(std::memory_order_release
);
2315 /* Clear any pre-existing voice property structs, in case the number of
2316 * auxiliary sends is changing. Active sources will have updates
2317 * respecified in UpdateAllSourceProps.
2319 ALvoiceProps
*vprops
{context
->FreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
)};
2322 struct ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2327 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2328 auto voices_end
= context
->Voices
+ context
->VoiceCount
.load(std::memory_order_relaxed
);
2329 std::for_each(context
->Voices
, voices_end
,
2330 [device
](ALvoice
*voice
) -> void
2332 al_free(voice
->Update
.exchange(nullptr, std::memory_order_acq_rel
));
2334 if(voice
->Source
.load(std::memory_order_acquire
) == nullptr)
2337 if(device
->AvgSpeakerDist
> 0.0f
)
2339 /* Reinitialize the NFC filters for new parameters. */
2340 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2341 (device
->AvgSpeakerDist
* device
->Frequency
);
2342 std::for_each(voice
->Direct
.Params
, voice
->Direct
.Params
+voice
->NumChannels
,
2343 [w1
](DirectParams
¶ms
) -> void
2344 { NfcFilterCreate(¶ms
.NFCtrlFilter
, 0.0f
, w1
); }
2351 context
->PropsClean
.test_and_set(std::memory_order_release
);
2352 UpdateContextProps(context
);
2353 context
->Listener
.PropsClean
.test_and_set(std::memory_order_release
);
2354 UpdateListenerProps(context
);
2355 UpdateAllSourceProps(context
);
2357 context
= context
->next
.load(std::memory_order_relaxed
);
2361 return ALC_INVALID_DEVICE
;
2363 if(!(device
->Flags
&DEVICE_PAUSED
))
2365 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2366 return ALC_INVALID_DEVICE
;
2367 device
->Flags
|= DEVICE_RUNNING
;
2370 return ALC_NO_ERROR
;
2374 ALCdevice_struct::ALCdevice_struct(DeviceType type
)
2377 almtx_init(&BufferLock
, almtx_plain
);
2378 almtx_init(&EffectLock
, almtx_plain
);
2379 almtx_init(&FilterLock
, almtx_plain
);
2381 almtx_init(&BackendLock
, almtx_plain
);
2384 /* ALCdevice_struct::~ALCdevice_struct
2386 * Frees the device structure, and destroys any objects the app failed to
2387 * delete. Called once there's no more references on the device.
2389 ALCdevice_struct::~ALCdevice_struct()
2391 TRACE("%p\n", this);
2394 DELETE_OBJ(Backend
);
2397 almtx_destroy(&BackendLock
);
2399 ReleaseALBuffers(this);
2400 std::for_each(BufferList
.begin(), BufferList
.end(),
2401 [](BufferSubList
&entry
) noexcept
-> void
2402 { al_free(entry
.Buffers
); }
2405 almtx_destroy(&BufferLock
);
2407 ReleaseALEffects(this);
2408 std::for_each(EffectList
.begin(), EffectList
.end(),
2409 [](EffectSubList
&entry
) noexcept
-> void
2410 { al_free(entry
.Effects
); }
2413 almtx_destroy(&EffectLock
);
2415 ReleaseALFilters(this);
2416 std::for_each(FilterList
.begin(), FilterList
.end(),
2417 [](FilterSubList
&entry
) noexcept
-> void
2418 { al_free(entry
.Filters
); }
2421 almtx_destroy(&FilterLock
);
2425 Hrtf_DecRef(HrtfHandle
);
2426 HrtfHandle
= nullptr;
2430 static void ALCdevice_IncRef(ALCdevice
*device
)
2432 auto ref
= IncrementRef(&device
->ref
);
2433 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2436 static void ALCdevice_DecRef(ALCdevice
*device
)
2438 auto ref
= DecrementRef(&device
->ref
);
2439 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2440 if(ref
== 0) delete device
;
2443 /* Simple RAII device reference. Takes the reference of the provided ALCdevice,
2444 * and decrements it when leaving scope. Movable (transfer reference) but not
2445 * copyable (no new references).
2448 ALCdevice
*mDev
{nullptr};
2450 void reset() noexcept
2453 ALCdevice_DecRef(mDev
);
2458 DeviceRef() noexcept
= default;
2459 DeviceRef(DeviceRef
&& rhs
) noexcept
: mDev
{rhs
.mDev
}
2460 { rhs
.mDev
= nullptr; }
2461 explicit DeviceRef(ALCdevice
*dev
) noexcept
: mDev(dev
) { }
2462 ~DeviceRef() { reset(); }
2464 DeviceRef
& operator=(const DeviceRef
&) = delete;
2465 DeviceRef
& operator=(DeviceRef
&& rhs
) noexcept
2473 operator bool() const noexcept
{ return mDev
!= nullptr; }
2475 ALCdevice
* operator->() noexcept
{ return mDev
; }
2476 ALCdevice
* get() noexcept
{ return mDev
; }
2478 ALCdevice
* release() noexcept
2480 ALCdevice
*ret
{mDev
};
2489 * Checks if the device handle is valid, and returns a new reference if so.
2491 static DeviceRef
VerifyDevice(ALCdevice
*device
)
2493 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2494 ALCdevice
*tmpDevice
{DeviceList
.load()};
2497 if(tmpDevice
== device
)
2499 ALCdevice_IncRef(tmpDevice
);
2500 return DeviceRef
{tmpDevice
};
2502 tmpDevice
= tmpDevice
->next
.load(std::memory_order_relaxed
);
2509 ALCcontext_struct::ALCcontext_struct(ALCdevice
*device
)
2516 * Initializes context fields
2518 static ALvoid
InitContext(ALCcontext
*Context
)
2520 ALlistener
&listener
= Context
->Listener
;
2521 struct ALeffectslotArray
*auxslots
;
2524 almtx_init(&Context
->PropLock
, almtx_plain
);
2525 almtx_init(&Context
->SourceLock
, almtx_plain
);
2526 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2528 if(Context
->DefaultSlot
)
2530 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2531 FAM_SIZE(struct ALeffectslotArray
, slot
, 1)));
2532 auxslots
->count
= 1;
2533 auxslots
->slot
[0] = Context
->DefaultSlot
.get();
2537 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2538 sizeof(struct ALeffectslotArray
)));
2539 auxslots
->count
= 0;
2541 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2544 Context
->mDistanceModel
= DistanceModel::Default
;
2545 Context
->SourceDistanceModel
= AL_FALSE
;
2546 Context
->DopplerFactor
= 1.0f
;
2547 Context
->DopplerVelocity
= 1.0f
;
2548 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2549 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2550 alsem_init(&Context
->EventSem
, 0);
2552 Context
->ExtensionList
= alExtList
;
2555 listener
.Params
.Matrix
= aluMatrixf::Identity
;
2556 aluVectorSet(&listener
.Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2557 listener
.Params
.Gain
= listener
.Gain
;
2558 listener
.Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2559 listener
.Params
.DopplerFactor
= Context
->DopplerFactor
;
2560 listener
.Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2561 listener
.Params
.ReverbSpeedOfSound
= listener
.Params
.SpeedOfSound
*
2562 listener
.Params
.MetersPerUnit
;
2563 listener
.Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2564 listener
.Params
.mDistanceModel
= Context
->mDistanceModel
;
2567 Context
->AsyncEvents
= ll_ringbuffer_create(63, sizeof(AsyncEvent
), false);
2568 StartEventThrd(Context
);
2572 /* ALCcontext_struct::~ALCcontext_struct()
2574 * Cleans up the context, and destroys any remaining objects the app failed to
2575 * delete. Called once there's no more references on the context.
2577 ALCcontext_struct::~ALCcontext_struct()
2579 TRACE("%p\n", this);
2581 struct ALcontextProps
*cprops
{Update
.load(std::memory_order_relaxed
)};
2584 TRACE("Freed unapplied context update %p\n", cprops
);
2588 cprops
= FreeContextProps
.load(std::memory_order_acquire
);
2591 struct ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2596 TRACE("Freed " SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2598 al_free(ActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
));
2599 DefaultSlot
= nullptr;
2601 ReleaseALSources(this);
2602 std::for_each(SourceList
.begin(), SourceList
.end(),
2603 [](const SourceSubList
&entry
) noexcept
-> void
2604 { al_free(entry
.Sources
); }
2608 almtx_destroy(&SourceLock
);
2611 struct ALeffectslotProps
*eprops
{FreeEffectslotProps
.load(std::memory_order_acquire
)};
2614 struct ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2615 if(eprops
->State
) eprops
->State
->DecRef();
2620 TRACE("Freed " SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2622 ReleaseALAuxiliaryEffectSlots(this);
2623 EffectSlotList
.clear();
2624 almtx_destroy(&EffectSlotLock
);
2627 struct ALvoiceProps
*vprops
{FreeVoiceProps
.load(std::memory_order_acquire
)};
2630 struct ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2635 TRACE("Freed " SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2637 std::for_each(Voices
, Voices
+ VoiceCount
.load(std::memory_order_relaxed
),
2638 [](ALvoice
*voice
) -> void { DeinitVoice(voice
); }
2642 VoiceCount
.store(0, std::memory_order_relaxed
);
2645 struct ALlistenerProps
*lprops
{Listener
.Update
.load(std::memory_order_relaxed
)};
2648 TRACE("Freed unapplied listener update %p\n", lprops
);
2652 lprops
= FreeListenerProps
.load(std::memory_order_acquire
);
2655 struct ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2660 TRACE("Freed " SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2662 alsem_destroy(&EventSem
);
2664 ll_ringbuffer_free(AsyncEvents
);
2665 AsyncEvents
= nullptr;
2667 almtx_destroy(&PropLock
);
2669 ALCdevice_DecRef(Device
);
2674 * Removes the context reference from the given device and removes it from
2675 * being current on the running thread or globally. Returns true if other
2676 * contexts still exist on the device.
2678 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2680 ALCcontext
*origctx
, *newhead
;
2683 if(LocalContext
.get() == context
)
2685 WARN("%p released while current on thread\n", context
);
2686 LocalContext
.set(nullptr);
2687 ALCcontext_DecRef(context
);
2691 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2692 ALCcontext_DecRef(context
);
2694 V0(device
->Backend
,lock
)();
2696 newhead
= context
->next
.load(std::memory_order_relaxed
);
2697 if(!device
->ContextList
.compare_exchange_strong(origctx
, newhead
))
2701 /* origctx is what the desired context failed to match. Try
2702 * swapping out the next one in the list.
2706 } while(!list
->next
.compare_exchange_strong(origctx
, newhead
));
2710 V0(device
->Backend
,unlock
)();
2712 /* Make sure the context is finished and no longer processing in the mixer
2713 * before sending the message queue kill event. The backend's lock does
2714 * this, although waiting for a non-odd mix count would work too.
2717 StopEventThrd(context
);
2719 ALCcontext_DecRef(context
);
2723 static void ALCcontext_IncRef(ALCcontext
*context
)
2725 auto ref
= IncrementRef(&context
->ref
);
2726 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2729 void ALCcontext_DecRef(ALCcontext
*context
)
2731 auto ref
= DecrementRef(&context
->ref
);
2732 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2733 if(ref
== 0) delete context
;
2736 static void ReleaseThreadCtx(ALCcontext
*context
)
2738 auto ref
= DecrementRef(&context
->ref
);
2739 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2740 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2745 * Checks if the given context is valid, returning a new reference to it if so.
2747 static ContextRef
VerifyContext(ALCcontext
*context
)
2749 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2750 ALCdevice
*dev
{DeviceList
.load()};
2753 ALCcontext
*ctx
= dev
->ContextList
.load(std::memory_order_acquire
);
2758 ALCcontext_IncRef(ctx
);
2759 return ContextRef
{ctx
};
2761 ctx
= ctx
->next
.load(std::memory_order_relaxed
);
2763 dev
= dev
->next
.load(std::memory_order_relaxed
);
2766 return ContextRef
{};
2772 * Returns a new reference to the currently active context for this thread.
2774 ContextRef
GetContextRef(void)
2776 ALCcontext
*context
{LocalContext
.get()};
2778 ALCcontext_IncRef(context
);
2781 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2782 context
= GlobalContext
.load(std::memory_order_acquire
);
2783 if(context
) ALCcontext_IncRef(context
);
2785 return ContextRef
{context
};
2789 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2791 ALCdevice
*device
{context
->Device
};
2792 ALsizei num_sends
{device
->NumAuxSends
};
2794 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2797 /* Allocate the voice pointers, voices, and the voices' stored source
2798 * property set (including the dynamically-sized Send[] array) in one
2801 size_t sizeof_voice
{RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16)};
2802 size_t sizeof_props
{RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16)};
2803 size_t size
{sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
};
2805 auto voices
= static_cast<ALvoice
**>(al_calloc(16, RoundUp(size
*num_voices
, 16)));
2806 /* The voice and property objects are stored interleaved since they're
2809 auto voice
= reinterpret_cast<ALvoice
*>((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2810 auto props
= reinterpret_cast<ALvoiceProps
*>((char*)voice
+ sizeof_voice
);
2815 const ALsizei v_count
= mini(context
->VoiceCount
.load(std::memory_order_relaxed
),
2817 const ALsizei s_count
= mini(old_sends
, num_sends
);
2819 for(;v
< v_count
;v
++)
2821 ALvoice
*old_voice
{context
->Voices
[v
]};
2823 /* Copy the old voice data and source property set to the new
2826 memcpy(voice
, old_voice
, sizeof(*voice
));
2827 std::copy_n(old_voice
->Send
, s_count
, voice
->Send
);
2829 memcpy(props
, old_voice
->Props
, sizeof(*props
));
2830 std::copy_n(old_voice
->Props
->Send
, s_count
, props
->Send
);
2832 /* Set this voice's property set pointer and voice reference. */
2833 voice
->Props
= props
;
2836 /* Increment pointers to the next storage space. */
2837 voice
= reinterpret_cast<ALvoice
*>((char*)props
+ sizeof_props
);
2838 props
= reinterpret_cast<ALvoiceProps
*>((char*)voice
+ sizeof_voice
);
2840 /* Deinit any left over voices that weren't copied over to the new
2841 * array. NOTE: If this does anything, v equals num_voices and
2842 * num_voices is less than VoiceCount, so the following loop won't do
2845 auto voices_end
= context
->Voices
+ context
->VoiceCount
.load(std::memory_order_relaxed
);
2846 std::for_each(context
->Voices
+ v
, voices_end
,
2847 [](ALvoice
*voice
) -> void { DeinitVoice(voice
); }
2850 /* Finish setting the voices' property set pointers and references. */
2851 for(;v
< num_voices
;v
++)
2853 ATOMIC_INIT(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr));
2855 voice
->Props
= props
;
2858 voice
= reinterpret_cast<ALvoice
*>((char*)props
+ sizeof_props
);
2859 props
= reinterpret_cast<ALvoiceProps
*>((char*)voice
+ sizeof_voice
);
2862 al_free(context
->Voices
);
2863 context
->Voices
= voices
;
2864 context
->MaxVoices
= num_voices
;
2865 context
->VoiceCount
= mini(context
->VoiceCount
.load(std::memory_order_relaxed
), num_voices
);
2869 /************************************************
2870 * Standard ALC functions
2871 ************************************************/
2875 * Return last ALC generated error code for the given device
2877 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2879 DeviceRef dev
{VerifyDevice(device
)};
2880 if(dev
) return dev
->LastError
.exchange(ALC_NO_ERROR
);
2881 return LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2885 /* alcSuspendContext
2887 * Suspends updates for the given context
2889 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2894 ContextRef ctx
{VerifyContext(context
)};
2896 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2898 ALCcontext_DeferUpdates(ctx
.get());
2901 /* alcProcessContext
2903 * Resumes processing updates for the given context
2905 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2910 ContextRef ctx
{VerifyContext(context
)};
2912 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2914 ALCcontext_ProcessUpdates(ctx
.get());
2920 * Returns information about the device, and error strings
2922 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2924 const ALCchar
*value
= nullptr;
2933 case ALC_INVALID_ENUM
:
2934 value
= alcErrInvalidEnum
;
2937 case ALC_INVALID_VALUE
:
2938 value
= alcErrInvalidValue
;
2941 case ALC_INVALID_DEVICE
:
2942 value
= alcErrInvalidDevice
;
2945 case ALC_INVALID_CONTEXT
:
2946 value
= alcErrInvalidContext
;
2949 case ALC_OUT_OF_MEMORY
:
2950 value
= alcErrOutOfMemory
;
2953 case ALC_DEVICE_SPECIFIER
:
2954 value
= alcDefaultName
;
2957 case ALC_ALL_DEVICES_SPECIFIER
:
2958 dev
= VerifyDevice(Device
);
2960 value
= dev
->DeviceName
.c_str();
2963 ProbeAllDevicesList();
2964 value
= alcAllDevicesList
.c_str();
2968 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2969 dev
= VerifyDevice(Device
);
2971 value
= dev
->DeviceName
.c_str();
2974 ProbeCaptureDeviceList();
2975 value
= alcCaptureDeviceList
.c_str();
2979 /* Default devices are always first in the list */
2980 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2981 value
= alcDefaultName
;
2984 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2985 if(alcAllDevicesList
.empty())
2986 ProbeAllDevicesList();
2988 /* Copy first entry as default. */
2989 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
2990 value
= alcDefaultAllDevicesSpecifier
.c_str();
2993 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2994 if(alcCaptureDeviceList
.empty())
2995 ProbeCaptureDeviceList();
2997 /* Copy first entry as default. */
2998 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
2999 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
3002 case ALC_EXTENSIONS
:
3003 dev
= VerifyDevice(Device
);
3004 if(dev
) value
= alcExtensionList
;
3005 else value
= alcNoDeviceExtList
;
3008 case ALC_HRTF_SPECIFIER_SOFT
:
3009 dev
= VerifyDevice(Device
);
3011 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3014 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
3015 value
= (dev
->HrtfHandle
? dev
->HrtfName
.c_str() : "");
3020 dev
= VerifyDevice(Device
);
3021 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
3029 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3031 if(device
->Type
== Capture
) return 9;
3032 if(device
->Type
!= Loopback
) return 29;
3033 if(device
->FmtChans
== DevFmtAmbi3D
)
3038 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3042 if(size
<= 0 || values
== nullptr)
3044 alcSetError(device
, ALC_INVALID_VALUE
);
3052 case ALC_MAJOR_VERSION
:
3053 values
[0] = alcMajorVersion
;
3055 case ALC_MINOR_VERSION
:
3056 values
[0] = alcMinorVersion
;
3059 case ALC_ATTRIBUTES_SIZE
:
3060 case ALC_ALL_ATTRIBUTES
:
3064 case ALC_MONO_SOURCES
:
3065 case ALC_STEREO_SOURCES
:
3066 case ALC_CAPTURE_SAMPLES
:
3067 case ALC_FORMAT_CHANNELS_SOFT
:
3068 case ALC_FORMAT_TYPE_SOFT
:
3069 case ALC_AMBISONIC_LAYOUT_SOFT
:
3070 case ALC_AMBISONIC_SCALING_SOFT
:
3071 case ALC_AMBISONIC_ORDER_SOFT
:
3072 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3073 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3077 alcSetError(nullptr, ALC_INVALID_ENUM
);
3083 if(device
->Type
== Capture
)
3087 case ALC_ATTRIBUTES_SIZE
:
3088 values
[0] = NumAttrsForDevice(device
);
3091 case ALC_ALL_ATTRIBUTES
:
3093 if(size
< NumAttrsForDevice(device
))
3094 alcSetError(device
, ALC_INVALID_VALUE
);
3097 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3098 values
[i
++] = ALC_MAJOR_VERSION
;
3099 values
[i
++] = alcMajorVersion
;
3100 values
[i
++] = ALC_MINOR_VERSION
;
3101 values
[i
++] = alcMinorVersion
;
3102 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3103 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3104 values
[i
++] = ALC_CONNECTED
;
3105 values
[i
++] = device
->Connected
.load(std::memory_order_relaxed
);
3110 case ALC_MAJOR_VERSION
:
3111 values
[0] = alcMajorVersion
;
3113 case ALC_MINOR_VERSION
:
3114 values
[0] = alcMinorVersion
;
3117 case ALC_CAPTURE_SAMPLES
:
3118 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3119 values
[0] = V0(device
->Backend
,availableSamples
)();
3124 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3128 alcSetError(device
, ALC_INVALID_ENUM
);
3137 case ALC_ATTRIBUTES_SIZE
:
3138 values
[0] = NumAttrsForDevice(device
);
3141 case ALC_ALL_ATTRIBUTES
:
3143 if(size
< NumAttrsForDevice(device
))
3144 alcSetError(device
, ALC_INVALID_VALUE
);
3147 std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3148 values
[i
++] = ALC_MAJOR_VERSION
;
3149 values
[i
++] = alcMajorVersion
;
3150 values
[i
++] = ALC_MINOR_VERSION
;
3151 values
[i
++] = alcMinorVersion
;
3152 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3153 values
[i
++] = alcEFXMajorVersion
;
3154 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3155 values
[i
++] = alcEFXMinorVersion
;
3157 values
[i
++] = ALC_FREQUENCY
;
3158 values
[i
++] = device
->Frequency
;
3159 if(device
->Type
!= Loopback
)
3161 values
[i
++] = ALC_REFRESH
;
3162 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3164 values
[i
++] = ALC_SYNC
;
3165 values
[i
++] = ALC_FALSE
;
3169 if(device
->FmtChans
== DevFmtAmbi3D
)
3171 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3172 values
[i
++] = static_cast<ALCint
>(device
->mAmbiLayout
);
3174 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3175 values
[i
++] = static_cast<ALCint
>(device
->mAmbiScale
);
3177 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3178 values
[i
++] = device
->mAmbiOrder
;
3181 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3182 values
[i
++] = device
->FmtChans
;
3184 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3185 values
[i
++] = device
->FmtType
;
3188 values
[i
++] = ALC_MONO_SOURCES
;
3189 values
[i
++] = device
->NumMonoSources
;
3191 values
[i
++] = ALC_STEREO_SOURCES
;
3192 values
[i
++] = device
->NumStereoSources
;
3194 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3195 values
[i
++] = device
->NumAuxSends
;
3197 values
[i
++] = ALC_HRTF_SOFT
;
3198 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3200 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3201 values
[i
++] = device
->HrtfStatus
;
3203 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3204 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3206 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3207 values
[i
++] = MAX_AMBI_ORDER
;
3213 case ALC_MAJOR_VERSION
:
3214 values
[0] = alcMajorVersion
;
3217 case ALC_MINOR_VERSION
:
3218 values
[0] = alcMinorVersion
;
3221 case ALC_EFX_MAJOR_VERSION
:
3222 values
[0] = alcEFXMajorVersion
;
3225 case ALC_EFX_MINOR_VERSION
:
3226 values
[0] = alcEFXMinorVersion
;
3230 values
[0] = device
->Frequency
;
3234 if(device
->Type
== Loopback
)
3236 alcSetError(device
, ALC_INVALID_DEVICE
);
3239 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3240 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3245 if(device
->Type
== Loopback
)
3247 alcSetError(device
, ALC_INVALID_DEVICE
);
3250 values
[0] = ALC_FALSE
;
3253 case ALC_FORMAT_CHANNELS_SOFT
:
3254 if(device
->Type
!= Loopback
)
3256 alcSetError(device
, ALC_INVALID_DEVICE
);
3259 values
[0] = device
->FmtChans
;
3262 case ALC_FORMAT_TYPE_SOFT
:
3263 if(device
->Type
!= Loopback
)
3265 alcSetError(device
, ALC_INVALID_DEVICE
);
3268 values
[0] = device
->FmtType
;
3271 case ALC_AMBISONIC_LAYOUT_SOFT
:
3272 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3274 alcSetError(device
, ALC_INVALID_DEVICE
);
3277 values
[0] = static_cast<ALCint
>(device
->mAmbiLayout
);
3280 case ALC_AMBISONIC_SCALING_SOFT
:
3281 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3283 alcSetError(device
, ALC_INVALID_DEVICE
);
3286 values
[0] = static_cast<ALCint
>(device
->mAmbiScale
);
3289 case ALC_AMBISONIC_ORDER_SOFT
:
3290 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3292 alcSetError(device
, ALC_INVALID_DEVICE
);
3295 values
[0] = device
->mAmbiOrder
;
3298 case ALC_MONO_SOURCES
:
3299 values
[0] = device
->NumMonoSources
;
3302 case ALC_STEREO_SOURCES
:
3303 values
[0] = device
->NumStereoSources
;
3306 case ALC_MAX_AUXILIARY_SENDS
:
3307 values
[0] = device
->NumAuxSends
;
3311 values
[0] = device
->Connected
.load(std::memory_order_acquire
);
3315 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3318 case ALC_HRTF_STATUS_SOFT
:
3319 values
[0] = device
->HrtfStatus
;
3322 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3323 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
3324 device
->HrtfList
.clear();
3325 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3326 values
[0] = (ALCint
)device
->HrtfList
.size();
3330 case ALC_OUTPUT_LIMITER_SOFT
:
3331 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3334 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3335 values
[0] = MAX_AMBI_ORDER
;
3339 alcSetError(device
, ALC_INVALID_ENUM
);
3347 * Returns information about the device and the version of OpenAL
3349 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3351 DeviceRef dev
{VerifyDevice(device
)};
3352 if(size
<= 0 || values
== nullptr)
3353 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3355 GetIntegerv(dev
.get(), param
, size
, values
);
3358 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3360 DeviceRef dev
{VerifyDevice(device
)};
3361 if(size
<= 0 || values
== nullptr)
3362 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3363 else if(!dev
|| dev
->Type
== Capture
)
3365 std::vector
<ALCint
> ivals(size
);
3366 size
= GetIntegerv(dev
.get(), pname
, size
, ivals
.data());
3367 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3369 else /* render device */
3373 case ALC_ATTRIBUTES_SIZE
:
3374 *values
= NumAttrsForDevice(dev
.get())+4;
3377 case ALC_ALL_ATTRIBUTES
:
3378 if(size
< NumAttrsForDevice(dev
.get())+4)
3379 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3383 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
3384 values
[i
++] = ALC_FREQUENCY
;
3385 values
[i
++] = dev
->Frequency
;
3387 if(dev
->Type
!= Loopback
)
3389 values
[i
++] = ALC_REFRESH
;
3390 values
[i
++] = dev
->Frequency
/ dev
->UpdateSize
;
3392 values
[i
++] = ALC_SYNC
;
3393 values
[i
++] = ALC_FALSE
;
3397 if(dev
->FmtChans
== DevFmtAmbi3D
)
3399 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3400 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiLayout
);
3402 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3403 values
[i
++] = static_cast<ALCint64SOFT
>(dev
->mAmbiScale
);
3405 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3406 values
[i
++] = dev
->mAmbiOrder
;
3409 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3410 values
[i
++] = dev
->FmtChans
;
3412 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3413 values
[i
++] = dev
->FmtType
;
3416 values
[i
++] = ALC_MONO_SOURCES
;
3417 values
[i
++] = dev
->NumMonoSources
;
3419 values
[i
++] = ALC_STEREO_SOURCES
;
3420 values
[i
++] = dev
->NumStereoSources
;
3422 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3423 values
[i
++] = dev
->NumAuxSends
;
3425 values
[i
++] = ALC_HRTF_SOFT
;
3426 values
[i
++] = (dev
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3428 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3429 values
[i
++] = dev
->HrtfStatus
;
3431 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3432 values
[i
++] = dev
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3434 ClockLatency clock
{GetClockLatency(dev
.get())};
3435 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3436 values
[i
++] = clock
.ClockTime
.count();
3438 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3439 values
[i
++] = clock
.Latency
.count();
3445 case ALC_DEVICE_CLOCK_SOFT
:
3446 { std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
3447 using std::chrono::seconds
;
3448 using std::chrono::nanoseconds
;
3449 using std::chrono::duration_cast
;
3451 nanoseconds basecount
;
3455 while(((refcount
=ReadRef(&dev
->MixCount
))&1) != 0)
3457 basecount
= dev
->ClockBase
;
3458 samplecount
= dev
->SamplesDone
;
3459 } while(refcount
!= ReadRef(&dev
->MixCount
));
3460 *values
= (duration_cast
<nanoseconds
>(seconds
{samplecount
})/dev
->Frequency
+
3465 case ALC_DEVICE_LATENCY_SOFT
:
3466 { std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
3467 ClockLatency clock
{GetClockLatency(dev
.get())};
3468 *values
= clock
.Latency
.count();
3472 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3474 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3477 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
3478 ClockLatency clock
{GetClockLatency(dev
.get())};
3479 values
[0] = clock
.ClockTime
.count();
3480 values
[1] = clock
.Latency
.count();
3485 std::vector
<ALCint
> ivals(size
);
3486 size
= GetIntegerv(dev
.get(), pname
, size
, ivals
.data());
3487 std::copy(ivals
.begin(), ivals
.begin()+size
, values
);
3494 /* alcIsExtensionPresent
3496 * Determines if there is support for a particular extension
3498 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3500 DeviceRef dev
{VerifyDevice(device
)};
3502 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3505 size_t len
= strlen(extName
);
3506 const char *ptr
= (dev
? alcExtensionList
: alcNoDeviceExtList
);
3509 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3510 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3513 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3517 } while(isspace(*ptr
));
3525 /* alcGetProcAddress
3527 * Retrieves the function address for a particular extension function
3529 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3533 DeviceRef dev
{VerifyDevice(device
)};
3534 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3539 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3541 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3542 return alcFunctions
[i
].address
;
3552 * Get the value for a particular ALC enumeration name
3554 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3558 DeviceRef dev
{VerifyDevice(device
)};
3559 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
3564 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3566 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3567 return alcEnumerations
[i
].value
;
3577 * Create and attach a context to the given device.
3579 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3581 ALCcontext
*ALContext
;
3585 /* Explicitly hold the list lock while taking the BackendLock in case the
3586 * device is asynchronously destropyed, to ensure this new context is
3587 * properly cleaned up after being made.
3589 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3590 DeviceRef dev
{VerifyDevice(device
)};
3591 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
3594 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
3597 std::unique_lock
<almtx_t
> backlock
{dev
->BackendLock
};
3600 dev
->LastError
.store(ALC_NO_ERROR
);
3602 ALContext
= new ALCcontext
{dev
.get()};
3603 ALCdevice_IncRef(ALContext
->Device
);
3605 if((err
=UpdateDeviceParams(dev
.get(), attrList
)) != ALC_NO_ERROR
)
3610 ALContext
= nullptr;
3612 alcSetError(dev
.get(), err
);
3613 if(err
== ALC_INVALID_DEVICE
)
3615 V0(dev
->Backend
,lock
)();
3616 aluHandleDisconnect(dev
.get(), "Device update failure");
3617 V0(dev
->Backend
,unlock
)();
3621 AllocateVoices(ALContext
, 256, dev
->NumAuxSends
);
3623 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& dev
->Type
== Playback
)
3625 ALContext
->DefaultSlot
.reset(new ALeffectslot
{});
3626 if(InitEffectSlot(ALContext
->DefaultSlot
.get()) == AL_NO_ERROR
)
3627 aluInitEffectPanning(ALContext
->DefaultSlot
.get());
3630 ALContext
->DefaultSlot
= nullptr;
3631 ERR("Failed to initialize the default effect slot\n");
3635 InitContext(ALContext
);
3637 if(ConfigValueFloat(dev
->DeviceName
.c_str(), nullptr, "volume-adjust", &valf
))
3639 if(!std::isfinite(valf
))
3640 ERR("volume-adjust must be finite: %f\n", valf
);
3643 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3645 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3646 ALContext
->GainBoost
= std::pow(10.0f
, db
/20.0f
);
3647 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3650 UpdateListenerProps(ALContext
);
3653 ALCcontext
*head
= dev
->ContextList
.load();
3655 ALContext
->next
.store(head
, std::memory_order_relaxed
);
3656 } while(!dev
->ContextList
.compare_exchange_weak(head
, ALContext
));
3660 if(ALContext
->DefaultSlot
)
3662 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3663 UpdateEffectSlotProps(ALContext
->DefaultSlot
.get(), ALContext
);
3665 ERR("Failed to initialize the default effect\n");
3668 TRACE("Created context %p\n", ALContext
);
3672 /* alcDestroyContext
3674 * Remove a context from its device
3676 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3678 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3679 ContextRef ctx
{VerifyContext(context
)};
3683 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3687 ALCdevice
* Device
{ctx
->Device
};
3690 std::lock_guard
<almtx_t
> _
{Device
->BackendLock
};
3691 if(!ReleaseContext(ctx
.get(), Device
))
3693 V0(Device
->Backend
,stop
)();
3694 Device
->Flags
&= ~DEVICE_RUNNING
;
3701 /* alcGetCurrentContext
3703 * Returns the currently active context on the calling thread
3705 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3707 ALCcontext
*Context
{LocalContext
.get()};
3708 if(!Context
) Context
= GlobalContext
.load();
3712 /* alcGetThreadContext
3714 * Returns the currently active thread-local context
3716 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3718 return LocalContext
.get();
3722 /* alcMakeContextCurrent
3724 * Makes the given context the active process-wide context, and removes the
3725 * thread-local context for the calling thread.
3727 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3729 /* context must be valid or nullptr */
3733 ctx
= VerifyContext(context
);
3736 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3740 /* Release this reference (if any) to store it in the GlobalContext
3741 * pointer. Take ownership of the reference (if any) that was previously
3744 ctx
= ContextRef
{GlobalContext
.exchange(ctx
.release())};
3746 /* Reset (decrement) the previous global reference by replacing it with the
3747 * thread-local context. Take ownership of the thread-local context
3748 * reference (if any), clearing the storage to null.
3750 ctx
= ContextRef
{LocalContext
.get()};
3751 if(ctx
) LocalContext
.set(nullptr);
3752 /* Reset (decrement) the previous thread-local reference. */
3757 /* alcSetThreadContext
3759 * Makes the given context the active context for the current thread
3761 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3763 /* context must be valid or nullptr */
3767 ctx
= VerifyContext(context
);
3770 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3774 /* context's reference count is already incremented */
3775 ContextRef old
{LocalContext
.get()};
3776 LocalContext
.set(ctx
.release());
3782 /* alcGetContextsDevice
3784 * Returns the device that a particular context is attached to
3786 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3788 ContextRef ctx
{VerifyContext(Context
)};
3791 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3800 * Opens the named device.
3802 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3806 if(!PlaybackBackend
.name
)
3808 alcSetError(nullptr, ALC_INVALID_VALUE
);
3812 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3814 /* Some old Windows apps hardcode these expecting OpenAL to use a
3815 * specific audio API, even when they're not enumerated. Creative's
3816 * router effectively ignores them too.
3818 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3819 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3822 deviceName
= nullptr;
3824 std::unique_ptr
<ALCdevice
> device
{new ALCdevice
{Playback
}};
3827 device
->FmtChans
= DevFmtChannelsDefault
;
3828 device
->FmtType
= DevFmtTypeDefault
;
3829 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3830 device
->LimiterState
= ALC_TRUE
;
3831 device
->NumUpdates
= 3;
3832 device
->UpdateSize
= 1024;
3834 device
->SourcesMax
= 256;
3835 device
->AuxiliaryEffectSlotMax
= 64;
3836 device
->NumAuxSends
= DEFAULT_SENDS
;
3838 const ALCchar
*fmt
{};
3839 if(ConfigValueStr(deviceName
, nullptr, "channels", &fmt
))
3841 static constexpr struct ChannelMap
{
3842 const char name
[16];
3843 enum DevFmtChannels chans
;
3846 { "mono", DevFmtMono
, 0 },
3847 { "stereo", DevFmtStereo
, 0 },
3848 { "quad", DevFmtQuad
, 0 },
3849 { "surround51", DevFmtX51
, 0 },
3850 { "surround61", DevFmtX61
, 0 },
3851 { "surround71", DevFmtX71
, 0 },
3852 { "surround51rear", DevFmtX51Rear
, 0 },
3853 { "ambi1", DevFmtAmbi3D
, 1 },
3854 { "ambi2", DevFmtAmbi3D
, 2 },
3855 { "ambi3", DevFmtAmbi3D
, 3 },
3858 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3859 [fmt
](const ChannelMap
&entry
) -> bool
3860 { return strcasecmp(entry
.name
, fmt
) == 0; }
3862 if(iter
== std::end(chanlist
))
3863 ERR("Unsupported channels: %s\n", fmt
);
3866 device
->FmtChans
= iter
->chans
;
3867 device
->mAmbiOrder
= iter
->order
;
3868 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3871 if(ConfigValueStr(deviceName
, nullptr, "sample-type", &fmt
))
3873 static constexpr struct TypeMap
{
3874 const char name
[16];
3875 enum DevFmtType type
;
3877 { "int8", DevFmtByte
},
3878 { "uint8", DevFmtUByte
},
3879 { "int16", DevFmtShort
},
3880 { "uint16", DevFmtUShort
},
3881 { "int32", DevFmtInt
},
3882 { "uint32", DevFmtUInt
},
3883 { "float32", DevFmtFloat
},
3886 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3887 [fmt
](const TypeMap
&entry
) -> bool
3888 { return strcasecmp(entry
.name
, fmt
) == 0; }
3890 if(iter
== std::end(typelist
))
3891 ERR("Unsupported sample-type: %s\n", fmt
);
3894 device
->FmtType
= iter
->type
;
3895 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3899 if(ConfigValueUInt(deviceName
, nullptr, "frequency", &device
->Frequency
))
3901 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3902 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3903 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3904 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3907 ConfigValueUInt(deviceName
, nullptr, "periods", &device
->NumUpdates
);
3908 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3910 ConfigValueUInt(deviceName
, nullptr, "period_size", &device
->UpdateSize
);
3911 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3912 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3913 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3915 ConfigValueUInt(deviceName
, nullptr, "sources", &device
->SourcesMax
);
3916 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3918 ConfigValueUInt(deviceName
, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
3919 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3920 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
3922 if(ConfigValueInt(deviceName
, nullptr, "sends", &device
->NumAuxSends
))
3923 device
->NumAuxSends
= clampi(
3924 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3927 device
->NumStereoSources
= 1;
3928 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3930 device
->Backend
= PlaybackBackend
.getFactory().createBackend(
3931 device
.get(), ALCbackend_Playback
);
3932 if(!device
->Backend
)
3935 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
3939 // Find a playback device to open
3940 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
3941 if(err
!= ALC_NO_ERROR
)
3944 alcSetError(nullptr, err
);
3948 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "ambi-format", &fmt
))
3950 if(strcasecmp(fmt
, "fuma") == 0)
3952 device
->mAmbiLayout
= AmbiLayout::FuMa
;
3953 device
->mAmbiScale
= AmbiNorm::FuMa
;
3955 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3957 device
->mAmbiLayout
= AmbiLayout::ACN
;
3958 device
->mAmbiScale
= AmbiNorm::SN3D
;
3960 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3962 device
->mAmbiLayout
= AmbiLayout::ACN
;
3963 device
->mAmbiScale
= AmbiNorm::N3D
;
3966 ERR("Unsupported ambi-format: %s\n", fmt
);
3970 ALCdevice
*head
{DeviceList
.load()};
3972 device
->next
.store(head
, std::memory_order_relaxed
);
3973 } while(!DeviceList
.compare_exchange_weak(head
, device
.get()));
3976 TRACE("Created device %p, \"%s\"\n", device
.get(), device
->DeviceName
.c_str());
3977 return device
.release();
3982 * Closes the given device.
3984 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3986 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3987 ALCdevice
*iter
{DeviceList
.load()};
3991 iter
= iter
->next
.load(std::memory_order_relaxed
);
3992 } while(iter
!= nullptr);
3993 if(!iter
|| iter
->Type
== Capture
)
3995 alcSetError(iter
, ALC_INVALID_DEVICE
);
3998 std::unique_lock
<almtx_t
> backlock
{device
->BackendLock
};
4000 ALCdevice
*origdev
{device
};
4001 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4002 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4008 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4012 ALCcontext
*ctx
{device
->ContextList
.load()};
4013 while(ctx
!= nullptr)
4015 ALCcontext
*next
= ctx
->next
.load(std::memory_order_relaxed
);
4016 WARN("Releasing context %p\n", ctx
);
4017 ReleaseContext(ctx
, device
);
4020 if((device
->Flags
&DEVICE_RUNNING
))
4021 V0(device
->Backend
,stop
)();
4022 device
->Flags
&= ~DEVICE_RUNNING
;
4025 ALCdevice_DecRef(device
);
4031 /************************************************
4032 * ALC capture functions
4033 ************************************************/
4034 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4038 if(!CaptureBackend
.name
)
4040 alcSetError(nullptr, ALC_INVALID_VALUE
);
4046 alcSetError(nullptr, ALC_INVALID_VALUE
);
4050 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4051 deviceName
= nullptr;
4053 std::unique_ptr
<ALCdevice
> device
{new ALCdevice
{Capture
}};
4055 device
->Frequency
= frequency
;
4056 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4058 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4061 alcSetError(nullptr, ALC_INVALID_ENUM
);
4064 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4066 device
->UpdateSize
= samples
;
4067 device
->NumUpdates
= 1;
4069 device
->Backend
= CaptureBackend
.getFactory().createBackend(device
.get(), ALCbackend_Capture
);
4070 if(!device
->Backend
)
4073 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4077 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4078 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4079 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4081 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
4082 if(err
!= ALC_NO_ERROR
)
4085 alcSetError(nullptr, err
);
4090 ALCdevice
*head
{DeviceList
.load()};
4092 device
->next
.store(head
, std::memory_order_relaxed
);
4093 } while(!DeviceList
.compare_exchange_weak(head
, device
.get()));
4096 TRACE("Created device %p, \"%s\"\n", device
.get(), device
->DeviceName
.c_str());
4097 return device
.release();
4100 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4102 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4104 ALCdevice
*iter
{DeviceList
.load()};
4108 iter
= iter
->next
.load(std::memory_order_relaxed
);
4109 } while(iter
!= nullptr);
4110 if(!iter
|| iter
->Type
!= Capture
)
4112 alcSetError(iter
, ALC_INVALID_DEVICE
);
4116 ALCdevice
*origdev
{device
};
4117 ALCdevice
*nextdev
{device
->next
.load(std::memory_order_relaxed
)};
4118 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4124 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4128 { std::lock_guard
<almtx_t
> _
{device
->BackendLock
};
4129 if((device
->Flags
&DEVICE_RUNNING
))
4130 V0(device
->Backend
,stop
)();
4131 device
->Flags
&= ~DEVICE_RUNNING
;
4134 ALCdevice_DecRef(device
);
4139 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4141 DeviceRef dev
{VerifyDevice(device
)};
4142 if(!dev
|| dev
->Type
!= Capture
)
4144 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4148 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
4149 if(!dev
->Connected
.load(std::memory_order_acquire
))
4150 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4151 else if(!(dev
->Flags
&DEVICE_RUNNING
))
4153 if(V0(dev
->Backend
,start
)())
4154 dev
->Flags
|= DEVICE_RUNNING
;
4157 aluHandleDisconnect(dev
.get(), "Device start failure");
4158 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4163 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4165 DeviceRef dev
{VerifyDevice(device
)};
4166 if(!dev
|| dev
->Type
!= Capture
)
4167 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4170 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
4171 if((dev
->Flags
&DEVICE_RUNNING
))
4172 V0(dev
->Backend
,stop
)();
4173 dev
->Flags
&= ~DEVICE_RUNNING
;
4177 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4179 DeviceRef dev
{VerifyDevice(device
)};
4180 if(!dev
|| dev
->Type
!= Capture
)
4182 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4186 ALCenum err
{ALC_INVALID_VALUE
};
4187 { std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
4188 if(samples
>= 0 && V0(dev
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4189 err
= V(dev
->Backend
,captureSamples
)(buffer
, samples
);
4191 if(err
!= ALC_NO_ERROR
)
4192 alcSetError(dev
.get(), err
);
4196 /************************************************
4197 * ALC loopback functions
4198 ************************************************/
4200 /* alcLoopbackOpenDeviceSOFT
4202 * Open a loopback device, for manual rendering.
4204 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4208 /* Make sure the device name, if specified, is us. */
4209 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4211 alcSetError(nullptr, ALC_INVALID_VALUE
);
4215 std::unique_ptr
<ALCdevice
> device
{new ALCdevice
{Loopback
}};
4217 device
->SourcesMax
= 256;
4218 device
->AuxiliaryEffectSlotMax
= 64;
4219 device
->NumAuxSends
= DEFAULT_SENDS
;
4222 device
->NumUpdates
= 0;
4223 device
->UpdateSize
= 0;
4225 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4226 device
->FmtChans
= DevFmtChannelsDefault
;
4227 device
->FmtType
= DevFmtTypeDefault
;
4229 ConfigValueUInt(nullptr, nullptr, "sources", &device
->SourcesMax
);
4230 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4232 ConfigValueUInt(nullptr, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4233 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4234 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4236 if(ConfigValueInt(nullptr, nullptr, "sends", &device
->NumAuxSends
))
4237 device
->NumAuxSends
= clampi(
4238 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4241 device
->NumStereoSources
= 1;
4242 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4244 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(
4245 device
.get(), ALCbackend_Loopback
);
4246 if(!device
->Backend
)
4249 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4253 // Open the "backend"
4254 V(device
->Backend
,open
)("Loopback");
4257 ALCdevice
*head
{DeviceList
.load()};
4259 device
->next
.store(head
, std::memory_order_relaxed
);
4260 } while(!DeviceList
.compare_exchange_weak(head
, device
.get()));
4263 TRACE("Created device %p\n", device
.get());
4264 return device
.release();
4267 /* alcIsRenderFormatSupportedSOFT
4269 * Determines if the loopback device supports the given format for rendering.
4271 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4273 DeviceRef dev
{VerifyDevice(device
)};
4274 if(!dev
|| dev
->Type
!= Loopback
)
4275 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4277 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4280 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4287 /* alcRenderSamplesSOFT
4289 * Renders some samples into a buffer, using the format last set by the
4290 * attributes given to alcCreateContext.
4292 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4294 DeviceRef dev
{VerifyDevice(device
)};
4295 if(!dev
|| dev
->Type
!= Loopback
)
4296 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4297 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4298 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4301 V0(dev
->Backend
,lock
)();
4302 aluMixData(dev
.get(), buffer
, samples
);
4303 V0(dev
->Backend
,unlock
)();
4308 /************************************************
4309 * ALC DSP pause/resume functions
4310 ************************************************/
4312 /* alcDevicePauseSOFT
4314 * Pause the DSP to stop audio processing.
4316 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4318 DeviceRef dev
{VerifyDevice(device
)};
4319 if(!dev
|| dev
->Type
!= Playback
)
4320 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4323 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
4324 if((dev
->Flags
&DEVICE_RUNNING
))
4325 V0(dev
->Backend
,stop
)();
4326 dev
->Flags
&= ~DEVICE_RUNNING
;
4327 dev
->Flags
|= DEVICE_PAUSED
;
4331 /* alcDeviceResumeSOFT
4333 * Resume the DSP to restart audio processing.
4335 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4337 DeviceRef dev
{VerifyDevice(device
)};
4338 if(!dev
|| dev
->Type
!= Playback
)
4339 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4342 std::lock_guard
<almtx_t
> _
{dev
->BackendLock
};
4343 if((dev
->Flags
&DEVICE_PAUSED
))
4345 dev
->Flags
&= ~DEVICE_PAUSED
;
4346 if(dev
->ContextList
.load() != nullptr)
4348 if(V0(dev
->Backend
,start
)() != ALC_FALSE
)
4349 dev
->Flags
|= DEVICE_RUNNING
;
4352 V0(dev
->Backend
,lock
)();
4353 aluHandleDisconnect(dev
.get(), "Device start failure");
4354 V0(dev
->Backend
,unlock
)();
4355 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4363 /************************************************
4364 * ALC HRTF functions
4365 ************************************************/
4367 /* alcGetStringiSOFT
4369 * Gets a string parameter at the given index.
4371 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4373 DeviceRef dev
{VerifyDevice(device
)};
4374 if(!dev
|| dev
->Type
== Capture
)
4375 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4376 else switch(paramName
)
4378 case ALC_HRTF_SPECIFIER_SOFT
:
4379 if(index
>= 0 && (size_t)index
< dev
->HrtfList
.size())
4380 return dev
->HrtfList
[index
].name
.c_str();
4381 alcSetError(dev
.get(), ALC_INVALID_VALUE
);
4385 alcSetError(dev
.get(), ALC_INVALID_ENUM
);
4392 /* alcResetDeviceSOFT
4394 * Resets the given device output, using the specified attribute list.
4396 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4398 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4399 DeviceRef dev
{VerifyDevice(device
)};
4400 if(!dev
|| dev
->Type
== Capture
|| !dev
->Connected
.load(std::memory_order_relaxed
))
4403 alcSetError(dev
.get(), ALC_INVALID_DEVICE
);
4406 std::unique_lock
<almtx_t
> backlock
{dev
->BackendLock
};
4409 ALCenum err
{UpdateDeviceParams(dev
.get(), attribs
)};
4412 if(err
!= ALC_NO_ERROR
)
4414 alcSetError(dev
.get(), err
);
4415 if(err
== ALC_INVALID_DEVICE
)
4417 V0(dev
->Backend
,lock
)();
4418 aluHandleDisconnect(dev
.get(), "Device start failure");
4419 V0(dev
->Backend
,unlock
)();