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"
53 #include "ringbuffer.h"
55 #include "fpu_modes.h"
61 #include "backends/base.h"
62 #include "backends/null.h"
63 #include "backends/loopback.h"
65 #include "backends/jack.h"
67 #ifdef HAVE_PULSEAUDIO
68 #include "backends/pulseaudio.h"
71 #include "backends/alsa.h"
74 #include "backends/wasapi.h"
77 #include "backends/coreaudio.h"
80 #include "backends/opensl.h"
83 #include "backends/solaris.h"
86 #include "backends/sndio.h"
89 #include "backends/oss.h"
92 #include "backends/qsa.h"
95 #include "backends/dsound.h"
98 #include "backends/winmm.h"
100 #ifdef HAVE_PORTAUDIO
101 #include "backends/portaudio.h"
104 #include "backends/sdl2.h"
107 #include "backends/wave.h"
113 /************************************************
115 ************************************************/
118 BackendFactory
& (*getFactory
)(void);
121 struct BackendInfo BackendList
[] = {
123 { "jack", JackBackendFactory::getFactory
},
125 #ifdef HAVE_PULSEAUDIO
126 { "pulse", PulseBackendFactory::getFactory
},
129 { "alsa", AlsaBackendFactory::getFactory
},
132 { "wasapi", WasapiBackendFactory::getFactory
},
134 #ifdef HAVE_COREAUDIO
135 { "core", CoreAudioBackendFactory::getFactory
},
138 { "opensl", OSLBackendFactory::getFactory
},
141 { "solaris", SolarisBackendFactory::getFactory
},
144 { "sndio", SndIOBackendFactory::getFactory
},
147 { "oss", OSSBackendFactory::getFactory
},
150 { "qsa", QSABackendFactory::getFactory
},
153 { "dsound", DSoundBackendFactory::getFactory
},
156 { "winmm", WinMMBackendFactory::getFactory
},
158 #ifdef HAVE_PORTAUDIO
159 { "port", PortBackendFactory::getFactory
},
162 { "sdl2", SDL2BackendFactory::getFactory
},
165 { "null", NullBackendFactory::getFactory
},
167 { "wave", WaveBackendFactory::getFactory
},
170 ALsizei BackendListSize
= COUNTOF(BackendList
);
172 struct BackendInfo PlaybackBackend
;
173 struct BackendInfo CaptureBackend
;
176 /************************************************
177 * Functions, enums, and errors
178 ************************************************/
179 #define DECL(x) { #x, (ALCvoid*)(x) }
181 const ALCchar
*funcName
;
184 DECL(alcCreateContext
),
185 DECL(alcMakeContextCurrent
),
186 DECL(alcProcessContext
),
187 DECL(alcSuspendContext
),
188 DECL(alcDestroyContext
),
189 DECL(alcGetCurrentContext
),
190 DECL(alcGetContextsDevice
),
192 DECL(alcCloseDevice
),
194 DECL(alcIsExtensionPresent
),
195 DECL(alcGetProcAddress
),
196 DECL(alcGetEnumValue
),
198 DECL(alcGetIntegerv
),
199 DECL(alcCaptureOpenDevice
),
200 DECL(alcCaptureCloseDevice
),
201 DECL(alcCaptureStart
),
202 DECL(alcCaptureStop
),
203 DECL(alcCaptureSamples
),
205 DECL(alcSetThreadContext
),
206 DECL(alcGetThreadContext
),
208 DECL(alcLoopbackOpenDeviceSOFT
),
209 DECL(alcIsRenderFormatSupportedSOFT
),
210 DECL(alcRenderSamplesSOFT
),
212 DECL(alcDevicePauseSOFT
),
213 DECL(alcDeviceResumeSOFT
),
215 DECL(alcGetStringiSOFT
),
216 DECL(alcResetDeviceSOFT
),
218 DECL(alcGetInteger64vSOFT
),
233 DECL(alIsExtensionPresent
),
234 DECL(alGetProcAddress
),
235 DECL(alGetEnumValue
),
242 DECL(alGetListenerf
),
243 DECL(alGetListener3f
),
244 DECL(alGetListenerfv
),
245 DECL(alGetListeneri
),
246 DECL(alGetListener3i
),
247 DECL(alGetListeneriv
),
249 DECL(alDeleteSources
),
265 DECL(alSourceRewindv
),
266 DECL(alSourcePausev
),
269 DECL(alSourceRewind
),
271 DECL(alSourceQueueBuffers
),
272 DECL(alSourceUnqueueBuffers
),
274 DECL(alDeleteBuffers
),
289 DECL(alDopplerFactor
),
290 DECL(alDopplerVelocity
),
291 DECL(alSpeedOfSound
),
292 DECL(alDistanceModel
),
295 DECL(alDeleteFilters
),
306 DECL(alDeleteEffects
),
316 DECL(alGenAuxiliaryEffectSlots
),
317 DECL(alDeleteAuxiliaryEffectSlots
),
318 DECL(alIsAuxiliaryEffectSlot
),
319 DECL(alAuxiliaryEffectSloti
),
320 DECL(alAuxiliaryEffectSlotiv
),
321 DECL(alAuxiliaryEffectSlotf
),
322 DECL(alAuxiliaryEffectSlotfv
),
323 DECL(alGetAuxiliaryEffectSloti
),
324 DECL(alGetAuxiliaryEffectSlotiv
),
325 DECL(alGetAuxiliaryEffectSlotf
),
326 DECL(alGetAuxiliaryEffectSlotfv
),
328 DECL(alDeferUpdatesSOFT
),
329 DECL(alProcessUpdatesSOFT
),
332 DECL(alSource3dSOFT
),
333 DECL(alSourcedvSOFT
),
334 DECL(alGetSourcedSOFT
),
335 DECL(alGetSource3dSOFT
),
336 DECL(alGetSourcedvSOFT
),
337 DECL(alSourcei64SOFT
),
338 DECL(alSource3i64SOFT
),
339 DECL(alSourcei64vSOFT
),
340 DECL(alGetSourcei64SOFT
),
341 DECL(alGetSource3i64SOFT
),
342 DECL(alGetSourcei64vSOFT
),
344 DECL(alGetStringiSOFT
),
346 DECL(alBufferStorageSOFT
),
347 DECL(alMapBufferSOFT
),
348 DECL(alUnmapBufferSOFT
),
349 DECL(alFlushMappedBufferSOFT
),
351 DECL(alEventControlSOFT
),
352 DECL(alEventCallbackSOFT
),
353 DECL(alGetPointerSOFT
),
354 DECL(alGetPointervSOFT
),
358 #define DECL(x) { #x, (x) }
360 const ALCchar
*enumName
;
362 } alcEnumerations
[] = {
367 DECL(ALC_MAJOR_VERSION
),
368 DECL(ALC_MINOR_VERSION
),
369 DECL(ALC_ATTRIBUTES_SIZE
),
370 DECL(ALC_ALL_ATTRIBUTES
),
371 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
372 DECL(ALC_DEVICE_SPECIFIER
),
373 DECL(ALC_ALL_DEVICES_SPECIFIER
),
374 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
375 DECL(ALC_EXTENSIONS
),
379 DECL(ALC_MONO_SOURCES
),
380 DECL(ALC_STEREO_SOURCES
),
381 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
382 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
383 DECL(ALC_CAPTURE_SAMPLES
),
386 DECL(ALC_EFX_MAJOR_VERSION
),
387 DECL(ALC_EFX_MINOR_VERSION
),
388 DECL(ALC_MAX_AUXILIARY_SENDS
),
390 DECL(ALC_FORMAT_CHANNELS_SOFT
),
391 DECL(ALC_FORMAT_TYPE_SOFT
),
394 DECL(ALC_STEREO_SOFT
),
396 DECL(ALC_5POINT1_SOFT
),
397 DECL(ALC_6POINT1_SOFT
),
398 DECL(ALC_7POINT1_SOFT
),
399 DECL(ALC_BFORMAT3D_SOFT
),
402 DECL(ALC_UNSIGNED_BYTE_SOFT
),
403 DECL(ALC_SHORT_SOFT
),
404 DECL(ALC_UNSIGNED_SHORT_SOFT
),
406 DECL(ALC_UNSIGNED_INT_SOFT
),
407 DECL(ALC_FLOAT_SOFT
),
410 DECL(ALC_DONT_CARE_SOFT
),
411 DECL(ALC_HRTF_STATUS_SOFT
),
412 DECL(ALC_HRTF_DISABLED_SOFT
),
413 DECL(ALC_HRTF_ENABLED_SOFT
),
414 DECL(ALC_HRTF_DENIED_SOFT
),
415 DECL(ALC_HRTF_REQUIRED_SOFT
),
416 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
417 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
418 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
419 DECL(ALC_HRTF_SPECIFIER_SOFT
),
420 DECL(ALC_HRTF_ID_SOFT
),
422 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
423 DECL(ALC_AMBISONIC_SCALING_SOFT
),
424 DECL(ALC_AMBISONIC_ORDER_SOFT
),
430 DECL(ALC_OUTPUT_LIMITER_SOFT
),
433 DECL(ALC_INVALID_DEVICE
),
434 DECL(ALC_INVALID_CONTEXT
),
435 DECL(ALC_INVALID_ENUM
),
436 DECL(ALC_INVALID_VALUE
),
437 DECL(ALC_OUT_OF_MEMORY
),
445 DECL(AL_SOURCE_RELATIVE
),
446 DECL(AL_CONE_INNER_ANGLE
),
447 DECL(AL_CONE_OUTER_ANGLE
),
457 DECL(AL_ORIENTATION
),
458 DECL(AL_REFERENCE_DISTANCE
),
459 DECL(AL_ROLLOFF_FACTOR
),
460 DECL(AL_CONE_OUTER_GAIN
),
461 DECL(AL_MAX_DISTANCE
),
463 DECL(AL_SAMPLE_OFFSET
),
464 DECL(AL_BYTE_OFFSET
),
465 DECL(AL_SOURCE_TYPE
),
468 DECL(AL_UNDETERMINED
),
469 DECL(AL_METERS_PER_UNIT
),
470 DECL(AL_LOOP_POINTS_SOFT
),
471 DECL(AL_DIRECT_CHANNELS_SOFT
),
473 DECL(AL_DIRECT_FILTER
),
474 DECL(AL_AUXILIARY_SEND_FILTER
),
475 DECL(AL_AIR_ABSORPTION_FACTOR
),
476 DECL(AL_ROOM_ROLLOFF_FACTOR
),
477 DECL(AL_CONE_OUTER_GAINHF
),
478 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
479 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
480 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
482 DECL(AL_SOURCE_STATE
),
488 DECL(AL_BUFFERS_QUEUED
),
489 DECL(AL_BUFFERS_PROCESSED
),
491 DECL(AL_FORMAT_MONO8
),
492 DECL(AL_FORMAT_MONO16
),
493 DECL(AL_FORMAT_MONO_FLOAT32
),
494 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
495 DECL(AL_FORMAT_STEREO8
),
496 DECL(AL_FORMAT_STEREO16
),
497 DECL(AL_FORMAT_STEREO_FLOAT32
),
498 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
499 DECL(AL_FORMAT_MONO_IMA4
),
500 DECL(AL_FORMAT_STEREO_IMA4
),
501 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
502 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
503 DECL(AL_FORMAT_QUAD8_LOKI
),
504 DECL(AL_FORMAT_QUAD16_LOKI
),
505 DECL(AL_FORMAT_QUAD8
),
506 DECL(AL_FORMAT_QUAD16
),
507 DECL(AL_FORMAT_QUAD32
),
508 DECL(AL_FORMAT_51CHN8
),
509 DECL(AL_FORMAT_51CHN16
),
510 DECL(AL_FORMAT_51CHN32
),
511 DECL(AL_FORMAT_61CHN8
),
512 DECL(AL_FORMAT_61CHN16
),
513 DECL(AL_FORMAT_61CHN32
),
514 DECL(AL_FORMAT_71CHN8
),
515 DECL(AL_FORMAT_71CHN16
),
516 DECL(AL_FORMAT_71CHN32
),
517 DECL(AL_FORMAT_REAR8
),
518 DECL(AL_FORMAT_REAR16
),
519 DECL(AL_FORMAT_REAR32
),
520 DECL(AL_FORMAT_MONO_MULAW
),
521 DECL(AL_FORMAT_MONO_MULAW_EXT
),
522 DECL(AL_FORMAT_STEREO_MULAW
),
523 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
524 DECL(AL_FORMAT_QUAD_MULAW
),
525 DECL(AL_FORMAT_51CHN_MULAW
),
526 DECL(AL_FORMAT_61CHN_MULAW
),
527 DECL(AL_FORMAT_71CHN_MULAW
),
528 DECL(AL_FORMAT_REAR_MULAW
),
529 DECL(AL_FORMAT_MONO_ALAW_EXT
),
530 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
532 DECL(AL_FORMAT_BFORMAT2D_8
),
533 DECL(AL_FORMAT_BFORMAT2D_16
),
534 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
535 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
536 DECL(AL_FORMAT_BFORMAT3D_8
),
537 DECL(AL_FORMAT_BFORMAT3D_16
),
538 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
539 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
545 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
546 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
548 DECL(AL_SOURCE_RADIUS
),
550 DECL(AL_STEREO_ANGLES
),
557 DECL(AL_INVALID_NAME
),
558 DECL(AL_INVALID_ENUM
),
559 DECL(AL_INVALID_VALUE
),
560 DECL(AL_INVALID_OPERATION
),
561 DECL(AL_OUT_OF_MEMORY
),
568 DECL(AL_DOPPLER_FACTOR
),
569 DECL(AL_DOPPLER_VELOCITY
),
570 DECL(AL_DISTANCE_MODEL
),
571 DECL(AL_SPEED_OF_SOUND
),
572 DECL(AL_SOURCE_DISTANCE_MODEL
),
573 DECL(AL_DEFERRED_UPDATES_SOFT
),
574 DECL(AL_GAIN_LIMIT_SOFT
),
576 DECL(AL_INVERSE_DISTANCE
),
577 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
578 DECL(AL_LINEAR_DISTANCE
),
579 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
580 DECL(AL_EXPONENT_DISTANCE
),
581 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
583 DECL(AL_FILTER_TYPE
),
584 DECL(AL_FILTER_NULL
),
585 DECL(AL_FILTER_LOWPASS
),
586 DECL(AL_FILTER_HIGHPASS
),
587 DECL(AL_FILTER_BANDPASS
),
589 DECL(AL_LOWPASS_GAIN
),
590 DECL(AL_LOWPASS_GAINHF
),
592 DECL(AL_HIGHPASS_GAIN
),
593 DECL(AL_HIGHPASS_GAINLF
),
595 DECL(AL_BANDPASS_GAIN
),
596 DECL(AL_BANDPASS_GAINHF
),
597 DECL(AL_BANDPASS_GAINLF
),
599 DECL(AL_EFFECT_TYPE
),
600 DECL(AL_EFFECT_NULL
),
601 DECL(AL_EFFECT_REVERB
),
602 DECL(AL_EFFECT_EAXREVERB
),
603 DECL(AL_EFFECT_CHORUS
),
604 DECL(AL_EFFECT_DISTORTION
),
605 DECL(AL_EFFECT_ECHO
),
606 DECL(AL_EFFECT_FLANGER
),
607 DECL(AL_EFFECT_PITCH_SHIFTER
),
608 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
610 DECL(AL_EFFECT_VOCAL_MORPHER
),
612 DECL(AL_EFFECT_RING_MODULATOR
),
613 DECL(AL_EFFECT_AUTOWAH
),
614 DECL(AL_EFFECT_COMPRESSOR
),
615 DECL(AL_EFFECT_EQUALIZER
),
616 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
617 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
619 DECL(AL_EFFECTSLOT_EFFECT
),
620 DECL(AL_EFFECTSLOT_GAIN
),
621 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
622 DECL(AL_EFFECTSLOT_NULL
),
624 DECL(AL_EAXREVERB_DENSITY
),
625 DECL(AL_EAXREVERB_DIFFUSION
),
626 DECL(AL_EAXREVERB_GAIN
),
627 DECL(AL_EAXREVERB_GAINHF
),
628 DECL(AL_EAXREVERB_GAINLF
),
629 DECL(AL_EAXREVERB_DECAY_TIME
),
630 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
631 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
632 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
633 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
634 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
635 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
636 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
637 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
638 DECL(AL_EAXREVERB_ECHO_TIME
),
639 DECL(AL_EAXREVERB_ECHO_DEPTH
),
640 DECL(AL_EAXREVERB_MODULATION_TIME
),
641 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
642 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
643 DECL(AL_EAXREVERB_HFREFERENCE
),
644 DECL(AL_EAXREVERB_LFREFERENCE
),
645 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
646 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
648 DECL(AL_REVERB_DENSITY
),
649 DECL(AL_REVERB_DIFFUSION
),
650 DECL(AL_REVERB_GAIN
),
651 DECL(AL_REVERB_GAINHF
),
652 DECL(AL_REVERB_DECAY_TIME
),
653 DECL(AL_REVERB_DECAY_HFRATIO
),
654 DECL(AL_REVERB_REFLECTIONS_GAIN
),
655 DECL(AL_REVERB_REFLECTIONS_DELAY
),
656 DECL(AL_REVERB_LATE_REVERB_GAIN
),
657 DECL(AL_REVERB_LATE_REVERB_DELAY
),
658 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
659 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
660 DECL(AL_REVERB_DECAY_HFLIMIT
),
662 DECL(AL_CHORUS_WAVEFORM
),
663 DECL(AL_CHORUS_PHASE
),
664 DECL(AL_CHORUS_RATE
),
665 DECL(AL_CHORUS_DEPTH
),
666 DECL(AL_CHORUS_FEEDBACK
),
667 DECL(AL_CHORUS_DELAY
),
669 DECL(AL_DISTORTION_EDGE
),
670 DECL(AL_DISTORTION_GAIN
),
671 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
672 DECL(AL_DISTORTION_EQCENTER
),
673 DECL(AL_DISTORTION_EQBANDWIDTH
),
676 DECL(AL_ECHO_LRDELAY
),
677 DECL(AL_ECHO_DAMPING
),
678 DECL(AL_ECHO_FEEDBACK
),
679 DECL(AL_ECHO_SPREAD
),
681 DECL(AL_FLANGER_WAVEFORM
),
682 DECL(AL_FLANGER_PHASE
),
683 DECL(AL_FLANGER_RATE
),
684 DECL(AL_FLANGER_DEPTH
),
685 DECL(AL_FLANGER_FEEDBACK
),
686 DECL(AL_FLANGER_DELAY
),
688 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
689 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
690 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
692 DECL(AL_RING_MODULATOR_FREQUENCY
),
693 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
694 DECL(AL_RING_MODULATOR_WAVEFORM
),
696 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
697 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
699 DECL(AL_COMPRESSOR_ONOFF
),
701 DECL(AL_EQUALIZER_LOW_GAIN
),
702 DECL(AL_EQUALIZER_LOW_CUTOFF
),
703 DECL(AL_EQUALIZER_MID1_GAIN
),
704 DECL(AL_EQUALIZER_MID1_CENTER
),
705 DECL(AL_EQUALIZER_MID1_WIDTH
),
706 DECL(AL_EQUALIZER_MID2_GAIN
),
707 DECL(AL_EQUALIZER_MID2_CENTER
),
708 DECL(AL_EQUALIZER_MID2_WIDTH
),
709 DECL(AL_EQUALIZER_HIGH_GAIN
),
710 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
712 DECL(AL_DEDICATED_GAIN
),
714 DECL(AL_AUTOWAH_ATTACK_TIME
),
715 DECL(AL_AUTOWAH_RELEASE_TIME
),
716 DECL(AL_AUTOWAH_RESONANCE
),
717 DECL(AL_AUTOWAH_PEAK_GAIN
),
719 DECL(AL_NUM_RESAMPLERS_SOFT
),
720 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
721 DECL(AL_SOURCE_RESAMPLER_SOFT
),
722 DECL(AL_RESAMPLER_NAME_SOFT
),
724 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
727 DECL(AL_MAP_READ_BIT_SOFT
),
728 DECL(AL_MAP_WRITE_BIT_SOFT
),
729 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
730 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
732 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
733 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
734 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
735 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
736 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
737 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
738 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
742 constexpr ALCchar alcNoError
[] = "No Error";
743 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
744 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
745 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
746 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
747 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
750 /************************************************
752 ************************************************/
754 /* Enumerated device names */
755 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
757 std::string alcAllDevicesList
;
758 std::string alcCaptureDeviceList
;
760 /* Default is always the first in the list */
761 std::string alcDefaultAllDevicesSpecifier
;
762 std::string alcCaptureDefaultDeviceSpecifier
;
764 /* Default context extensions */
765 constexpr ALchar alExtList
[] =
769 "AL_EXT_EXPONENT_DISTANCE "
772 "AL_EXT_LINEAR_DISTANCE "
775 "AL_EXT_MULAW_BFORMAT "
776 "AL_EXT_MULAW_MCFORMATS "
778 "AL_EXT_source_distance_model "
779 "AL_EXT_SOURCE_RADIUS "
780 "AL_EXT_STEREO_ANGLES "
781 "AL_LOKI_quadriphonic "
782 "AL_SOFT_block_alignment "
783 "AL_SOFT_deferred_updates "
784 "AL_SOFT_direct_channels "
786 "AL_SOFTX_filter_gain_ex "
787 "AL_SOFT_gain_clamp_ex "
788 "AL_SOFT_loop_points "
789 "AL_SOFTX_map_buffer "
791 "AL_SOFT_source_latency "
792 "AL_SOFT_source_length "
793 "AL_SOFT_source_resampler "
794 "AL_SOFT_source_spatialize";
796 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
798 /* Thread-local current context */
799 std::atomic
<void(*)(ALCcontext
*)> ThreadCtxProc
{nullptr};
801 ALCcontext
*ctx
{nullptr};
806 auto destruct
= ThreadCtxProc
.load();
812 ALCcontext
*get() const noexcept
{ return ctx
; }
813 void set(ALCcontext
*ctx_
) noexcept
{ ctx
= ctx_
; }
815 thread_local ThreadCtx LocalContext
;
816 /* Process-wide current context */
817 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
819 /* Flag to trap ALC device errors */
820 bool TrapALCError
{false};
822 /* One-time configuration init control */
823 std::once_flag alc_config_once
{};
825 /* Default effect that applies to sources that don't have an effect on send 0 */
826 ALeffect DefaultEffect
;
828 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
831 bool SuspendDefers
{true};
834 /************************************************
836 ************************************************/
837 constexpr ALCchar alcNoDeviceExtList
[] =
838 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
839 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
840 constexpr ALCchar alcExtensionList
[] =
841 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
842 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
843 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
844 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
845 constexpr ALCint alcMajorVersion
= 1;
846 constexpr ALCint alcMinorVersion
= 1;
848 constexpr ALCint alcEFXMajorVersion
= 1;
849 constexpr ALCint alcEFXMinorVersion
= 0;
852 /************************************************
854 ************************************************/
855 std::atomic
<ALCdevice
*> DeviceList
{nullptr};
857 std::recursive_mutex ListLock
;
861 /* Mixing thread piority level */
866 enum LogLevel LogLevel
= LogWarning
;
868 enum LogLevel LogLevel
= LogError
;
871 /************************************************
872 * Library initialization
873 ************************************************/
875 static void alc_init(void);
876 static void alc_deinit(void);
877 static void alc_deinit_safe(void);
879 #ifndef AL_LIBTYPE_STATIC
880 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
884 case DLL_PROCESS_ATTACH
:
885 /* Pin the DLL so we won't get unloaded until the process terminates */
886 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
887 (WCHAR
*)hModule
, &hModule
);
891 case DLL_PROCESS_DETACH
:
900 #elif defined(_MSC_VER)
901 #pragma section(".CRT$XCU",read)
902 static void alc_constructor(void);
903 static void alc_destructor(void);
904 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
906 static void alc_constructor(void)
908 atexit(alc_destructor
);
912 static void alc_destructor(void)
916 #elif defined(HAVE_GCC_DESTRUCTOR)
917 static void alc_init(void) __attribute__((constructor
));
918 static void alc_deinit(void) __attribute__((destructor
));
920 #error "No static initialization available on this platform!"
923 #elif defined(HAVE_GCC_DESTRUCTOR)
925 static void alc_init(void) __attribute__((constructor
));
926 static void alc_deinit(void) __attribute__((destructor
));
929 #error "No global initialization available on this platform!"
932 static void ReleaseThreadCtx(ALCcontext
*ctx
);
933 static void alc_init(void)
937 const char *str
{getenv("__ALSOFT_HALF_ANGLE_CONES")};
938 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
941 str
= getenv("__ALSOFT_REVERSE_Z");
942 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
945 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
946 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
947 OverrideReverbSpeedOfSound
= AL_TRUE
;
949 ThreadCtxProc
= ReleaseThreadCtx
;
952 static void alc_initconfig(void)
954 const char *devs
, *str
;
959 str
= getenv("ALSOFT_LOGLEVEL");
962 long lvl
= strtol(str
, nullptr, 0);
963 if(lvl
>= NoLog
&& lvl
<= LogRef
)
964 LogLevel
= static_cast<enum LogLevel
>(lvl
);
967 str
= getenv("ALSOFT_LOGFILE");
971 std::wstring wname
{utf8_to_wstr(str
)};
972 FILE *logfile
= _wfopen(wname
.c_str(), L
"wt");
974 FILE *logfile
= fopen(str
, "wt");
976 if(logfile
) LogFile
= logfile
;
977 else ERR("Failed to open log file '%s'\n", str
);
980 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
981 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
984 if(BackendListSize
> 0)
985 names
+= BackendList
[0].name
;
986 for(i
= 1;i
< BackendListSize
;i
++)
989 names
+= BackendList
[i
].name
;
991 TRACE("Supported backends: %s\n", names
.c_str());
995 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
998 if(strcasecmp(str
, "ignore") == 0)
1000 SuspendDefers
= false;
1001 TRACE("Selected context suspend behavior, \"ignore\"\n");
1004 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
1008 #if defined(HAVE_SSE4_1)
1009 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
1010 #elif defined(HAVE_SSE3)
1011 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
1012 #elif defined(HAVE_SSE2)
1013 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
1014 #elif defined(HAVE_SSE)
1015 capfilter
|= CPU_CAP_SSE
;
1018 capfilter
|= CPU_CAP_NEON
;
1020 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str
))
1022 if(strcasecmp(str
, "all") == 0)
1027 const char *next
= str
;
1031 while(isspace(str
[0]))
1033 next
= strchr(str
, ',');
1035 if(!str
[0] || str
[0] == ',')
1038 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1039 while(len
> 0 && isspace(str
[len
-1]))
1041 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
1042 capfilter
&= ~CPU_CAP_SSE
;
1043 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
1044 capfilter
&= ~CPU_CAP_SSE2
;
1045 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
1046 capfilter
&= ~CPU_CAP_SSE3
;
1047 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
1048 capfilter
&= ~CPU_CAP_SSE4_1
;
1049 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
1050 capfilter
&= ~CPU_CAP_NEON
;
1052 WARN("Invalid CPU extension \"%s\"\n", str
);
1056 FillCPUCaps(capfilter
);
1063 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel
);
1068 str
= getenv("ALSOFT_TRAP_ERROR");
1069 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1071 TrapALError
= AL_TRUE
;
1072 TrapALCError
= true;
1076 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1077 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1078 TrapALError
= AL_TRUE
;
1079 TrapALError
= GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError
);
1081 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1082 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1083 TrapALCError
= true;
1084 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError
);
1087 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf
))
1088 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1090 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1091 ConfigValueStr(nullptr, nullptr, "drivers", &devs
))
1095 const char *next
= devs
;
1096 int endlist
, delitem
;
1101 while(isspace(devs
[0]))
1103 next
= strchr(devs
, ',');
1105 delitem
= (devs
[0] == '-');
1106 if(devs
[0] == '-') devs
++;
1108 if(!devs
[0] || devs
[0] == ',')
1115 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1116 while(len
> 0 && isspace(devs
[len
-1]))
1119 /* HACK: For backwards compatibility, convert backend references of
1120 * mmdevapi to wasapi. This should eventually be removed.
1122 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1128 for(n
= i
;n
< BackendListSize
;n
++)
1130 if(len
== strlen(BackendList
[n
].name
) &&
1131 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1135 for(;n
+1 < BackendListSize
;n
++)
1136 BackendList
[n
] = BackendList
[n
+1];
1141 struct BackendInfo Bkp
= BackendList
[n
];
1143 BackendList
[n
] = BackendList
[n
-1];
1144 BackendList
[n
] = Bkp
;
1154 BackendListSize
= i
;
1157 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1159 BackendList
[n
] = BackendList
[i
];
1161 BackendFactory
&factory
= BackendList
[n
].getFactory();
1164 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1168 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1169 if(!PlaybackBackend
.name
&& factory
.querySupport(ALCbackend_Playback
))
1171 PlaybackBackend
= BackendList
[n
];
1172 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1174 if(!CaptureBackend
.name
&& factory
.querySupport(ALCbackend_Capture
))
1176 CaptureBackend
= BackendList
[n
];
1177 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1181 BackendListSize
= n
;
1183 LoopbackBackendFactory::getFactory().init();
1185 if(!PlaybackBackend
.name
)
1186 WARN("No playback backend available!\n");
1187 if(!CaptureBackend
.name
)
1188 WARN("No capture backend available!\n");
1190 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str
))
1193 const char *next
= str
;
1197 next
= strchr(str
, ',');
1199 if(!str
[0] || next
== str
)
1202 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1203 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1205 if(len
== strlen(EffectList
[n
].name
) &&
1206 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1207 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1212 InitEffect(&DefaultEffect
);
1213 str
= getenv("ALSOFT_DEFAULT_REVERB");
1214 if((str
&& str
[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str
))
1215 LoadReverbPreset(str
, &DefaultEffect
);
1217 #define DO_INITCONFIG() std::call_once(alc_config_once, [](){alc_initconfig();})
1220 /************************************************
1221 * Library deinitialization
1222 ************************************************/
1223 static void alc_cleanup(void)
1225 alcAllDevicesList
.clear();
1226 alcCaptureDeviceList
.clear();
1228 alcDefaultAllDevicesSpecifier
.clear();
1229 alcCaptureDefaultDeviceSpecifier
.clear();
1231 if(ALCdevice
*dev
{DeviceList
.exchange(nullptr)})
1236 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
1237 } while(dev
!= nullptr);
1238 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1242 static void alc_deinit_safe(void)
1249 ThreadCtxProc
= nullptr;
1251 if(LogFile
!= stderr
)
1256 static void alc_deinit(void)
1262 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1263 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1265 for(i
= 0;i
< BackendListSize
;i
++)
1266 BackendList
[i
].getFactory().deinit();
1268 LoopbackBackendFactory::getFactory().deinit();
1274 /************************************************
1275 * Device enumeration
1276 ************************************************/
1277 static void ProbeDevices(std::string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1281 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1283 if(backendinfo
->getFactory
)
1284 backendinfo
->getFactory().probe(type
, list
);
1286 static void ProbeAllDevicesList(void)
1287 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1288 static void ProbeCaptureDeviceList(void)
1289 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1292 /************************************************
1293 * Device format information
1294 ************************************************/
1295 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1299 case DevFmtByte
: return "Signed Byte";
1300 case DevFmtUByte
: return "Unsigned Byte";
1301 case DevFmtShort
: return "Signed Short";
1302 case DevFmtUShort
: return "Unsigned Short";
1303 case DevFmtInt
: return "Signed Int";
1304 case DevFmtUInt
: return "Unsigned Int";
1305 case DevFmtFloat
: return "Float";
1307 return "(unknown type)";
1309 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1313 case DevFmtMono
: return "Mono";
1314 case DevFmtStereo
: return "Stereo";
1315 case DevFmtQuad
: return "Quadraphonic";
1316 case DevFmtX51
: return "5.1 Surround";
1317 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1318 case DevFmtX61
: return "6.1 Surround";
1319 case DevFmtX71
: return "7.1 Surround";
1320 case DevFmtAmbi3D
: return "Ambisonic 3D";
1322 return "(unknown channels)";
1325 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1329 case DevFmtByte
: return sizeof(ALbyte
);
1330 case DevFmtUByte
: return sizeof(ALubyte
);
1331 case DevFmtShort
: return sizeof(ALshort
);
1332 case DevFmtUShort
: return sizeof(ALushort
);
1333 case DevFmtInt
: return sizeof(ALint
);
1334 case DevFmtUInt
: return sizeof(ALuint
);
1335 case DevFmtFloat
: return sizeof(ALfloat
);
1339 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1343 case DevFmtMono
: return 1;
1344 case DevFmtStereo
: return 2;
1345 case DevFmtQuad
: return 4;
1346 case DevFmtX51
: return 6;
1347 case DevFmtX51Rear
: return 6;
1348 case DevFmtX61
: return 7;
1349 case DevFmtX71
: return 8;
1350 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1351 (ambiorder
== 2) ? 9 :
1352 (ambiorder
== 1) ? 4 : 1;
1357 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1358 enum DevFmtType
*type
)
1360 static const struct {
1362 enum DevFmtChannels channels
;
1363 enum DevFmtType type
;
1365 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1366 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1367 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1369 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1370 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1371 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1373 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1374 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1375 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1377 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1378 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1379 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1381 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1382 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1383 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1385 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1386 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1387 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1391 for(i
= 0;i
< COUNTOF(list
);i
++)
1393 if(list
[i
].format
== format
)
1395 *chans
= list
[i
].channels
;
1396 *type
= list
[i
].type
;
1404 static ALCboolean
IsValidALCType(ALCenum type
)
1409 case ALC_UNSIGNED_BYTE_SOFT
:
1410 case ALC_SHORT_SOFT
:
1411 case ALC_UNSIGNED_SHORT_SOFT
:
1413 case ALC_UNSIGNED_INT_SOFT
:
1414 case ALC_FLOAT_SOFT
:
1420 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1425 case ALC_STEREO_SOFT
:
1427 case ALC_5POINT1_SOFT
:
1428 case ALC_6POINT1_SOFT
:
1429 case ALC_7POINT1_SOFT
:
1430 case ALC_BFORMAT3D_SOFT
:
1436 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1447 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1459 /************************************************
1460 * Miscellaneous ALC helpers
1461 ************************************************/
1463 /* SetDefaultWFXChannelOrder
1465 * Sets the default channel order used by WaveFormatEx.
1467 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1471 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1472 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1474 switch(device
->FmtChans
)
1477 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1480 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1481 device
->RealOut
.ChannelName
[1] = FrontRight
;
1484 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1485 device
->RealOut
.ChannelName
[1] = FrontRight
;
1486 device
->RealOut
.ChannelName
[2] = BackLeft
;
1487 device
->RealOut
.ChannelName
[3] = BackRight
;
1490 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1491 device
->RealOut
.ChannelName
[1] = FrontRight
;
1492 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1493 device
->RealOut
.ChannelName
[3] = LFE
;
1494 device
->RealOut
.ChannelName
[4] = SideLeft
;
1495 device
->RealOut
.ChannelName
[5] = SideRight
;
1498 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1499 device
->RealOut
.ChannelName
[1] = FrontRight
;
1500 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1501 device
->RealOut
.ChannelName
[3] = LFE
;
1502 device
->RealOut
.ChannelName
[4] = BackLeft
;
1503 device
->RealOut
.ChannelName
[5] = BackRight
;
1506 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1507 device
->RealOut
.ChannelName
[1] = FrontRight
;
1508 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1509 device
->RealOut
.ChannelName
[3] = LFE
;
1510 device
->RealOut
.ChannelName
[4] = BackCenter
;
1511 device
->RealOut
.ChannelName
[5] = SideLeft
;
1512 device
->RealOut
.ChannelName
[6] = SideRight
;
1515 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1516 device
->RealOut
.ChannelName
[1] = FrontRight
;
1517 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1518 device
->RealOut
.ChannelName
[3] = LFE
;
1519 device
->RealOut
.ChannelName
[4] = BackLeft
;
1520 device
->RealOut
.ChannelName
[5] = BackRight
;
1521 device
->RealOut
.ChannelName
[6] = SideLeft
;
1522 device
->RealOut
.ChannelName
[7] = SideRight
;
1525 device
->RealOut
.ChannelName
[0] = Aux0
;
1526 if(device
->mAmbiOrder
> 0)
1528 device
->RealOut
.ChannelName
[1] = Aux1
;
1529 device
->RealOut
.ChannelName
[2] = Aux2
;
1530 device
->RealOut
.ChannelName
[3] = Aux3
;
1532 if(device
->mAmbiOrder
> 1)
1534 device
->RealOut
.ChannelName
[4] = Aux4
;
1535 device
->RealOut
.ChannelName
[5] = Aux5
;
1536 device
->RealOut
.ChannelName
[6] = Aux6
;
1537 device
->RealOut
.ChannelName
[7] = Aux7
;
1538 device
->RealOut
.ChannelName
[8] = Aux8
;
1540 if(device
->mAmbiOrder
> 2)
1542 device
->RealOut
.ChannelName
[9] = Aux9
;
1543 device
->RealOut
.ChannelName
[10] = Aux10
;
1544 device
->RealOut
.ChannelName
[11] = Aux11
;
1545 device
->RealOut
.ChannelName
[12] = Aux12
;
1546 device
->RealOut
.ChannelName
[13] = Aux13
;
1547 device
->RealOut
.ChannelName
[14] = Aux14
;
1548 device
->RealOut
.ChannelName
[15] = Aux15
;
1554 /* SetDefaultChannelOrder
1556 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1558 void SetDefaultChannelOrder(ALCdevice
*device
)
1562 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1563 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1565 switch(device
->FmtChans
)
1568 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1569 device
->RealOut
.ChannelName
[1] = FrontRight
;
1570 device
->RealOut
.ChannelName
[2] = BackLeft
;
1571 device
->RealOut
.ChannelName
[3] = BackRight
;
1572 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1573 device
->RealOut
.ChannelName
[5] = LFE
;
1576 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1577 device
->RealOut
.ChannelName
[1] = FrontRight
;
1578 device
->RealOut
.ChannelName
[2] = BackLeft
;
1579 device
->RealOut
.ChannelName
[3] = BackRight
;
1580 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1581 device
->RealOut
.ChannelName
[5] = LFE
;
1582 device
->RealOut
.ChannelName
[6] = SideLeft
;
1583 device
->RealOut
.ChannelName
[7] = SideRight
;
1586 /* Same as WFX order */
1593 SetDefaultWFXChannelOrder(device
);
1599 /* ALCcontext_DeferUpdates
1601 * Defers/suspends updates for the given context's listener and sources. This
1602 * does *NOT* stop mixing, but rather prevents certain property changes from
1605 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1607 context
->DeferUpdates
.store(true);
1610 /* ALCcontext_ProcessUpdates
1612 * Resumes update processing after being deferred.
1614 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1616 almtx_lock(&context
->PropLock
);
1617 if(context
->DeferUpdates
.exchange(false))
1619 /* Tell the mixer to stop applying updates, then wait for any active
1620 * updating to finish, before providing updates.
1622 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1623 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1626 if(!context
->PropsClean
.test_and_set(std::memory_order_acq_rel
))
1627 UpdateContextProps(context
);
1628 if(!context
->Listener
.PropsClean
.test_and_set(std::memory_order_acq_rel
))
1629 UpdateListenerProps(context
);
1630 UpdateAllEffectSlotProps(context
);
1631 UpdateAllSourceProps(context
);
1633 /* Now with all updates declared, let the mixer continue applying them
1634 * so they all happen at once.
1636 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1638 almtx_unlock(&context
->PropLock
);
1644 * Stores the latest ALC device error
1646 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1648 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1652 /* DebugBreak() will cause an exception if there is no debugger */
1653 if(IsDebuggerPresent())
1655 #elif defined(SIGTRAP)
1661 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1663 LastNullDeviceError
.store(errorCode
);
1667 static struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1669 return CompressorInit(device
->RealOut
.NumChannels
, device
->Frequency
,
1670 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
,
1671 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1676 * Updates the device's base clock time with however many samples have been
1677 * done. This is used so frequency changes on the device don't cause the time
1678 * to jump forward or back. Must not be called while the device is running/
1681 static inline void UpdateClockBase(ALCdevice
*device
)
1683 IncrementRef(&device
->MixCount
);
1684 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1685 device
->SamplesDone
= 0;
1686 IncrementRef(&device
->MixCount
);
1689 /* UpdateDeviceParams
1691 * Updates device parameters according to the attribute list (caller is
1692 * responsible for holding the list lock).
1694 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1696 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1697 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1698 ALCenum gainLimiter
= device
->LimiterState
;
1699 const ALsizei old_sends
= device
->NumAuxSends
;
1700 ALsizei new_sends
= device
->NumAuxSends
;
1701 enum DevFmtChannels oldChans
;
1702 enum DevFmtType oldType
;
1703 ALboolean update_failed
;
1704 ALCsizei hrtf_id
= -1;
1705 ALCcontext
*context
;
1710 // Check for attributes
1711 if(device
->Type
== Loopback
)
1713 ALCsizei numMono
, numStereo
, numSends
;
1714 ALCenum alayout
= AL_NONE
;
1715 ALCenum ascale
= AL_NONE
;
1716 ALCenum schans
= AL_NONE
;
1717 ALCenum stype
= AL_NONE
;
1718 ALCsizei attrIdx
= 0;
1719 ALCsizei aorder
= 0;
1724 WARN("Missing attributes for loopback device\n");
1725 return ALC_INVALID_VALUE
;
1728 numMono
= device
->NumMonoSources
;
1729 numStereo
= device
->NumStereoSources
;
1730 numSends
= old_sends
;
1732 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1733 while(attrList
[attrIdx
])
1735 switch(attrList
[attrIdx
])
1737 case ALC_FORMAT_CHANNELS_SOFT
:
1738 schans
= attrList
[attrIdx
+ 1];
1739 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1740 if(!IsValidALCChannels(schans
))
1741 return ALC_INVALID_VALUE
;
1744 case ALC_FORMAT_TYPE_SOFT
:
1745 stype
= attrList
[attrIdx
+ 1];
1746 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1747 if(!IsValidALCType(stype
))
1748 return ALC_INVALID_VALUE
;
1752 freq
= attrList
[attrIdx
+ 1];
1753 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1754 if(freq
< MIN_OUTPUT_RATE
)
1755 return ALC_INVALID_VALUE
;
1758 case ALC_AMBISONIC_LAYOUT_SOFT
:
1759 alayout
= attrList
[attrIdx
+ 1];
1760 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1761 if(!IsValidAmbiLayout(alayout
))
1762 return ALC_INVALID_VALUE
;
1765 case ALC_AMBISONIC_SCALING_SOFT
:
1766 ascale
= attrList
[attrIdx
+ 1];
1767 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1768 if(!IsValidAmbiScaling(ascale
))
1769 return ALC_INVALID_VALUE
;
1772 case ALC_AMBISONIC_ORDER_SOFT
:
1773 aorder
= attrList
[attrIdx
+ 1];
1774 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1775 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1776 return ALC_INVALID_VALUE
;
1779 case ALC_MONO_SOURCES
:
1780 numMono
= attrList
[attrIdx
+ 1];
1781 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1782 numMono
= maxi(numMono
, 0);
1785 case ALC_STEREO_SOURCES
:
1786 numStereo
= attrList
[attrIdx
+ 1];
1787 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1788 numStereo
= maxi(numStereo
, 0);
1791 case ALC_MAX_AUXILIARY_SENDS
:
1792 numSends
= attrList
[attrIdx
+ 1];
1793 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1794 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1798 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1799 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1800 hrtf_appreq
= Hrtf_Disable
;
1801 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1802 hrtf_appreq
= Hrtf_Enable
;
1804 hrtf_appreq
= Hrtf_Default
;
1807 case ALC_HRTF_ID_SOFT
:
1808 hrtf_id
= attrList
[attrIdx
+ 1];
1809 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1812 case ALC_OUTPUT_LIMITER_SOFT
:
1813 gainLimiter
= attrList
[attrIdx
+ 1];
1814 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1818 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1819 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1827 if(!schans
|| !stype
|| !freq
)
1829 WARN("Missing format for loopback device\n");
1830 return ALC_INVALID_VALUE
;
1832 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1834 WARN("Missing ambisonic info for loopback device\n");
1835 return ALC_INVALID_VALUE
;
1838 if((device
->Flags
&DEVICE_RUNNING
))
1839 V0(device
->Backend
,stop
)();
1840 device
->Flags
&= ~DEVICE_RUNNING
;
1842 UpdateClockBase(device
);
1844 device
->Frequency
= freq
;
1845 device
->FmtChans
= static_cast<enum DevFmtChannels
>(schans
);
1846 device
->FmtType
= static_cast<enum DevFmtType
>(stype
);
1847 if(schans
== ALC_BFORMAT3D_SOFT
)
1849 device
->mAmbiOrder
= aorder
;
1850 device
->mAmbiLayout
= static_cast<enum AmbiLayout
>(alayout
);
1851 device
->mAmbiScale
= static_cast<enum AmbiNorm
>(ascale
);
1854 if(numMono
> INT_MAX
-numStereo
)
1855 numMono
= INT_MAX
-numStereo
;
1856 numMono
+= numStereo
;
1857 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono
))
1863 numMono
= maxi(numMono
, 256);
1864 numStereo
= mini(numStereo
, numMono
);
1865 numMono
-= numStereo
;
1866 device
->SourcesMax
= numMono
+ numStereo
;
1868 device
->NumMonoSources
= numMono
;
1869 device
->NumStereoSources
= numStereo
;
1871 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends
))
1872 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1874 new_sends
= numSends
;
1876 else if(attrList
&& attrList
[0])
1878 ALCsizei numMono
, numStereo
, numSends
;
1879 ALCsizei attrIdx
= 0;
1882 /* If a context is already running on the device, stop playback so the
1883 * device attributes can be updated. */
1884 if((device
->Flags
&DEVICE_RUNNING
))
1885 V0(device
->Backend
,stop
)();
1886 device
->Flags
&= ~DEVICE_RUNNING
;
1888 UpdateClockBase(device
);
1890 freq
= device
->Frequency
;
1891 numMono
= device
->NumMonoSources
;
1892 numStereo
= device
->NumStereoSources
;
1893 numSends
= old_sends
;
1895 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1896 while(attrList
[attrIdx
])
1898 switch(attrList
[attrIdx
])
1901 freq
= attrList
[attrIdx
+ 1];
1902 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1903 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1906 case ALC_MONO_SOURCES
:
1907 numMono
= attrList
[attrIdx
+ 1];
1908 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1909 numMono
= maxi(numMono
, 0);
1912 case ALC_STEREO_SOURCES
:
1913 numStereo
= attrList
[attrIdx
+ 1];
1914 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1915 numStereo
= maxi(numStereo
, 0);
1918 case ALC_MAX_AUXILIARY_SENDS
:
1919 numSends
= attrList
[attrIdx
+ 1];
1920 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1921 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1925 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1926 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1927 hrtf_appreq
= Hrtf_Disable
;
1928 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1929 hrtf_appreq
= Hrtf_Enable
;
1931 hrtf_appreq
= Hrtf_Default
;
1934 case ALC_HRTF_ID_SOFT
:
1935 hrtf_id
= attrList
[attrIdx
+ 1];
1936 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1939 case ALC_OUTPUT_LIMITER_SOFT
:
1940 gainLimiter
= attrList
[attrIdx
+ 1];
1941 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1945 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1946 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1954 ConfigValueUInt(device
->DeviceName
.c_str(), nullptr, "frequency", &freq
);
1955 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1957 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1959 /* SSE and Neon do best with the update size being a multiple of 4 */
1960 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1961 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1963 device
->Frequency
= freq
;
1965 if(numMono
> INT_MAX
-numStereo
)
1966 numMono
= INT_MAX
-numStereo
;
1967 numMono
+= numStereo
;
1968 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sources", &numMono
))
1974 numMono
= maxi(numMono
, 256);
1975 numStereo
= mini(numStereo
, numMono
);
1976 numMono
-= numStereo
;
1977 device
->SourcesMax
= numMono
+ numStereo
;
1979 device
->NumMonoSources
= numMono
;
1980 device
->NumStereoSources
= numStereo
;
1982 if(ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "sends", &new_sends
))
1983 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1985 new_sends
= numSends
;
1988 if((device
->Flags
&DEVICE_RUNNING
))
1989 return ALC_NO_ERROR
;
1991 al_free(device
->Uhj_Encoder
);
1992 device
->Uhj_Encoder
= nullptr;
1994 al_free(device
->Bs2b
);
1995 device
->Bs2b
= nullptr;
1997 al_free(device
->ChannelDelay
[0].Buffer
);
1998 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2000 device
->ChannelDelay
[i
].Length
= 0;
2001 device
->ChannelDelay
[i
].Buffer
= nullptr;
2004 device
->Dry
.Buffer
= nullptr;
2005 device
->Dry
.NumChannels
= 0;
2006 device
->FOAOut
.Buffer
= nullptr;
2007 device
->FOAOut
.NumChannels
= 0;
2008 device
->RealOut
.Buffer
= nullptr;
2009 device
->RealOut
.NumChannels
= 0;
2010 device
->MixBuffer
.clear();
2011 device
->MixBuffer
.shrink_to_fit();
2013 UpdateClockBase(device
);
2014 device
->FixedLatency
= 0;
2016 device
->DitherSeed
= DITHER_RNG_SEED
;
2018 /*************************************************************************
2019 * Update device format request if HRTF is requested
2021 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2022 if(device
->Type
!= Loopback
)
2025 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "hrtf", &hrtf
))
2027 if(strcasecmp(hrtf
, "true") == 0)
2028 hrtf_userreq
= Hrtf_Enable
;
2029 else if(strcasecmp(hrtf
, "false") == 0)
2030 hrtf_userreq
= Hrtf_Disable
;
2031 else if(strcasecmp(hrtf
, "auto") != 0)
2032 ERR("Unexpected hrtf value: %s\n", hrtf
);
2035 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2037 struct Hrtf
*hrtf
= nullptr;
2038 if(device
->HrtfList
.empty())
2039 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
2040 if(!device
->HrtfList
.empty())
2042 if(hrtf_id
>= 0 && (size_t)hrtf_id
< device
->HrtfList
.size())
2043 hrtf
= GetLoadedHrtf(device
->HrtfList
[hrtf_id
].hrtf
);
2045 hrtf
= GetLoadedHrtf(device
->HrtfList
.front().hrtf
);
2050 device
->FmtChans
= DevFmtStereo
;
2051 device
->Frequency
= hrtf
->sampleRate
;
2052 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2053 if(device
->HrtfHandle
)
2054 Hrtf_DecRef(device
->HrtfHandle
);
2055 device
->HrtfHandle
= hrtf
;
2059 hrtf_userreq
= Hrtf_Default
;
2060 hrtf_appreq
= Hrtf_Disable
;
2061 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2066 oldFreq
= device
->Frequency
;
2067 oldChans
= device
->FmtChans
;
2068 oldType
= device
->FmtType
;
2070 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2071 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2072 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2073 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2074 device
->UpdateSize
, device
->NumUpdates
2077 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2078 return ALC_INVALID_DEVICE
;
2080 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2082 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2083 DevFmtChannelsString(device
->FmtChans
));
2084 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2086 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2088 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2089 DevFmtTypeString(device
->FmtType
));
2090 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2092 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2094 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2095 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2098 if((device
->UpdateSize
&3) != 0)
2100 if((CPUCapFlags
&CPU_CAP_SSE
))
2101 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2102 if((CPUCapFlags
&CPU_CAP_NEON
))
2103 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2106 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2107 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2108 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2111 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2112 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2113 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2115 /* Allocate extra channels for any post-filter output. */
2116 ALsizei num_chans
{device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2117 device
->RealOut
.NumChannels
};
2119 TRACE("Allocating %d channels, " SZFMT
" bytes\n", num_chans
,
2120 num_chans
*sizeof(device
->MixBuffer
[0]));
2121 device
->MixBuffer
.resize(num_chans
);
2123 device
->Dry
.Buffer
= &reinterpret_cast<ALfloat(&)[BUFFERSIZE
]>(device
->MixBuffer
[0]);
2124 if(device
->RealOut
.NumChannels
!= 0)
2125 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2126 device
->FOAOut
.NumChannels
;
2129 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2130 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2133 if(device
->FOAOut
.NumChannels
!= 0)
2134 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2137 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2138 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2141 device
->NumAuxSends
= new_sends
;
2142 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2143 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2144 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2146 device
->DitherDepth
= 0.0f
;
2147 if(GetConfigValueBool(device
->DeviceName
.c_str(), nullptr, "dither", 1))
2150 ConfigValueInt(device
->DeviceName
.c_str(), nullptr, "dither-depth", &depth
);
2153 switch(device
->FmtType
)
2172 depth
= clampi(depth
, 2, 24);
2173 device
->DitherDepth
= std::pow(2.0f
, (ALfloat
)(depth
-1));
2176 if(!(device
->DitherDepth
> 0.0f
))
2177 TRACE("Dithering disabled\n");
2179 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5f
)+1,
2180 device
->DitherDepth
);
2182 device
->LimiterState
= gainLimiter
;
2183 if(ConfigValueBool(device
->DeviceName
.c_str(), nullptr, "output-limiter", &val
))
2184 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2186 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2187 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2188 * output (where samples must be clamped), and don't for floating-point
2189 * (which can take unclamped samples).
2191 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2193 switch(device
->FmtType
)
2201 gainLimiter
= ALC_TRUE
;
2204 gainLimiter
= ALC_FALSE
;
2208 if(gainLimiter
!= ALC_FALSE
)
2210 ALfloat thrshld
= 1.0f
;
2211 switch(device
->FmtType
)
2215 thrshld
= 127.0f
/ 128.0f
;
2219 thrshld
= 32767.0f
/ 32768.0f
;
2226 if(device
->DitherDepth
> 0.0f
)
2227 thrshld
-= 1.0f
/ device
->DitherDepth
;
2229 al_free(device
->Limiter
);
2230 device
->Limiter
= CreateDeviceLimiter(device
, std::log10(thrshld
) * 20.0f
);
2231 device
->FixedLatency
+= (ALuint
)(GetCompressorLookAhead(device
->Limiter
) *
2232 DEVICE_CLOCK_RES
/ device
->Frequency
);
2236 al_free(device
->Limiter
);
2237 device
->Limiter
= nullptr;
2239 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2241 aluSelectPostProcess(device
);
2243 TRACE("Fixed device latency: %uns\n", device
->FixedLatency
);
2245 /* Need to delay returning failure until replacement Send arrays have been
2246 * allocated with the appropriate size.
2248 update_failed
= AL_FALSE
;
2250 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2253 struct ALvoiceProps
*vprops
;
2256 if(context
->DefaultSlot
)
2258 ALeffectslot
*slot
= context
->DefaultSlot
.get();
2259 EffectState
*state
= slot
->Effect
.State
;
2261 state
->mOutBuffer
= device
->Dry
.Buffer
;
2262 state
->mOutChannels
= device
->Dry
.NumChannels
;
2263 if(state
->deviceUpdate(device
) == AL_FALSE
)
2264 update_failed
= AL_TRUE
;
2266 UpdateEffectSlotProps(slot
, context
);
2269 almtx_lock(&context
->PropLock
);
2270 almtx_lock(&context
->EffectSlotLock
);
2271 for(auto &slot
: context
->EffectSlotList
)
2273 EffectState
*state
= slot
->Effect
.State
;
2275 state
->mOutBuffer
= device
->Dry
.Buffer
;
2276 state
->mOutChannels
= device
->Dry
.NumChannels
;
2277 if(state
->deviceUpdate(device
) == AL_FALSE
)
2278 update_failed
= AL_TRUE
;
2280 UpdateEffectSlotProps(slot
.get(), context
);
2282 almtx_unlock(&context
->EffectSlotLock
);
2284 almtx_lock(&context
->SourceLock
);
2285 for(auto &sublist
: context
->SourceList
)
2287 uint64_t usemask
= ~sublist
.FreeMask
;
2290 ALsizei idx
= CTZ64(usemask
);
2291 ALsource
*source
= sublist
.Sources
+ idx
;
2293 usemask
&= ~(U64(1) << idx
);
2295 if(old_sends
!= device
->NumAuxSends
)
2297 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2300 memcpy(sends
, source
->Send
,
2301 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2303 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2305 if(source
->Send
[s
].Slot
)
2306 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2307 source
->Send
[s
].Slot
= nullptr;
2309 al_free(source
->Send
);
2310 source
->Send
= static_cast<decltype(source
->Send
)>(sends
);
2311 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2313 source
->Send
[s
].Slot
= nullptr;
2314 source
->Send
[s
].Gain
= 1.0f
;
2315 source
->Send
[s
].GainHF
= 1.0f
;
2316 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2317 source
->Send
[s
].GainLF
= 1.0f
;
2318 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2322 source
->PropsClean
.clear(std::memory_order_release
);
2326 /* Clear any pre-existing voice property structs, in case the number of
2327 * auxiliary sends is changing. Active sources will have updates
2328 * respecified in UpdateAllSourceProps.
2330 vprops
= context
->FreeVoiceProps
.exchange(nullptr, std::memory_order_acq_rel
);
2333 struct ALvoiceProps
*next
= vprops
->next
.load(std::memory_order_relaxed
);
2338 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2339 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2341 ALvoice
*voice
= context
->Voices
[pos
];
2343 al_free(voice
->Update
.exchange(nullptr, std::memory_order_acq_rel
));
2345 if(voice
->Source
.load(std::memory_order_acquire
) == nullptr)
2348 if(device
->AvgSpeakerDist
> 0.0f
)
2350 /* Reinitialize the NFC filters for new parameters. */
2351 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2352 (device
->AvgSpeakerDist
* device
->Frequency
);
2353 for(i
= 0;i
< voice
->NumChannels
;i
++)
2354 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2357 almtx_unlock(&context
->SourceLock
);
2359 context
->PropsClean
.test_and_set(std::memory_order_release
);
2360 UpdateContextProps(context
);
2361 context
->Listener
.PropsClean
.test_and_set(std::memory_order_release
);
2362 UpdateListenerProps(context
);
2363 UpdateAllSourceProps(context
);
2364 almtx_unlock(&context
->PropLock
);
2366 context
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2370 return ALC_INVALID_DEVICE
;
2372 if(!(device
->Flags
&DEVICE_PAUSED
))
2374 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2375 return ALC_INVALID_DEVICE
;
2376 device
->Flags
|= DEVICE_RUNNING
;
2379 return ALC_NO_ERROR
;
2383 ALCdevice_struct::ALCdevice_struct(DeviceType type
)
2386 almtx_init(&BufferLock
, almtx_plain
);
2387 almtx_init(&EffectLock
, almtx_plain
);
2388 almtx_init(&FilterLock
, almtx_plain
);
2390 almtx_init(&BackendLock
, almtx_plain
);
2393 /* ALCdevice_struct::~ALCdevice_struct
2395 * Frees the device structure, and destroys any objects the app failed to
2396 * delete. Called once there's no more references on the device.
2398 ALCdevice_struct::~ALCdevice_struct()
2400 TRACE("%p\n", this);
2403 DELETE_OBJ(Backend
);
2406 almtx_destroy(&BackendLock
);
2408 ReleaseALBuffers(this);
2409 std::for_each(BufferList
.begin(), BufferList
.end(),
2410 [](BufferSubList
&entry
) noexcept
-> void
2411 { al_free(entry
.Buffers
); }
2414 almtx_destroy(&BufferLock
);
2416 ReleaseALEffects(this);
2417 std::for_each(EffectList
.begin(), EffectList
.end(),
2418 [](EffectSubList
&entry
) noexcept
-> void
2419 { al_free(entry
.Effects
); }
2422 almtx_destroy(&EffectLock
);
2424 ReleaseALFilters(this);
2425 std::for_each(FilterList
.begin(), FilterList
.end(),
2426 [](FilterSubList
&entry
) noexcept
-> void
2427 { al_free(entry
.Filters
); }
2430 almtx_destroy(&FilterLock
);
2434 Hrtf_DecRef(HrtfHandle
);
2435 HrtfHandle
= nullptr;
2442 al_free(Uhj_Encoder
);
2443 Uhj_Encoder
= nullptr;
2445 bformatdec_free(&AmbiDecoder
);
2446 ambiup_free(&AmbiUp
);
2449 Stablizer
= nullptr;
2454 al_free(ChannelDelay
[0].Buffer
);
2455 for(ALsizei i
{0};i
< MAX_OUTPUT_CHANNELS
;i
++)
2457 ChannelDelay
[i
].Gain
= 1.0f
;
2458 ChannelDelay
[i
].Length
= 0;
2459 ChannelDelay
[i
].Buffer
= nullptr;
2464 void ALCdevice_IncRef(ALCdevice
*device
)
2466 auto ref
= IncrementRef(&device
->ref
);
2467 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2470 void ALCdevice_DecRef(ALCdevice
*device
)
2472 auto ref
= DecrementRef(&device
->ref
);
2473 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2474 if(ref
== 0) delete device
;
2479 * Checks if the device handle is valid, and increments its ref count if so.
2481 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2483 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2484 ALCdevice
*tmpDevice
{DeviceList
.load()};
2487 if(tmpDevice
== *device
)
2489 ALCdevice_IncRef(tmpDevice
);
2492 tmpDevice
= ATOMIC_LOAD(&tmpDevice
->next
, almemory_order_relaxed
);
2500 ALCcontext_struct::ALCcontext_struct(ALCdevice
*device
)
2507 * Initializes context fields
2509 static ALvoid
InitContext(ALCcontext
*Context
)
2511 ALlistener
&listener
= Context
->Listener
;
2512 struct ALeffectslotArray
*auxslots
;
2515 almtx_init(&Context
->PropLock
, almtx_plain
);
2516 almtx_init(&Context
->SourceLock
, almtx_plain
);
2517 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2519 if(Context
->DefaultSlot
)
2521 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2522 FAM_SIZE(struct ALeffectslotArray
, slot
, 1)));
2523 auxslots
->count
= 1;
2524 auxslots
->slot
[0] = Context
->DefaultSlot
.get();
2528 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2529 sizeof(struct ALeffectslotArray
)));
2530 auxslots
->count
= 0;
2532 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2535 Context
->mDistanceModel
= DistanceModel::Default
;
2536 Context
->SourceDistanceModel
= AL_FALSE
;
2537 Context
->DopplerFactor
= 1.0f
;
2538 Context
->DopplerVelocity
= 1.0f
;
2539 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2540 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2541 alsem_init(&Context
->EventSem
, 0);
2543 Context
->ExtensionList
= alExtList
;
2546 listener
.Params
.Matrix
= aluMatrixf::Identity
;
2547 aluVectorSet(&listener
.Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2548 listener
.Params
.Gain
= listener
.Gain
;
2549 listener
.Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2550 listener
.Params
.DopplerFactor
= Context
->DopplerFactor
;
2551 listener
.Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2552 listener
.Params
.ReverbSpeedOfSound
= listener
.Params
.SpeedOfSound
*
2553 listener
.Params
.MetersPerUnit
;
2554 listener
.Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2555 listener
.Params
.mDistanceModel
= Context
->mDistanceModel
;
2558 Context
->AsyncEvents
= ll_ringbuffer_create(63, sizeof(AsyncEvent
), false);
2559 StartEventThrd(Context
);
2563 /* ALCcontext_struct::~ALCcontext_struct()
2565 * Cleans up the context, and destroys any remaining objects the app failed to
2566 * delete. Called once there's no more references on the context.
2568 ALCcontext_struct::~ALCcontext_struct()
2570 TRACE("%p\n", this);
2572 struct ALcontextProps
*cprops
{Update
.load(std::memory_order_relaxed
)};
2575 TRACE("Freed unapplied context update %p\n", cprops
);
2579 cprops
= FreeContextProps
.load(std::memory_order_acquire
);
2582 struct ALcontextProps
*next
{cprops
->next
.load(std::memory_order_relaxed
)};
2587 TRACE("Freed " SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2589 al_free(ActiveAuxSlots
.exchange(nullptr, std::memory_order_relaxed
));
2590 DefaultSlot
= nullptr;
2592 ReleaseALSources(this);
2593 std::for_each(SourceList
.begin(), SourceList
.end(),
2594 [](const SourceSubList
&entry
) noexcept
-> void
2595 { al_free(entry
.Sources
); }
2599 almtx_destroy(&SourceLock
);
2602 struct ALeffectslotProps
*eprops
{FreeEffectslotProps
.load(std::memory_order_acquire
)};
2605 struct ALeffectslotProps
*next
{eprops
->next
.load(std::memory_order_relaxed
)};
2606 if(eprops
->State
) eprops
->State
->DecRef();
2611 TRACE("Freed " SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2613 ReleaseALAuxiliaryEffectSlots(this);
2614 EffectSlotList
.clear();
2615 almtx_destroy(&EffectSlotLock
);
2618 struct ALvoiceProps
*vprops
{FreeVoiceProps
.load(std::memory_order_acquire
)};
2621 struct ALvoiceProps
*next
{vprops
->next
.load(std::memory_order_relaxed
)};
2626 TRACE("Freed " SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2628 for(ALsizei i
{0};i
< VoiceCount
;i
++)
2629 DeinitVoice(Voices
[i
]);
2635 struct ALlistenerProps
*lprops
{Listener
.Update
.load(std::memory_order_relaxed
)};
2638 TRACE("Freed unapplied listener update %p\n", lprops
);
2642 lprops
= FreeListenerProps
.load(std::memory_order_acquire
);
2645 struct ALlistenerProps
*next
{lprops
->next
.load(std::memory_order_relaxed
)};
2650 TRACE("Freed " SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2652 alsem_destroy(&EventSem
);
2654 ll_ringbuffer_free(AsyncEvents
);
2655 AsyncEvents
= nullptr;
2657 almtx_destroy(&PropLock
);
2659 ALCdevice_DecRef(Device
);
2664 * Removes the context reference from the given device and removes it from
2665 * being current on the running thread or globally. Returns true if other
2666 * contexts still exist on the device.
2668 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2670 ALCcontext
*origctx
, *newhead
;
2673 if(LocalContext
.get() == context
)
2675 WARN("%p released while current on thread\n", context
);
2676 LocalContext
.set(nullptr);
2677 ALCcontext_DecRef(context
);
2681 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2682 ALCcontext_DecRef(context
);
2684 V0(device
->Backend
,lock
)();
2686 newhead
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2687 if(!device
->ContextList
.compare_exchange_strong(origctx
, newhead
))
2691 /* origctx is what the desired context failed to match. Try
2692 * swapping out the next one in the list.
2696 } while(!list
->next
.compare_exchange_strong(origctx
, newhead
));
2700 V0(device
->Backend
,unlock
)();
2702 /* Make sure the context is finished and no longer processing in the mixer
2703 * before sending the message queue kill event. The backend's lock does
2704 * this, although waiting for a non-odd mix count would work too.
2707 StopEventThrd(context
);
2709 ALCcontext_DecRef(context
);
2713 static void ALCcontext_IncRef(ALCcontext
*context
)
2715 auto ref
= IncrementRef(&context
->ref
);
2716 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2719 void ALCcontext_DecRef(ALCcontext
*context
)
2721 auto ref
= DecrementRef(&context
->ref
);
2722 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2723 if(ref
== 0) delete context
;
2726 static void ReleaseThreadCtx(ALCcontext
*context
)
2728 auto ref
= DecrementRef(&context
->ref
);
2729 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2730 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2735 * Checks that the given context is valid, and increments its reference count.
2737 static ALCboolean
VerifyContext(ALCcontext
**context
)
2739 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2740 ALCdevice
*dev
{DeviceList
.load()};
2743 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2748 ALCcontext_IncRef(ctx
);
2751 ctx
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
2753 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
2763 * Returns the currently active context for this thread, and adds a reference
2764 * without locking it.
2766 ALCcontext
*GetContextRef(void)
2768 ALCcontext
*context
{LocalContext
.get()};
2770 ALCcontext_IncRef(context
);
2773 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2774 context
= GlobalContext
.load(std::memory_order_acquire
);
2775 if(context
) ALCcontext_IncRef(context
);
2782 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2784 ALCdevice
*device
= context
->Device
;
2785 ALsizei num_sends
= device
->NumAuxSends
;
2786 struct ALvoiceProps
*props
;
2787 size_t sizeof_props
;
2788 size_t sizeof_voice
;
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 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2802 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2803 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2805 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 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2810 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2814 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2815 const ALsizei s_count
= mini(old_sends
, num_sends
);
2817 for(;v
< v_count
;v
++)
2819 ALvoice
*old_voice
= context
->Voices
[v
];
2822 /* Copy the old voice data and source property set to the new
2825 memcpy(voice
, old_voice
, sizeof(*voice
));
2826 for(i
= 0;i
< s_count
;i
++)
2827 voice
->Send
[i
] = old_voice
->Send
[i
];
2829 memcpy(props
, old_voice
->Props
, sizeof(*props
));
2830 for(i
= 0;i
< s_count
;i
++)
2831 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2833 /* Set this voice's property set pointer and voice reference. */
2834 voice
->Props
= props
;
2837 /* Increment pointers to the next storage space. */
2838 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2839 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2841 /* Deinit any left over voices that weren't copied over to the new
2842 * array. NOTE: If this does anything, v equals num_voices and
2843 * num_voices is less than VoiceCount, so the following loop won't do
2846 for(;v
< context
->VoiceCount
;v
++)
2847 DeinitVoice(context
->Voices
[v
]);
2849 /* Finish setting the voices' property set pointers and references. */
2850 for(;v
< num_voices
;v
++)
2852 ATOMIC_INIT(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr));
2854 voice
->Props
= props
;
2857 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2858 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2861 al_free(context
->Voices
);
2862 context
->Voices
= voices
;
2863 context
->MaxVoices
= num_voices
;
2864 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2868 /************************************************
2869 * Standard ALC functions
2870 ************************************************/
2874 * Return last ALC generated error code for the given device
2876 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2880 if(VerifyDevice(&device
))
2882 errorCode
= device
->LastError
.exchange(ALC_NO_ERROR
);
2883 ALCdevice_DecRef(device
);
2886 errorCode
= LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2892 /* alcSuspendContext
2894 * Suspends updates for the given context
2896 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2901 if(!VerifyContext(&context
))
2902 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2905 ALCcontext_DeferUpdates(context
);
2906 ALCcontext_DecRef(context
);
2910 /* alcProcessContext
2912 * Resumes processing updates for the given context
2914 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2919 if(!VerifyContext(&context
))
2920 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
2923 ALCcontext_ProcessUpdates(context
);
2924 ALCcontext_DecRef(context
);
2931 * Returns information about the device, and error strings
2933 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2935 const ALCchar
*value
= nullptr;
2943 case ALC_INVALID_ENUM
:
2944 value
= alcErrInvalidEnum
;
2947 case ALC_INVALID_VALUE
:
2948 value
= alcErrInvalidValue
;
2951 case ALC_INVALID_DEVICE
:
2952 value
= alcErrInvalidDevice
;
2955 case ALC_INVALID_CONTEXT
:
2956 value
= alcErrInvalidContext
;
2959 case ALC_OUT_OF_MEMORY
:
2960 value
= alcErrOutOfMemory
;
2963 case ALC_DEVICE_SPECIFIER
:
2964 value
= alcDefaultName
;
2967 case ALC_ALL_DEVICES_SPECIFIER
:
2968 if(VerifyDevice(&Device
))
2970 value
= Device
->DeviceName
.c_str();
2971 ALCdevice_DecRef(Device
);
2975 ProbeAllDevicesList();
2976 value
= alcAllDevicesList
.c_str();
2980 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2981 if(VerifyDevice(&Device
))
2983 value
= Device
->DeviceName
.c_str();
2984 ALCdevice_DecRef(Device
);
2988 ProbeCaptureDeviceList();
2989 value
= alcCaptureDeviceList
.c_str();
2993 /* Default devices are always first in the list */
2994 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2995 value
= alcDefaultName
;
2998 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2999 if(alcAllDevicesList
.empty())
3000 ProbeAllDevicesList();
3002 /* Copy first entry as default. */
3003 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
3004 value
= alcDefaultAllDevicesSpecifier
.c_str();
3007 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3008 if(alcCaptureDeviceList
.empty())
3009 ProbeCaptureDeviceList();
3011 /* Copy first entry as default. */
3012 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
3013 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
3016 case ALC_EXTENSIONS
:
3017 if(!VerifyDevice(&Device
))
3018 value
= alcNoDeviceExtList
;
3021 value
= alcExtensionList
;
3022 ALCdevice_DecRef(Device
);
3026 case ALC_HRTF_SPECIFIER_SOFT
:
3027 if(!VerifyDevice(&Device
))
3028 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3031 almtx_lock(&Device
->BackendLock
);
3032 value
= (Device
->HrtfHandle
? Device
->HrtfName
.c_str() : "");
3033 almtx_unlock(&Device
->BackendLock
);
3034 ALCdevice_DecRef(Device
);
3039 VerifyDevice(&Device
);
3040 alcSetError(Device
, ALC_INVALID_ENUM
);
3041 if(Device
) ALCdevice_DecRef(Device
);
3049 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3051 if(device
->Type
== Capture
) return 9;
3052 if(device
->Type
!= Loopback
) return 29;
3053 if(device
->FmtChans
== DevFmtAmbi3D
)
3058 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3062 if(size
<= 0 || values
== nullptr)
3064 alcSetError(device
, ALC_INVALID_VALUE
);
3072 case ALC_MAJOR_VERSION
:
3073 values
[0] = alcMajorVersion
;
3075 case ALC_MINOR_VERSION
:
3076 values
[0] = alcMinorVersion
;
3079 case ALC_ATTRIBUTES_SIZE
:
3080 case ALC_ALL_ATTRIBUTES
:
3084 case ALC_MONO_SOURCES
:
3085 case ALC_STEREO_SOURCES
:
3086 case ALC_CAPTURE_SAMPLES
:
3087 case ALC_FORMAT_CHANNELS_SOFT
:
3088 case ALC_FORMAT_TYPE_SOFT
:
3089 case ALC_AMBISONIC_LAYOUT_SOFT
:
3090 case ALC_AMBISONIC_SCALING_SOFT
:
3091 case ALC_AMBISONIC_ORDER_SOFT
:
3092 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3093 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3097 alcSetError(nullptr, ALC_INVALID_ENUM
);
3103 if(device
->Type
== Capture
)
3107 case ALC_ATTRIBUTES_SIZE
:
3108 values
[0] = NumAttrsForDevice(device
);
3111 case ALC_ALL_ATTRIBUTES
:
3112 if(size
< NumAttrsForDevice(device
))
3114 alcSetError(device
, ALC_INVALID_VALUE
);
3119 almtx_lock(&device
->BackendLock
);
3120 values
[i
++] = ALC_MAJOR_VERSION
;
3121 values
[i
++] = alcMajorVersion
;
3122 values
[i
++] = ALC_MINOR_VERSION
;
3123 values
[i
++] = alcMinorVersion
;
3124 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3125 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3126 values
[i
++] = ALC_CONNECTED
;
3127 values
[i
++] = ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
);
3128 almtx_unlock(&device
->BackendLock
);
3133 case ALC_MAJOR_VERSION
:
3134 values
[0] = alcMajorVersion
;
3136 case ALC_MINOR_VERSION
:
3137 values
[0] = alcMinorVersion
;
3140 case ALC_CAPTURE_SAMPLES
:
3141 almtx_lock(&device
->BackendLock
);
3142 values
[0] = V0(device
->Backend
,availableSamples
)();
3143 almtx_unlock(&device
->BackendLock
);
3147 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3151 alcSetError(device
, ALC_INVALID_ENUM
);
3160 case ALC_ATTRIBUTES_SIZE
:
3161 values
[0] = NumAttrsForDevice(device
);
3164 case ALC_ALL_ATTRIBUTES
:
3165 if(size
< NumAttrsForDevice(device
))
3167 alcSetError(device
, ALC_INVALID_VALUE
);
3172 almtx_lock(&device
->BackendLock
);
3173 values
[i
++] = ALC_MAJOR_VERSION
;
3174 values
[i
++] = alcMajorVersion
;
3175 values
[i
++] = ALC_MINOR_VERSION
;
3176 values
[i
++] = alcMinorVersion
;
3177 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3178 values
[i
++] = alcEFXMajorVersion
;
3179 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3180 values
[i
++] = alcEFXMinorVersion
;
3182 values
[i
++] = ALC_FREQUENCY
;
3183 values
[i
++] = device
->Frequency
;
3184 if(device
->Type
!= Loopback
)
3186 values
[i
++] = ALC_REFRESH
;
3187 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3189 values
[i
++] = ALC_SYNC
;
3190 values
[i
++] = ALC_FALSE
;
3194 if(device
->FmtChans
== DevFmtAmbi3D
)
3196 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3197 values
[i
++] = device
->mAmbiLayout
;
3199 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3200 values
[i
++] = device
->mAmbiScale
;
3202 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3203 values
[i
++] = device
->mAmbiOrder
;
3206 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3207 values
[i
++] = device
->FmtChans
;
3209 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3210 values
[i
++] = device
->FmtType
;
3213 values
[i
++] = ALC_MONO_SOURCES
;
3214 values
[i
++] = device
->NumMonoSources
;
3216 values
[i
++] = ALC_STEREO_SOURCES
;
3217 values
[i
++] = device
->NumStereoSources
;
3219 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3220 values
[i
++] = device
->NumAuxSends
;
3222 values
[i
++] = ALC_HRTF_SOFT
;
3223 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3225 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3226 values
[i
++] = device
->HrtfStatus
;
3228 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3229 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3231 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3232 values
[i
++] = MAX_AMBI_ORDER
;
3233 almtx_unlock(&device
->BackendLock
);
3238 case ALC_MAJOR_VERSION
:
3239 values
[0] = alcMajorVersion
;
3242 case ALC_MINOR_VERSION
:
3243 values
[0] = alcMinorVersion
;
3246 case ALC_EFX_MAJOR_VERSION
:
3247 values
[0] = alcEFXMajorVersion
;
3250 case ALC_EFX_MINOR_VERSION
:
3251 values
[0] = alcEFXMinorVersion
;
3255 values
[0] = device
->Frequency
;
3259 if(device
->Type
== Loopback
)
3261 alcSetError(device
, ALC_INVALID_DEVICE
);
3264 almtx_lock(&device
->BackendLock
);
3265 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3266 almtx_unlock(&device
->BackendLock
);
3270 if(device
->Type
== Loopback
)
3272 alcSetError(device
, ALC_INVALID_DEVICE
);
3275 values
[0] = ALC_FALSE
;
3278 case ALC_FORMAT_CHANNELS_SOFT
:
3279 if(device
->Type
!= Loopback
)
3281 alcSetError(device
, ALC_INVALID_DEVICE
);
3284 values
[0] = device
->FmtChans
;
3287 case ALC_FORMAT_TYPE_SOFT
:
3288 if(device
->Type
!= Loopback
)
3290 alcSetError(device
, ALC_INVALID_DEVICE
);
3293 values
[0] = device
->FmtType
;
3296 case ALC_AMBISONIC_LAYOUT_SOFT
:
3297 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3299 alcSetError(device
, ALC_INVALID_DEVICE
);
3302 values
[0] = device
->mAmbiLayout
;
3305 case ALC_AMBISONIC_SCALING_SOFT
:
3306 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3308 alcSetError(device
, ALC_INVALID_DEVICE
);
3311 values
[0] = device
->mAmbiScale
;
3314 case ALC_AMBISONIC_ORDER_SOFT
:
3315 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3317 alcSetError(device
, ALC_INVALID_DEVICE
);
3320 values
[0] = device
->mAmbiOrder
;
3323 case ALC_MONO_SOURCES
:
3324 values
[0] = device
->NumMonoSources
;
3327 case ALC_STEREO_SOURCES
:
3328 values
[0] = device
->NumStereoSources
;
3331 case ALC_MAX_AUXILIARY_SENDS
:
3332 values
[0] = device
->NumAuxSends
;
3336 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3340 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3343 case ALC_HRTF_STATUS_SOFT
:
3344 values
[0] = device
->HrtfStatus
;
3347 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3348 almtx_lock(&device
->BackendLock
);
3349 device
->HrtfList
.clear();
3350 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
.c_str());
3351 values
[0] = (ALCint
)device
->HrtfList
.size();
3352 almtx_unlock(&device
->BackendLock
);
3355 case ALC_OUTPUT_LIMITER_SOFT
:
3356 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3359 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3360 values
[0] = MAX_AMBI_ORDER
;
3364 alcSetError(device
, ALC_INVALID_ENUM
);
3372 * Returns information about the device and the version of OpenAL
3374 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3376 VerifyDevice(&device
);
3377 if(size
<= 0 || values
== nullptr)
3378 alcSetError(device
, ALC_INVALID_VALUE
);
3380 GetIntegerv(device
, param
, size
, values
);
3381 if(device
) ALCdevice_DecRef(device
);
3384 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3388 VerifyDevice(&device
);
3389 if(size
<= 0 || values
== nullptr)
3390 alcSetError(device
, ALC_INVALID_VALUE
);
3391 else if(!device
|| device
->Type
== Capture
)
3393 std::vector
<ALCint
> ivals(size
);
3394 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3395 for(i
= 0;i
< size
;i
++)
3396 values
[i
] = ivals
[i
];
3398 else /* render device */
3407 case ALC_ATTRIBUTES_SIZE
:
3408 *values
= NumAttrsForDevice(device
)+4;
3411 case ALC_ALL_ATTRIBUTES
:
3412 if(size
< NumAttrsForDevice(device
)+4)
3413 alcSetError(device
, ALC_INVALID_VALUE
);
3417 almtx_lock(&device
->BackendLock
);
3418 values
[i
++] = ALC_FREQUENCY
;
3419 values
[i
++] = device
->Frequency
;
3421 if(device
->Type
!= Loopback
)
3423 values
[i
++] = ALC_REFRESH
;
3424 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3426 values
[i
++] = ALC_SYNC
;
3427 values
[i
++] = ALC_FALSE
;
3431 if(device
->FmtChans
== DevFmtAmbi3D
)
3433 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3434 values
[i
++] = device
->mAmbiLayout
;
3436 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3437 values
[i
++] = device
->mAmbiScale
;
3439 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3440 values
[i
++] = device
->mAmbiOrder
;
3443 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3444 values
[i
++] = device
->FmtChans
;
3446 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3447 values
[i
++] = device
->FmtType
;
3450 values
[i
++] = ALC_MONO_SOURCES
;
3451 values
[i
++] = device
->NumMonoSources
;
3453 values
[i
++] = ALC_STEREO_SOURCES
;
3454 values
[i
++] = device
->NumStereoSources
;
3456 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3457 values
[i
++] = device
->NumAuxSends
;
3459 values
[i
++] = ALC_HRTF_SOFT
;
3460 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3462 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3463 values
[i
++] = device
->HrtfStatus
;
3465 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3466 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3468 clock
= GetClockLatency(device
);
3469 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3470 values
[i
++] = clock
.ClockTime
;
3472 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3473 values
[i
++] = clock
.Latency
;
3474 almtx_unlock(&device
->BackendLock
);
3480 case ALC_DEVICE_CLOCK_SOFT
:
3481 almtx_lock(&device
->BackendLock
);
3483 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3485 basecount
= device
->ClockBase
;
3486 samplecount
= device
->SamplesDone
;
3487 } while(refcount
!= ReadRef(&device
->MixCount
));
3488 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3489 almtx_unlock(&device
->BackendLock
);
3492 case ALC_DEVICE_LATENCY_SOFT
:
3493 almtx_lock(&device
->BackendLock
);
3494 clock
= GetClockLatency(device
);
3495 almtx_unlock(&device
->BackendLock
);
3496 *values
= clock
.Latency
;
3499 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3501 alcSetError(device
, ALC_INVALID_VALUE
);
3504 almtx_lock(&device
->BackendLock
);
3505 clock
= GetClockLatency(device
);
3506 almtx_unlock(&device
->BackendLock
);
3507 values
[0] = clock
.ClockTime
;
3508 values
[1] = clock
.Latency
;
3513 std::vector
<ALCint
> ivals(size
);
3514 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3515 for(i
= 0;i
< size
;i
++)
3516 values
[i
] = ivals
[i
];
3521 ALCdevice_DecRef(device
);
3525 /* alcIsExtensionPresent
3527 * Determines if there is support for a particular extension
3529 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3531 ALCboolean bResult
= ALC_FALSE
;
3533 VerifyDevice(&device
);
3536 alcSetError(device
, ALC_INVALID_VALUE
);
3539 size_t len
= strlen(extName
);
3540 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3543 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3544 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3549 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3553 } while(isspace(*ptr
));
3558 ALCdevice_DecRef(device
);
3563 /* alcGetProcAddress
3565 * Retrieves the function address for a particular extension function
3567 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3569 ALCvoid
*ptr
= nullptr;
3573 VerifyDevice(&device
);
3574 alcSetError(device
, ALC_INVALID_VALUE
);
3575 if(device
) ALCdevice_DecRef(device
);
3580 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3582 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3584 ptr
= alcFunctions
[i
].address
;
3596 * Get the value for a particular ALC enumeration name
3598 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3604 VerifyDevice(&device
);
3605 alcSetError(device
, ALC_INVALID_VALUE
);
3606 if(device
) ALCdevice_DecRef(device
);
3611 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3613 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3615 val
= alcEnumerations
[i
].value
;
3627 * Create and attach a context to the given device.
3629 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3631 ALCcontext
*ALContext
;
3635 /* Explicitly hold the list lock while taking the BackendLock in case the
3636 * device is asynchronously destropyed, to ensure this new context is
3637 * properly cleaned up after being made.
3639 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3640 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3641 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
3644 alcSetError(device
, ALC_INVALID_DEVICE
);
3645 if(device
) ALCdevice_DecRef(device
);
3648 almtx_lock(&device
->BackendLock
);
3651 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3653 ALContext
= new ALCcontext
{device
};
3654 ALCdevice_IncRef(ALContext
->Device
);
3656 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3658 almtx_unlock(&device
->BackendLock
);
3661 ALContext
= nullptr;
3663 alcSetError(device
, err
);
3664 if(err
== ALC_INVALID_DEVICE
)
3666 V0(device
->Backend
,lock
)();
3667 aluHandleDisconnect(device
, "Device update failure");
3668 V0(device
->Backend
,unlock
)();
3670 ALCdevice_DecRef(device
);
3673 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3675 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3677 ALContext
->DefaultSlot
.reset(new ALeffectslot
{});
3678 if(InitEffectSlot(ALContext
->DefaultSlot
.get()) == AL_NO_ERROR
)
3679 aluInitEffectPanning(ALContext
->DefaultSlot
.get());
3682 ALContext
->DefaultSlot
= nullptr;
3683 ERR("Failed to initialize the default effect slot\n");
3687 InitContext(ALContext
);
3689 if(ConfigValueFloat(device
->DeviceName
.c_str(), nullptr, "volume-adjust", &valf
))
3691 if(!std::isfinite(valf
))
3692 ERR("volume-adjust must be finite: %f\n", valf
);
3695 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3697 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3698 ALContext
->GainBoost
= std::pow(10.0f
, db
/20.0f
);
3699 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3702 UpdateListenerProps(ALContext
);
3705 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3707 ATOMIC_STORE(&ALContext
->next
, head
, almemory_order_relaxed
);
3708 } while(!device
->ContextList
.compare_exchange_weak(head
, ALContext
));
3710 almtx_unlock(&device
->BackendLock
);
3712 if(ALContext
->DefaultSlot
)
3714 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
.get(), &DefaultEffect
) == AL_NO_ERROR
)
3715 UpdateEffectSlotProps(ALContext
->DefaultSlot
.get(), ALContext
);
3717 ERR("Failed to initialize the default effect\n");
3720 ALCdevice_DecRef(device
);
3722 TRACE("Created context %p\n", ALContext
);
3726 /* alcDestroyContext
3728 * Remove a context from its device
3730 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3732 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3733 if(!VerifyContext(&context
))
3736 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3740 ALCdevice
* Device
{context
->Device
};
3743 almtx_lock(&Device
->BackendLock
);
3744 if(!ReleaseContext(context
, Device
))
3746 V0(Device
->Backend
,stop
)();
3747 Device
->Flags
&= ~DEVICE_RUNNING
;
3749 almtx_unlock(&Device
->BackendLock
);
3753 ALCcontext_DecRef(context
);
3757 /* alcGetCurrentContext
3759 * Returns the currently active context on the calling thread
3761 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3763 ALCcontext
*Context
{LocalContext
.get()};
3764 if(!Context
) Context
= GlobalContext
.load();
3768 /* alcGetThreadContext
3770 * Returns the currently active thread-local context
3772 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3774 return LocalContext
.get();
3778 /* alcMakeContextCurrent
3780 * Makes the given context the active process-wide context, and removes the
3781 * thread-local context for the calling thread.
3783 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3785 /* context must be valid or nullptr */
3786 if(context
&& !VerifyContext(&context
))
3788 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3791 /* context's reference count is already incremented */
3792 context
= GlobalContext
.exchange(context
);
3793 if(context
) ALCcontext_DecRef(context
);
3795 if((context
=LocalContext
.get()) != nullptr)
3797 LocalContext
.set(nullptr);
3798 ALCcontext_DecRef(context
);
3804 /* alcSetThreadContext
3806 * Makes the given context the active context for the current thread
3808 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3810 /* context must be valid or nullptr */
3811 if(context
&& !VerifyContext(&context
))
3813 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3816 /* context's reference count is already incremented */
3817 ALCcontext
*old
{LocalContext
.get()};
3818 LocalContext
.set(context
);
3819 if(old
) ALCcontext_DecRef(old
);
3825 /* alcGetContextsDevice
3827 * Returns the device that a particular context is attached to
3829 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3831 if(!VerifyContext(&Context
))
3833 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3836 ALCdevice
*Device
{Context
->Device
};
3837 ALCcontext_DecRef(Context
);
3845 * Opens the named device.
3847 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3851 if(!PlaybackBackend
.name
)
3853 alcSetError(nullptr, ALC_INVALID_VALUE
);
3857 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3859 /* Some old Windows apps hardcode these expecting OpenAL to use a
3860 * specific audio API, even when they're not enumerated. Creative's
3861 * router effectively ignores them too.
3863 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3864 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3867 deviceName
= nullptr;
3869 auto device
= new ALCdevice
{Playback
};
3872 device
->FmtChans
= DevFmtChannelsDefault
;
3873 device
->FmtType
= DevFmtTypeDefault
;
3874 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3875 device
->IsHeadphones
= AL_FALSE
;
3876 device
->mAmbiLayout
= AmbiLayout_Default
;
3877 device
->mAmbiScale
= AmbiNorm_Default
;
3878 device
->LimiterState
= ALC_TRUE
;
3879 device
->NumUpdates
= 3;
3880 device
->UpdateSize
= 1024;
3882 device
->SourcesMax
= 256;
3883 device
->AuxiliaryEffectSlotMax
= 64;
3884 device
->NumAuxSends
= DEFAULT_SENDS
;
3886 const ALCchar
*fmt
{};
3887 if(ConfigValueStr(deviceName
, nullptr, "channels", &fmt
))
3889 static constexpr struct ChannelMap
{
3890 const char name
[16];
3891 enum DevFmtChannels chans
;
3894 { "mono", DevFmtMono
, 0 },
3895 { "stereo", DevFmtStereo
, 0 },
3896 { "quad", DevFmtQuad
, 0 },
3897 { "surround51", DevFmtX51
, 0 },
3898 { "surround61", DevFmtX61
, 0 },
3899 { "surround71", DevFmtX71
, 0 },
3900 { "surround51rear", DevFmtX51Rear
, 0 },
3901 { "ambi1", DevFmtAmbi3D
, 1 },
3902 { "ambi2", DevFmtAmbi3D
, 2 },
3903 { "ambi3", DevFmtAmbi3D
, 3 },
3906 auto iter
= std::find_if(std::begin(chanlist
), std::end(chanlist
),
3907 [fmt
](const ChannelMap
&entry
) -> bool
3908 { return strcasecmp(entry
.name
, fmt
) == 0; }
3910 if(iter
== std::end(chanlist
))
3911 ERR("Unsupported channels: %s\n", fmt
);
3914 device
->FmtChans
= iter
->chans
;
3915 device
->mAmbiOrder
= iter
->order
;
3916 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3919 if(ConfigValueStr(deviceName
, nullptr, "sample-type", &fmt
))
3921 static constexpr struct TypeMap
{
3922 const char name
[16];
3923 enum DevFmtType type
;
3925 { "int8", DevFmtByte
},
3926 { "uint8", DevFmtUByte
},
3927 { "int16", DevFmtShort
},
3928 { "uint16", DevFmtUShort
},
3929 { "int32", DevFmtInt
},
3930 { "uint32", DevFmtUInt
},
3931 { "float32", DevFmtFloat
},
3934 auto iter
= std::find_if(std::begin(typelist
), std::end(typelist
),
3935 [fmt
](const TypeMap
&entry
) -> bool
3936 { return strcasecmp(entry
.name
, fmt
) == 0; }
3938 if(iter
== std::end(typelist
))
3939 ERR("Unsupported sample-type: %s\n", fmt
);
3942 device
->FmtType
= iter
->type
;
3943 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3947 if(ConfigValueUInt(deviceName
, nullptr, "frequency", &device
->Frequency
))
3949 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3950 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3951 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3952 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3955 ConfigValueUInt(deviceName
, nullptr, "periods", &device
->NumUpdates
);
3956 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3958 ConfigValueUInt(deviceName
, nullptr, "period_size", &device
->UpdateSize
);
3959 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3960 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3961 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3963 ConfigValueUInt(deviceName
, nullptr, "sources", &device
->SourcesMax
);
3964 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3966 ConfigValueUInt(deviceName
, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
3967 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3968 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
3970 if(ConfigValueInt(deviceName
, nullptr, "sends", &device
->NumAuxSends
))
3971 device
->NumAuxSends
= clampi(
3972 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3975 device
->NumStereoSources
= 1;
3976 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3978 device
->Backend
= PlaybackBackend
.getFactory().createBackend(device
, ALCbackend_Playback
);
3979 if(!device
->Backend
)
3982 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
3986 // Find a playback device to open
3987 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
3988 if(err
!= ALC_NO_ERROR
)
3991 alcSetError(nullptr, err
);
3995 if(ConfigValueStr(device
->DeviceName
.c_str(), nullptr, "ambi-format", &fmt
))
3997 if(strcasecmp(fmt
, "fuma") == 0)
3999 device
->mAmbiLayout
= AmbiLayout_FuMa
;
4000 device
->mAmbiScale
= AmbiNorm_FuMa
;
4002 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4004 device
->mAmbiLayout
= AmbiLayout_ACN
;
4005 device
->mAmbiScale
= AmbiNorm_SN3D
;
4007 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4009 device
->mAmbiLayout
= AmbiLayout_ACN
;
4010 device
->mAmbiScale
= AmbiNorm_N3D
;
4013 ERR("Unsupported ambi-format: %s\n", fmt
);
4017 ALCdevice
*head
{DeviceList
.load()};
4019 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4020 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4023 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
4029 * Closes the given device.
4031 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4033 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4034 ALCdevice
*iter
{DeviceList
.load()};
4038 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4039 } while(iter
!= nullptr);
4040 if(!iter
|| iter
->Type
== Capture
)
4042 alcSetError(iter
, ALC_INVALID_DEVICE
);
4045 almtx_lock(&device
->BackendLock
);
4047 ALCdevice
*origdev
{device
};
4048 ALCdevice
*nextdev
{ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
)};
4049 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4055 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4059 ALCcontext
*ctx
{ATOMIC_LOAD_SEQ(&device
->ContextList
)};
4060 while(ctx
!= nullptr)
4062 ALCcontext
*next
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
4063 WARN("Releasing context %p\n", ctx
);
4064 ReleaseContext(ctx
, device
);
4067 if((device
->Flags
&DEVICE_RUNNING
))
4068 V0(device
->Backend
,stop
)();
4069 device
->Flags
&= ~DEVICE_RUNNING
;
4070 almtx_unlock(&device
->BackendLock
);
4072 ALCdevice_DecRef(device
);
4078 /************************************************
4079 * ALC capture functions
4080 ************************************************/
4081 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4085 if(!CaptureBackend
.name
)
4087 alcSetError(nullptr, ALC_INVALID_VALUE
);
4093 alcSetError(nullptr, ALC_INVALID_VALUE
);
4097 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4098 deviceName
= nullptr;
4100 auto device
= new ALCdevice
{Capture
};
4102 device
->Frequency
= frequency
;
4103 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4105 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4108 alcSetError(nullptr, ALC_INVALID_ENUM
);
4111 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4112 device
->IsHeadphones
= AL_FALSE
;
4113 device
->mAmbiOrder
= 0;
4114 device
->mAmbiLayout
= AmbiLayout_Default
;
4115 device
->mAmbiScale
= AmbiNorm_Default
;
4117 device
->UpdateSize
= samples
;
4118 device
->NumUpdates
= 1;
4120 device
->Backend
= CaptureBackend
.getFactory().createBackend(device
, ALCbackend_Capture
);
4121 if(!device
->Backend
)
4124 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4128 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4129 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4130 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4132 ALCenum err
{V(device
->Backend
,open
)(deviceName
)};
4133 if(err
!= ALC_NO_ERROR
)
4136 alcSetError(nullptr, err
);
4141 ALCdevice
*head
{DeviceList
.load()};
4143 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4144 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4147 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
.c_str());
4151 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4153 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4155 ALCdevice
*iter
{DeviceList
.load()};
4159 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4160 } while(iter
!= nullptr);
4161 if(!iter
|| iter
->Type
!= Capture
)
4163 alcSetError(iter
, ALC_INVALID_DEVICE
);
4167 ALCdevice
*origdev
{device
};
4168 ALCdevice
*nextdev
{ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
)};
4169 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4175 } while(!list
->next
.compare_exchange_strong(origdev
, nextdev
));
4179 almtx_lock(&device
->BackendLock
);
4180 if((device
->Flags
&DEVICE_RUNNING
))
4181 V0(device
->Backend
,stop
)();
4182 device
->Flags
&= ~DEVICE_RUNNING
;
4183 almtx_unlock(&device
->BackendLock
);
4185 ALCdevice_DecRef(device
);
4190 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4192 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4193 alcSetError(device
, ALC_INVALID_DEVICE
);
4196 almtx_lock(&device
->BackendLock
);
4197 if(!ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
))
4198 alcSetError(device
, ALC_INVALID_DEVICE
);
4199 else if(!(device
->Flags
&DEVICE_RUNNING
))
4201 if(V0(device
->Backend
,start
)())
4202 device
->Flags
|= DEVICE_RUNNING
;
4205 aluHandleDisconnect(device
, "Device start failure");
4206 alcSetError(device
, ALC_INVALID_DEVICE
);
4209 almtx_unlock(&device
->BackendLock
);
4212 if(device
) ALCdevice_DecRef(device
);
4215 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4217 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4218 alcSetError(device
, ALC_INVALID_DEVICE
);
4221 almtx_lock(&device
->BackendLock
);
4222 if((device
->Flags
&DEVICE_RUNNING
))
4223 V0(device
->Backend
,stop
)();
4224 device
->Flags
&= ~DEVICE_RUNNING
;
4225 almtx_unlock(&device
->BackendLock
);
4228 if(device
) ALCdevice_DecRef(device
);
4231 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4233 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4234 alcSetError(device
, ALC_INVALID_DEVICE
);
4237 ALCenum err
= ALC_INVALID_VALUE
;
4239 almtx_lock(&device
->BackendLock
);
4240 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4241 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4242 almtx_unlock(&device
->BackendLock
);
4244 if(err
!= ALC_NO_ERROR
)
4245 alcSetError(device
, err
);
4247 if(device
) ALCdevice_DecRef(device
);
4251 /************************************************
4252 * ALC loopback functions
4253 ************************************************/
4255 /* alcLoopbackOpenDeviceSOFT
4257 * Open a loopback device, for manual rendering.
4259 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4263 /* Make sure the device name, if specified, is us. */
4264 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4266 alcSetError(nullptr, ALC_INVALID_VALUE
);
4270 auto device
= new ALCdevice
{Loopback
};
4272 device
->SourcesMax
= 256;
4273 device
->AuxiliaryEffectSlotMax
= 64;
4274 device
->NumAuxSends
= DEFAULT_SENDS
;
4277 device
->NumUpdates
= 0;
4278 device
->UpdateSize
= 0;
4280 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4281 device
->FmtChans
= DevFmtChannelsDefault
;
4282 device
->FmtType
= DevFmtTypeDefault
;
4283 device
->IsHeadphones
= AL_FALSE
;
4284 device
->mAmbiLayout
= AmbiLayout_Default
;
4285 device
->mAmbiScale
= AmbiNorm_Default
;
4287 ConfigValueUInt(nullptr, nullptr, "sources", &device
->SourcesMax
);
4288 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4290 ConfigValueUInt(nullptr, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4291 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4292 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4294 if(ConfigValueInt(nullptr, nullptr, "sends", &device
->NumAuxSends
))
4295 device
->NumAuxSends
= clampi(
4296 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4299 device
->NumStereoSources
= 1;
4300 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4302 device
->Backend
= LoopbackBackendFactory::getFactory().createBackend(
4303 device
, ALCbackend_Loopback
);
4304 if(!device
->Backend
)
4307 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4311 // Open the "backend"
4312 V(device
->Backend
,open
)("Loopback");
4315 ALCdevice
*head
{DeviceList
.load()};
4317 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4318 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4321 TRACE("Created device %p\n", device
);
4325 /* alcIsRenderFormatSupportedSOFT
4327 * Determines if the loopback device supports the given format for rendering.
4329 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4331 ALCboolean ret
{ALC_FALSE
};
4333 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4334 alcSetError(device
, ALC_INVALID_DEVICE
);
4336 alcSetError(device
, ALC_INVALID_VALUE
);
4339 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4342 if(device
) ALCdevice_DecRef(device
);
4347 /* alcRenderSamplesSOFT
4349 * Renders some samples into a buffer, using the format last set by the
4350 * attributes given to alcCreateContext.
4352 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4354 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4355 alcSetError(device
, ALC_INVALID_DEVICE
);
4356 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4357 alcSetError(device
, ALC_INVALID_VALUE
);
4360 V0(device
->Backend
,lock
)();
4361 aluMixData(device
, buffer
, samples
);
4362 V0(device
->Backend
,unlock
)();
4364 if(device
) ALCdevice_DecRef(device
);
4368 /************************************************
4369 * ALC DSP pause/resume functions
4370 ************************************************/
4372 /* alcDevicePauseSOFT
4374 * Pause the DSP to stop audio processing.
4376 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4378 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4379 alcSetError(device
, ALC_INVALID_DEVICE
);
4382 almtx_lock(&device
->BackendLock
);
4383 if((device
->Flags
&DEVICE_RUNNING
))
4384 V0(device
->Backend
,stop
)();
4385 device
->Flags
&= ~DEVICE_RUNNING
;
4386 device
->Flags
|= DEVICE_PAUSED
;
4387 almtx_unlock(&device
->BackendLock
);
4389 if(device
) ALCdevice_DecRef(device
);
4392 /* alcDeviceResumeSOFT
4394 * Resume the DSP to restart audio processing.
4396 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4398 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4399 alcSetError(device
, ALC_INVALID_DEVICE
);
4402 almtx_lock(&device
->BackendLock
);
4403 if((device
->Flags
&DEVICE_PAUSED
))
4405 device
->Flags
&= ~DEVICE_PAUSED
;
4406 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != nullptr)
4408 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4409 device
->Flags
|= DEVICE_RUNNING
;
4412 V0(device
->Backend
,lock
)();
4413 aluHandleDisconnect(device
, "Device start failure");
4414 V0(device
->Backend
,unlock
)();
4415 alcSetError(device
, ALC_INVALID_DEVICE
);
4419 almtx_unlock(&device
->BackendLock
);
4421 if(device
) ALCdevice_DecRef(device
);
4425 /************************************************
4426 * ALC HRTF functions
4427 ************************************************/
4429 /* alcGetStringiSOFT
4431 * Gets a string parameter at the given index.
4433 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4435 const ALCchar
*str
{nullptr};
4437 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4438 alcSetError(device
, ALC_INVALID_DEVICE
);
4439 else switch(paramName
)
4441 case ALC_HRTF_SPECIFIER_SOFT
:
4442 if(index
>= 0 && (size_t)index
< device
->HrtfList
.size())
4443 str
= device
->HrtfList
[index
].name
.c_str();
4445 alcSetError(device
, ALC_INVALID_VALUE
);
4449 alcSetError(device
, ALC_INVALID_ENUM
);
4452 if(device
) ALCdevice_DecRef(device
);
4457 /* alcResetDeviceSOFT
4459 * Resets the given device output, using the specified attribute list.
4461 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4463 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4464 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4465 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
4468 alcSetError(device
, ALC_INVALID_DEVICE
);
4469 if(device
) ALCdevice_DecRef(device
);
4472 almtx_lock(&device
->BackendLock
);
4475 ALCenum err
{UpdateDeviceParams(device
, attribs
)};
4476 almtx_unlock(&device
->BackendLock
);
4478 if(err
!= ALC_NO_ERROR
)
4480 alcSetError(device
, err
);
4481 if(err
== ALC_INVALID_DEVICE
)
4483 V0(device
->Backend
,lock
)();
4484 aluHandleDisconnect(device
, "Device start failure");
4485 V0(device
->Backend
,unlock
)();
4487 ALCdevice_DecRef(device
);
4490 ALCdevice_DecRef(device
);