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 "alListener.h"
45 #include "alAuxEffectSlot.h"
47 #include "mastering.h"
48 #include "bformatdec.h"
51 #include "ringbuffer.h"
53 #include "fpu_modes.h"
59 #include "backends/base.h"
60 #include "backends/null.h"
65 /************************************************
67 ************************************************/
70 BackendFactory
& (*getFactory
)(void);
73 struct BackendInfo BackendList
[] = {
76 { "jack", ALCjackBackendFactory_getFactory
},
78 #ifdef HAVE_PULSEAUDIO
79 { "pulse", ALCpulseBackendFactory_getFactory
},
82 { "alsa", ALCalsaBackendFactory_getFactory
},
85 { "core", ALCcoreAudioBackendFactory_getFactory
},
88 { "solaris", ALCsolarisBackendFactory_getFactory
},
91 { "sndio", SndioBackendFactory_getFactory
},
94 { "oss", ALCossBackendFactory_getFactory
},
97 { "qsa", ALCqsaBackendFactory_getFactory
},
100 { "wasapi", ALCwasapiBackendFactory_getFactory
},
103 { "dsound", ALCdsoundBackendFactory_getFactory
},
106 { "winmm", ALCwinmmBackendFactory_getFactory
},
108 #ifdef HAVE_PORTAUDIO
109 { "port", ALCportBackendFactory_getFactory
},
112 { "opensl", ALCopenslBackendFactory_getFactory
},
115 { "sdl2", ALCsdl2BackendFactory_getFactory
},
118 { "null", ALCnullBackendFactory_getFactory
},
120 { "wave", ALCwaveBackendFactory_getFactory
},
123 { "null", NullBackendFactory::getFactory
},
125 ALsizei BackendListSize
= COUNTOF(BackendList
);
128 struct BackendInfo PlaybackBackend
;
129 struct BackendInfo CaptureBackend
;
132 /************************************************
133 * Functions, enums, and errors
134 ************************************************/
135 #define DECL(x) { #x, (ALCvoid*)(x) }
137 const ALCchar
*funcName
;
140 DECL(alcCreateContext
),
141 DECL(alcMakeContextCurrent
),
142 DECL(alcProcessContext
),
143 DECL(alcSuspendContext
),
144 DECL(alcDestroyContext
),
145 DECL(alcGetCurrentContext
),
146 DECL(alcGetContextsDevice
),
148 DECL(alcCloseDevice
),
150 DECL(alcIsExtensionPresent
),
151 DECL(alcGetProcAddress
),
152 DECL(alcGetEnumValue
),
154 DECL(alcGetIntegerv
),
155 DECL(alcCaptureOpenDevice
),
156 DECL(alcCaptureCloseDevice
),
157 DECL(alcCaptureStart
),
158 DECL(alcCaptureStop
),
159 DECL(alcCaptureSamples
),
161 DECL(alcSetThreadContext
),
162 DECL(alcGetThreadContext
),
164 DECL(alcLoopbackOpenDeviceSOFT
),
165 DECL(alcIsRenderFormatSupportedSOFT
),
166 DECL(alcRenderSamplesSOFT
),
168 DECL(alcDevicePauseSOFT
),
169 DECL(alcDeviceResumeSOFT
),
171 DECL(alcGetStringiSOFT
),
172 DECL(alcResetDeviceSOFT
),
174 DECL(alcGetInteger64vSOFT
),
189 DECL(alIsExtensionPresent
),
190 DECL(alGetProcAddress
),
191 DECL(alGetEnumValue
),
198 DECL(alGetListenerf
),
199 DECL(alGetListener3f
),
200 DECL(alGetListenerfv
),
201 DECL(alGetListeneri
),
202 DECL(alGetListener3i
),
203 DECL(alGetListeneriv
),
205 DECL(alDeleteSources
),
221 DECL(alSourceRewindv
),
222 DECL(alSourcePausev
),
225 DECL(alSourceRewind
),
227 DECL(alSourceQueueBuffers
),
228 DECL(alSourceUnqueueBuffers
),
230 DECL(alDeleteBuffers
),
245 DECL(alDopplerFactor
),
246 DECL(alDopplerVelocity
),
247 DECL(alSpeedOfSound
),
248 DECL(alDistanceModel
),
251 DECL(alDeleteFilters
),
262 DECL(alDeleteEffects
),
272 DECL(alGenAuxiliaryEffectSlots
),
273 DECL(alDeleteAuxiliaryEffectSlots
),
274 DECL(alIsAuxiliaryEffectSlot
),
275 DECL(alAuxiliaryEffectSloti
),
276 DECL(alAuxiliaryEffectSlotiv
),
277 DECL(alAuxiliaryEffectSlotf
),
278 DECL(alAuxiliaryEffectSlotfv
),
279 DECL(alGetAuxiliaryEffectSloti
),
280 DECL(alGetAuxiliaryEffectSlotiv
),
281 DECL(alGetAuxiliaryEffectSlotf
),
282 DECL(alGetAuxiliaryEffectSlotfv
),
284 DECL(alDeferUpdatesSOFT
),
285 DECL(alProcessUpdatesSOFT
),
288 DECL(alSource3dSOFT
),
289 DECL(alSourcedvSOFT
),
290 DECL(alGetSourcedSOFT
),
291 DECL(alGetSource3dSOFT
),
292 DECL(alGetSourcedvSOFT
),
293 DECL(alSourcei64SOFT
),
294 DECL(alSource3i64SOFT
),
295 DECL(alSourcei64vSOFT
),
296 DECL(alGetSourcei64SOFT
),
297 DECL(alGetSource3i64SOFT
),
298 DECL(alGetSourcei64vSOFT
),
300 DECL(alGetStringiSOFT
),
302 DECL(alBufferStorageSOFT
),
303 DECL(alMapBufferSOFT
),
304 DECL(alUnmapBufferSOFT
),
305 DECL(alFlushMappedBufferSOFT
),
307 DECL(alEventControlSOFT
),
308 DECL(alEventCallbackSOFT
),
309 DECL(alGetPointerSOFT
),
310 DECL(alGetPointervSOFT
),
314 #define DECL(x) { #x, (x) }
316 const ALCchar
*enumName
;
318 } alcEnumerations
[] = {
323 DECL(ALC_MAJOR_VERSION
),
324 DECL(ALC_MINOR_VERSION
),
325 DECL(ALC_ATTRIBUTES_SIZE
),
326 DECL(ALC_ALL_ATTRIBUTES
),
327 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
328 DECL(ALC_DEVICE_SPECIFIER
),
329 DECL(ALC_ALL_DEVICES_SPECIFIER
),
330 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
331 DECL(ALC_EXTENSIONS
),
335 DECL(ALC_MONO_SOURCES
),
336 DECL(ALC_STEREO_SOURCES
),
337 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
338 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
339 DECL(ALC_CAPTURE_SAMPLES
),
342 DECL(ALC_EFX_MAJOR_VERSION
),
343 DECL(ALC_EFX_MINOR_VERSION
),
344 DECL(ALC_MAX_AUXILIARY_SENDS
),
346 DECL(ALC_FORMAT_CHANNELS_SOFT
),
347 DECL(ALC_FORMAT_TYPE_SOFT
),
350 DECL(ALC_STEREO_SOFT
),
352 DECL(ALC_5POINT1_SOFT
),
353 DECL(ALC_6POINT1_SOFT
),
354 DECL(ALC_7POINT1_SOFT
),
355 DECL(ALC_BFORMAT3D_SOFT
),
358 DECL(ALC_UNSIGNED_BYTE_SOFT
),
359 DECL(ALC_SHORT_SOFT
),
360 DECL(ALC_UNSIGNED_SHORT_SOFT
),
362 DECL(ALC_UNSIGNED_INT_SOFT
),
363 DECL(ALC_FLOAT_SOFT
),
366 DECL(ALC_DONT_CARE_SOFT
),
367 DECL(ALC_HRTF_STATUS_SOFT
),
368 DECL(ALC_HRTF_DISABLED_SOFT
),
369 DECL(ALC_HRTF_ENABLED_SOFT
),
370 DECL(ALC_HRTF_DENIED_SOFT
),
371 DECL(ALC_HRTF_REQUIRED_SOFT
),
372 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
373 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
374 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
375 DECL(ALC_HRTF_SPECIFIER_SOFT
),
376 DECL(ALC_HRTF_ID_SOFT
),
378 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
379 DECL(ALC_AMBISONIC_SCALING_SOFT
),
380 DECL(ALC_AMBISONIC_ORDER_SOFT
),
386 DECL(ALC_OUTPUT_LIMITER_SOFT
),
389 DECL(ALC_INVALID_DEVICE
),
390 DECL(ALC_INVALID_CONTEXT
),
391 DECL(ALC_INVALID_ENUM
),
392 DECL(ALC_INVALID_VALUE
),
393 DECL(ALC_OUT_OF_MEMORY
),
401 DECL(AL_SOURCE_RELATIVE
),
402 DECL(AL_CONE_INNER_ANGLE
),
403 DECL(AL_CONE_OUTER_ANGLE
),
413 DECL(AL_ORIENTATION
),
414 DECL(AL_REFERENCE_DISTANCE
),
415 DECL(AL_ROLLOFF_FACTOR
),
416 DECL(AL_CONE_OUTER_GAIN
),
417 DECL(AL_MAX_DISTANCE
),
419 DECL(AL_SAMPLE_OFFSET
),
420 DECL(AL_BYTE_OFFSET
),
421 DECL(AL_SOURCE_TYPE
),
424 DECL(AL_UNDETERMINED
),
425 DECL(AL_METERS_PER_UNIT
),
426 DECL(AL_LOOP_POINTS_SOFT
),
427 DECL(AL_DIRECT_CHANNELS_SOFT
),
429 DECL(AL_DIRECT_FILTER
),
430 DECL(AL_AUXILIARY_SEND_FILTER
),
431 DECL(AL_AIR_ABSORPTION_FACTOR
),
432 DECL(AL_ROOM_ROLLOFF_FACTOR
),
433 DECL(AL_CONE_OUTER_GAINHF
),
434 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
435 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
436 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
438 DECL(AL_SOURCE_STATE
),
444 DECL(AL_BUFFERS_QUEUED
),
445 DECL(AL_BUFFERS_PROCESSED
),
447 DECL(AL_FORMAT_MONO8
),
448 DECL(AL_FORMAT_MONO16
),
449 DECL(AL_FORMAT_MONO_FLOAT32
),
450 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
451 DECL(AL_FORMAT_STEREO8
),
452 DECL(AL_FORMAT_STEREO16
),
453 DECL(AL_FORMAT_STEREO_FLOAT32
),
454 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
455 DECL(AL_FORMAT_MONO_IMA4
),
456 DECL(AL_FORMAT_STEREO_IMA4
),
457 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
458 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
459 DECL(AL_FORMAT_QUAD8_LOKI
),
460 DECL(AL_FORMAT_QUAD16_LOKI
),
461 DECL(AL_FORMAT_QUAD8
),
462 DECL(AL_FORMAT_QUAD16
),
463 DECL(AL_FORMAT_QUAD32
),
464 DECL(AL_FORMAT_51CHN8
),
465 DECL(AL_FORMAT_51CHN16
),
466 DECL(AL_FORMAT_51CHN32
),
467 DECL(AL_FORMAT_61CHN8
),
468 DECL(AL_FORMAT_61CHN16
),
469 DECL(AL_FORMAT_61CHN32
),
470 DECL(AL_FORMAT_71CHN8
),
471 DECL(AL_FORMAT_71CHN16
),
472 DECL(AL_FORMAT_71CHN32
),
473 DECL(AL_FORMAT_REAR8
),
474 DECL(AL_FORMAT_REAR16
),
475 DECL(AL_FORMAT_REAR32
),
476 DECL(AL_FORMAT_MONO_MULAW
),
477 DECL(AL_FORMAT_MONO_MULAW_EXT
),
478 DECL(AL_FORMAT_STEREO_MULAW
),
479 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
480 DECL(AL_FORMAT_QUAD_MULAW
),
481 DECL(AL_FORMAT_51CHN_MULAW
),
482 DECL(AL_FORMAT_61CHN_MULAW
),
483 DECL(AL_FORMAT_71CHN_MULAW
),
484 DECL(AL_FORMAT_REAR_MULAW
),
485 DECL(AL_FORMAT_MONO_ALAW_EXT
),
486 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
488 DECL(AL_FORMAT_BFORMAT2D_8
),
489 DECL(AL_FORMAT_BFORMAT2D_16
),
490 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
491 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
492 DECL(AL_FORMAT_BFORMAT3D_8
),
493 DECL(AL_FORMAT_BFORMAT3D_16
),
494 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
495 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
501 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
502 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
504 DECL(AL_SOURCE_RADIUS
),
506 DECL(AL_STEREO_ANGLES
),
513 DECL(AL_INVALID_NAME
),
514 DECL(AL_INVALID_ENUM
),
515 DECL(AL_INVALID_VALUE
),
516 DECL(AL_INVALID_OPERATION
),
517 DECL(AL_OUT_OF_MEMORY
),
524 DECL(AL_DOPPLER_FACTOR
),
525 DECL(AL_DOPPLER_VELOCITY
),
526 DECL(AL_DISTANCE_MODEL
),
527 DECL(AL_SPEED_OF_SOUND
),
528 DECL(AL_SOURCE_DISTANCE_MODEL
),
529 DECL(AL_DEFERRED_UPDATES_SOFT
),
530 DECL(AL_GAIN_LIMIT_SOFT
),
532 DECL(AL_INVERSE_DISTANCE
),
533 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
534 DECL(AL_LINEAR_DISTANCE
),
535 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
536 DECL(AL_EXPONENT_DISTANCE
),
537 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
539 DECL(AL_FILTER_TYPE
),
540 DECL(AL_FILTER_NULL
),
541 DECL(AL_FILTER_LOWPASS
),
542 DECL(AL_FILTER_HIGHPASS
),
543 DECL(AL_FILTER_BANDPASS
),
545 DECL(AL_LOWPASS_GAIN
),
546 DECL(AL_LOWPASS_GAINHF
),
548 DECL(AL_HIGHPASS_GAIN
),
549 DECL(AL_HIGHPASS_GAINLF
),
551 DECL(AL_BANDPASS_GAIN
),
552 DECL(AL_BANDPASS_GAINHF
),
553 DECL(AL_BANDPASS_GAINLF
),
555 DECL(AL_EFFECT_TYPE
),
556 DECL(AL_EFFECT_NULL
),
557 DECL(AL_EFFECT_REVERB
),
558 DECL(AL_EFFECT_EAXREVERB
),
559 DECL(AL_EFFECT_CHORUS
),
560 DECL(AL_EFFECT_DISTORTION
),
561 DECL(AL_EFFECT_ECHO
),
562 DECL(AL_EFFECT_FLANGER
),
563 DECL(AL_EFFECT_PITCH_SHIFTER
),
564 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
566 DECL(AL_EFFECT_VOCAL_MORPHER
),
568 DECL(AL_EFFECT_RING_MODULATOR
),
569 DECL(AL_EFFECT_AUTOWAH
),
570 DECL(AL_EFFECT_COMPRESSOR
),
571 DECL(AL_EFFECT_EQUALIZER
),
572 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
573 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
575 DECL(AL_EFFECTSLOT_EFFECT
),
576 DECL(AL_EFFECTSLOT_GAIN
),
577 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
578 DECL(AL_EFFECTSLOT_NULL
),
580 DECL(AL_EAXREVERB_DENSITY
),
581 DECL(AL_EAXREVERB_DIFFUSION
),
582 DECL(AL_EAXREVERB_GAIN
),
583 DECL(AL_EAXREVERB_GAINHF
),
584 DECL(AL_EAXREVERB_GAINLF
),
585 DECL(AL_EAXREVERB_DECAY_TIME
),
586 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
587 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
588 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
589 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
590 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
591 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
592 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
593 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
594 DECL(AL_EAXREVERB_ECHO_TIME
),
595 DECL(AL_EAXREVERB_ECHO_DEPTH
),
596 DECL(AL_EAXREVERB_MODULATION_TIME
),
597 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
598 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
599 DECL(AL_EAXREVERB_HFREFERENCE
),
600 DECL(AL_EAXREVERB_LFREFERENCE
),
601 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
602 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
604 DECL(AL_REVERB_DENSITY
),
605 DECL(AL_REVERB_DIFFUSION
),
606 DECL(AL_REVERB_GAIN
),
607 DECL(AL_REVERB_GAINHF
),
608 DECL(AL_REVERB_DECAY_TIME
),
609 DECL(AL_REVERB_DECAY_HFRATIO
),
610 DECL(AL_REVERB_REFLECTIONS_GAIN
),
611 DECL(AL_REVERB_REFLECTIONS_DELAY
),
612 DECL(AL_REVERB_LATE_REVERB_GAIN
),
613 DECL(AL_REVERB_LATE_REVERB_DELAY
),
614 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
615 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
616 DECL(AL_REVERB_DECAY_HFLIMIT
),
618 DECL(AL_CHORUS_WAVEFORM
),
619 DECL(AL_CHORUS_PHASE
),
620 DECL(AL_CHORUS_RATE
),
621 DECL(AL_CHORUS_DEPTH
),
622 DECL(AL_CHORUS_FEEDBACK
),
623 DECL(AL_CHORUS_DELAY
),
625 DECL(AL_DISTORTION_EDGE
),
626 DECL(AL_DISTORTION_GAIN
),
627 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
628 DECL(AL_DISTORTION_EQCENTER
),
629 DECL(AL_DISTORTION_EQBANDWIDTH
),
632 DECL(AL_ECHO_LRDELAY
),
633 DECL(AL_ECHO_DAMPING
),
634 DECL(AL_ECHO_FEEDBACK
),
635 DECL(AL_ECHO_SPREAD
),
637 DECL(AL_FLANGER_WAVEFORM
),
638 DECL(AL_FLANGER_PHASE
),
639 DECL(AL_FLANGER_RATE
),
640 DECL(AL_FLANGER_DEPTH
),
641 DECL(AL_FLANGER_FEEDBACK
),
642 DECL(AL_FLANGER_DELAY
),
644 DECL(AL_FREQUENCY_SHIFTER_FREQUENCY
),
645 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
646 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
648 DECL(AL_RING_MODULATOR_FREQUENCY
),
649 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
650 DECL(AL_RING_MODULATOR_WAVEFORM
),
652 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
653 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
655 DECL(AL_COMPRESSOR_ONOFF
),
657 DECL(AL_EQUALIZER_LOW_GAIN
),
658 DECL(AL_EQUALIZER_LOW_CUTOFF
),
659 DECL(AL_EQUALIZER_MID1_GAIN
),
660 DECL(AL_EQUALIZER_MID1_CENTER
),
661 DECL(AL_EQUALIZER_MID1_WIDTH
),
662 DECL(AL_EQUALIZER_MID2_GAIN
),
663 DECL(AL_EQUALIZER_MID2_CENTER
),
664 DECL(AL_EQUALIZER_MID2_WIDTH
),
665 DECL(AL_EQUALIZER_HIGH_GAIN
),
666 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
668 DECL(AL_DEDICATED_GAIN
),
670 DECL(AL_AUTOWAH_ATTACK_TIME
),
671 DECL(AL_AUTOWAH_RELEASE_TIME
),
672 DECL(AL_AUTOWAH_RESONANCE
),
673 DECL(AL_AUTOWAH_PEAK_GAIN
),
675 DECL(AL_NUM_RESAMPLERS_SOFT
),
676 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
677 DECL(AL_SOURCE_RESAMPLER_SOFT
),
678 DECL(AL_RESAMPLER_NAME_SOFT
),
680 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
683 DECL(AL_MAP_READ_BIT_SOFT
),
684 DECL(AL_MAP_WRITE_BIT_SOFT
),
685 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
686 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
688 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
689 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
690 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
691 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
692 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
693 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
694 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
698 constexpr ALCchar alcNoError
[] = "No Error";
699 constexpr ALCchar alcErrInvalidDevice
[] = "Invalid Device";
700 constexpr ALCchar alcErrInvalidContext
[] = "Invalid Context";
701 constexpr ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
702 constexpr ALCchar alcErrInvalidValue
[] = "Invalid Value";
703 constexpr ALCchar alcErrOutOfMemory
[] = "Out of Memory";
706 /************************************************
708 ************************************************/
710 /* Enumerated device names */
711 constexpr ALCchar alcDefaultName
[] = "OpenAL Soft\0";
713 std::string alcAllDevicesList
;
714 std::string alcCaptureDeviceList
;
716 /* Default is always the first in the list */
717 std::string alcDefaultAllDevicesSpecifier
;
718 std::string alcCaptureDefaultDeviceSpecifier
;
720 /* Default context extensions */
721 constexpr ALchar alExtList
[] =
725 "AL_EXT_EXPONENT_DISTANCE "
728 "AL_EXT_LINEAR_DISTANCE "
731 "AL_EXT_MULAW_BFORMAT "
732 "AL_EXT_MULAW_MCFORMATS "
734 "AL_EXT_source_distance_model "
735 "AL_EXT_SOURCE_RADIUS "
736 "AL_EXT_STEREO_ANGLES "
737 "AL_LOKI_quadriphonic "
738 "AL_SOFT_block_alignment "
739 "AL_SOFT_deferred_updates "
740 "AL_SOFT_direct_channels "
742 "AL_SOFTX_filter_gain_ex "
743 "AL_SOFT_gain_clamp_ex "
744 "AL_SOFT_loop_points "
745 "AL_SOFTX_map_buffer "
747 "AL_SOFT_source_latency "
748 "AL_SOFT_source_length "
749 "AL_SOFT_source_resampler "
750 "AL_SOFT_source_spatialize";
752 std::atomic
<ALCenum
> LastNullDeviceError
{ALC_NO_ERROR
};
754 /* Thread-local current context */
755 altss_t LocalContext
;
756 /* Process-wide current context */
757 std::atomic
<ALCcontext
*> GlobalContext
{nullptr};
759 /* Flag to trap ALC device errors */
760 bool TrapALCError
{false};
762 /* One-time configuration init control */
763 std::once_flag alc_config_once
{};
765 /* Default effect that applies to sources that don't have an effect on send 0 */
766 ALeffect DefaultEffect
;
768 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
771 bool SuspendDefers
{true};
774 /************************************************
776 ************************************************/
777 constexpr ALCchar alcNoDeviceExtList
[] =
778 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
779 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
780 constexpr ALCchar alcExtensionList
[] =
781 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
782 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
783 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
784 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
785 constexpr ALCint alcMajorVersion
= 1;
786 constexpr ALCint alcMinorVersion
= 1;
788 constexpr ALCint alcEFXMajorVersion
= 1;
789 constexpr ALCint alcEFXMinorVersion
= 0;
792 /************************************************
794 ************************************************/
795 std::atomic
<ALCdevice
*> DeviceList
{nullptr};
797 std::recursive_mutex ListLock
;
801 /* Mixing thread piority level */
806 enum LogLevel LogLevel
= LogWarning
;
808 enum LogLevel LogLevel
= LogError
;
811 /************************************************
812 * Library initialization
813 ************************************************/
815 static void alc_init(void);
816 static void alc_deinit(void);
817 static void alc_deinit_safe(void);
819 #ifndef AL_LIBTYPE_STATIC
820 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
824 case DLL_PROCESS_ATTACH
:
825 /* Pin the DLL so we won't get unloaded until the process terminates */
826 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
827 (WCHAR
*)hModule
, &hModule
);
831 case DLL_THREAD_DETACH
:
832 althrd_thread_detach();
835 case DLL_PROCESS_DETACH
:
844 #elif defined(_MSC_VER)
845 #pragma section(".CRT$XCU",read)
846 static void alc_constructor(void);
847 static void alc_destructor(void);
848 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
850 static void alc_constructor(void)
852 atexit(alc_destructor
);
856 static void alc_destructor(void)
860 #elif defined(HAVE_GCC_DESTRUCTOR)
861 static void alc_init(void) __attribute__((constructor
));
862 static void alc_deinit(void) __attribute__((destructor
));
864 #error "No static initialization available on this platform!"
867 #elif defined(HAVE_GCC_DESTRUCTOR)
869 static void alc_init(void) __attribute__((constructor
));
870 static void alc_deinit(void) __attribute__((destructor
));
873 #error "No global initialization available on this platform!"
876 static void ReleaseThreadCtx(void *ptr
);
877 static void alc_init(void)
884 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
885 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
888 str
= getenv("__ALSOFT_REVERSE_Z");
889 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
892 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
893 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
894 OverrideReverbSpeedOfSound
= AL_TRUE
;
896 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
897 assert(ret
== althrd_success
);
900 static void alc_initconfig(void)
902 const char *devs
, *str
;
907 str
= getenv("ALSOFT_LOGLEVEL");
910 long lvl
= strtol(str
, nullptr, 0);
911 if(lvl
>= NoLog
&& lvl
<= LogRef
)
912 LogLevel
= static_cast<enum LogLevel
>(lvl
);
915 str
= getenv("ALSOFT_LOGFILE");
919 std::wstring wname
{utf8_to_wstr(str
)};
920 FILE *logfile
= _wfopen(wname
.c_str(), L
"wt");
922 FILE *logfile
= fopen(str
, "wt");
924 if(logfile
) LogFile
= logfile
;
925 else ERR("Failed to open log file '%s'\n", str
);
928 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
929 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
934 if(BackendListSize
> 0)
935 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
936 for(i
= 1;i
< BackendListSize
;i
++)
937 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
938 TRACE("Supported backends: %s\n", buf
);
942 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
945 if(strcasecmp(str
, "ignore") == 0)
947 SuspendDefers
= false;
948 TRACE("Selected context suspend behavior, \"ignore\"\n");
951 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
955 #if defined(HAVE_SSE4_1)
956 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
957 #elif defined(HAVE_SSE3)
958 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
959 #elif defined(HAVE_SSE2)
960 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
961 #elif defined(HAVE_SSE)
962 capfilter
|= CPU_CAP_SSE
;
965 capfilter
|= CPU_CAP_NEON
;
967 if(ConfigValueStr(nullptr, nullptr, "disable-cpu-exts", &str
))
969 if(strcasecmp(str
, "all") == 0)
974 const char *next
= str
;
978 while(isspace(str
[0]))
980 next
= strchr(str
, ',');
982 if(!str
[0] || str
[0] == ',')
985 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
986 while(len
> 0 && isspace(str
[len
-1]))
988 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
989 capfilter
&= ~CPU_CAP_SSE
;
990 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
991 capfilter
&= ~CPU_CAP_SSE2
;
992 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
993 capfilter
&= ~CPU_CAP_SSE3
;
994 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
995 capfilter
&= ~CPU_CAP_SSE4_1
;
996 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
997 capfilter
&= ~CPU_CAP_NEON
;
999 WARN("Invalid CPU extension \"%s\"\n", str
);
1003 FillCPUCaps(capfilter
);
1010 ConfigValueInt(nullptr, nullptr, "rt-prio", &RTPrioLevel
);
1015 str
= getenv("ALSOFT_TRAP_ERROR");
1016 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1018 TrapALError
= AL_TRUE
;
1019 TrapALCError
= true;
1023 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1024 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1025 TrapALError
= AL_TRUE
;
1026 TrapALError
= GetConfigValueBool(nullptr, nullptr, "trap-al-error", TrapALError
);
1028 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1029 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, nullptr, 0) == 1))
1030 TrapALCError
= true;
1031 TrapALCError
= !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", TrapALCError
);
1034 if(ConfigValueFloat(nullptr, "reverb", "boost", &valf
))
1035 ReverbBoost
*= std::pow(10.0f
, valf
/ 20.0f
);
1037 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1038 ConfigValueStr(nullptr, nullptr, "drivers", &devs
))
1042 const char *next
= devs
;
1043 int endlist
, delitem
;
1048 while(isspace(devs
[0]))
1050 next
= strchr(devs
, ',');
1052 delitem
= (devs
[0] == '-');
1053 if(devs
[0] == '-') devs
++;
1055 if(!devs
[0] || devs
[0] == ',')
1062 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1063 while(len
> 0 && isspace(devs
[len
-1]))
1066 /* HACK: For backwards compatibility, convert backend references of
1067 * mmdevapi to wasapi. This should eventually be removed.
1069 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1075 for(n
= i
;n
< BackendListSize
;n
++)
1077 if(len
== strlen(BackendList
[n
].name
) &&
1078 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1082 for(;n
+1 < BackendListSize
;n
++)
1083 BackendList
[n
] = BackendList
[n
+1];
1088 struct BackendInfo Bkp
= BackendList
[n
];
1090 BackendList
[n
] = BackendList
[n
-1];
1091 BackendList
[n
] = Bkp
;
1101 BackendListSize
= i
;
1104 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1106 BackendList
[n
] = BackendList
[i
];
1108 BackendFactory
&factory
= BackendList
[n
].getFactory();
1111 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1115 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1116 if(!PlaybackBackend
.name
&& factory
.querySupport(ALCbackend_Playback
))
1118 PlaybackBackend
= BackendList
[n
];
1119 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1121 if(!CaptureBackend
.name
&& factory
.querySupport(ALCbackend_Capture
))
1123 CaptureBackend
= BackendList
[n
];
1124 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1128 BackendListSize
= n
;
1131 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1135 if(!PlaybackBackend
.name
)
1136 WARN("No playback backend available!\n");
1137 if(!CaptureBackend
.name
)
1138 WARN("No capture backend available!\n");
1140 if(ConfigValueStr(nullptr, nullptr, "excludefx", &str
))
1143 const char *next
= str
;
1147 next
= strchr(str
, ',');
1149 if(!str
[0] || next
== str
)
1152 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1153 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1155 if(len
== strlen(EffectList
[n
].name
) &&
1156 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1157 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1162 InitEffect(&DefaultEffect
);
1163 str
= getenv("ALSOFT_DEFAULT_REVERB");
1164 if((str
&& str
[0]) || ConfigValueStr(nullptr, nullptr, "default-reverb", &str
))
1165 LoadReverbPreset(str
, &DefaultEffect
);
1167 #define DO_INITCONFIG() std::call_once(alc_config_once, alc_initconfig)
1170 /************************************************
1171 * Library deinitialization
1172 ************************************************/
1173 static void alc_cleanup(void)
1175 alcAllDevicesList
.clear();
1176 alcCaptureDeviceList
.clear();
1178 alcDefaultAllDevicesSpecifier
.clear();
1179 alcCaptureDefaultDeviceSpecifier
.clear();
1181 if(ALCdevice
*dev
{DeviceList
.exchange(nullptr)})
1186 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
1187 } while(dev
!= nullptr);
1188 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1192 static void alc_deinit_safe(void)
1199 altss_delete(LocalContext
);
1201 if(LogFile
!= stderr
)
1208 static void alc_deinit(void)
1214 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1215 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1217 for(i
= 0;i
< BackendListSize
;i
++)
1218 BackendList
[i
].getFactory().deinit();
1221 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1222 V0(factory
,deinit
)();
1229 /************************************************
1230 * Device enumeration
1231 ************************************************/
1232 static void ProbeDevices(std::string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1236 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
1238 if(backendinfo
->getFactory
)
1239 backendinfo
->getFactory().probe(type
, list
);
1241 static void ProbeAllDevicesList(void)
1242 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1243 static void ProbeCaptureDeviceList(void)
1244 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1247 /************************************************
1248 * Device format information
1249 ************************************************/
1250 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1254 case DevFmtByte
: return "Signed Byte";
1255 case DevFmtUByte
: return "Unsigned Byte";
1256 case DevFmtShort
: return "Signed Short";
1257 case DevFmtUShort
: return "Unsigned Short";
1258 case DevFmtInt
: return "Signed Int";
1259 case DevFmtUInt
: return "Unsigned Int";
1260 case DevFmtFloat
: return "Float";
1262 return "(unknown type)";
1264 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1268 case DevFmtMono
: return "Mono";
1269 case DevFmtStereo
: return "Stereo";
1270 case DevFmtQuad
: return "Quadraphonic";
1271 case DevFmtX51
: return "5.1 Surround";
1272 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1273 case DevFmtX61
: return "6.1 Surround";
1274 case DevFmtX71
: return "7.1 Surround";
1275 case DevFmtAmbi3D
: return "Ambisonic 3D";
1277 return "(unknown channels)";
1280 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1284 case DevFmtByte
: return sizeof(ALbyte
);
1285 case DevFmtUByte
: return sizeof(ALubyte
);
1286 case DevFmtShort
: return sizeof(ALshort
);
1287 case DevFmtUShort
: return sizeof(ALushort
);
1288 case DevFmtInt
: return sizeof(ALint
);
1289 case DevFmtUInt
: return sizeof(ALuint
);
1290 case DevFmtFloat
: return sizeof(ALfloat
);
1294 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1298 case DevFmtMono
: return 1;
1299 case DevFmtStereo
: return 2;
1300 case DevFmtQuad
: return 4;
1301 case DevFmtX51
: return 6;
1302 case DevFmtX51Rear
: return 6;
1303 case DevFmtX61
: return 7;
1304 case DevFmtX71
: return 8;
1305 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1306 (ambiorder
== 2) ? 9 :
1307 (ambiorder
== 1) ? 4 : 1;
1312 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1313 enum DevFmtType
*type
)
1315 static const struct {
1317 enum DevFmtChannels channels
;
1318 enum DevFmtType type
;
1320 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1321 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1322 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1324 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1325 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1326 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1328 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1329 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1330 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1332 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1333 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1334 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1336 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1337 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1338 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1340 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1341 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1342 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1346 for(i
= 0;i
< COUNTOF(list
);i
++)
1348 if(list
[i
].format
== format
)
1350 *chans
= list
[i
].channels
;
1351 *type
= list
[i
].type
;
1359 static ALCboolean
IsValidALCType(ALCenum type
)
1364 case ALC_UNSIGNED_BYTE_SOFT
:
1365 case ALC_SHORT_SOFT
:
1366 case ALC_UNSIGNED_SHORT_SOFT
:
1368 case ALC_UNSIGNED_INT_SOFT
:
1369 case ALC_FLOAT_SOFT
:
1375 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1380 case ALC_STEREO_SOFT
:
1382 case ALC_5POINT1_SOFT
:
1383 case ALC_6POINT1_SOFT
:
1384 case ALC_7POINT1_SOFT
:
1385 case ALC_BFORMAT3D_SOFT
:
1391 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1402 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1414 /************************************************
1415 * Miscellaneous ALC helpers
1416 ************************************************/
1418 /* SetDefaultWFXChannelOrder
1420 * Sets the default channel order used by WaveFormatEx.
1422 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1426 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1427 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1429 switch(device
->FmtChans
)
1432 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1435 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1436 device
->RealOut
.ChannelName
[1] = FrontRight
;
1439 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1440 device
->RealOut
.ChannelName
[1] = FrontRight
;
1441 device
->RealOut
.ChannelName
[2] = BackLeft
;
1442 device
->RealOut
.ChannelName
[3] = BackRight
;
1445 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1446 device
->RealOut
.ChannelName
[1] = FrontRight
;
1447 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1448 device
->RealOut
.ChannelName
[3] = LFE
;
1449 device
->RealOut
.ChannelName
[4] = SideLeft
;
1450 device
->RealOut
.ChannelName
[5] = SideRight
;
1453 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1454 device
->RealOut
.ChannelName
[1] = FrontRight
;
1455 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1456 device
->RealOut
.ChannelName
[3] = LFE
;
1457 device
->RealOut
.ChannelName
[4] = BackLeft
;
1458 device
->RealOut
.ChannelName
[5] = BackRight
;
1461 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1462 device
->RealOut
.ChannelName
[1] = FrontRight
;
1463 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1464 device
->RealOut
.ChannelName
[3] = LFE
;
1465 device
->RealOut
.ChannelName
[4] = BackCenter
;
1466 device
->RealOut
.ChannelName
[5] = SideLeft
;
1467 device
->RealOut
.ChannelName
[6] = SideRight
;
1470 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1471 device
->RealOut
.ChannelName
[1] = FrontRight
;
1472 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1473 device
->RealOut
.ChannelName
[3] = LFE
;
1474 device
->RealOut
.ChannelName
[4] = BackLeft
;
1475 device
->RealOut
.ChannelName
[5] = BackRight
;
1476 device
->RealOut
.ChannelName
[6] = SideLeft
;
1477 device
->RealOut
.ChannelName
[7] = SideRight
;
1480 device
->RealOut
.ChannelName
[0] = Aux0
;
1481 if(device
->AmbiOrder
> 0)
1483 device
->RealOut
.ChannelName
[1] = Aux1
;
1484 device
->RealOut
.ChannelName
[2] = Aux2
;
1485 device
->RealOut
.ChannelName
[3] = Aux3
;
1487 if(device
->AmbiOrder
> 1)
1489 device
->RealOut
.ChannelName
[4] = Aux4
;
1490 device
->RealOut
.ChannelName
[5] = Aux5
;
1491 device
->RealOut
.ChannelName
[6] = Aux6
;
1492 device
->RealOut
.ChannelName
[7] = Aux7
;
1493 device
->RealOut
.ChannelName
[8] = Aux8
;
1495 if(device
->AmbiOrder
> 2)
1497 device
->RealOut
.ChannelName
[9] = Aux9
;
1498 device
->RealOut
.ChannelName
[10] = Aux10
;
1499 device
->RealOut
.ChannelName
[11] = Aux11
;
1500 device
->RealOut
.ChannelName
[12] = Aux12
;
1501 device
->RealOut
.ChannelName
[13] = Aux13
;
1502 device
->RealOut
.ChannelName
[14] = Aux14
;
1503 device
->RealOut
.ChannelName
[15] = Aux15
;
1509 /* SetDefaultChannelOrder
1511 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1513 void SetDefaultChannelOrder(ALCdevice
*device
)
1517 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1518 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1520 switch(device
->FmtChans
)
1523 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1524 device
->RealOut
.ChannelName
[1] = FrontRight
;
1525 device
->RealOut
.ChannelName
[2] = BackLeft
;
1526 device
->RealOut
.ChannelName
[3] = BackRight
;
1527 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1528 device
->RealOut
.ChannelName
[5] = LFE
;
1531 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1532 device
->RealOut
.ChannelName
[1] = FrontRight
;
1533 device
->RealOut
.ChannelName
[2] = BackLeft
;
1534 device
->RealOut
.ChannelName
[3] = BackRight
;
1535 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1536 device
->RealOut
.ChannelName
[5] = LFE
;
1537 device
->RealOut
.ChannelName
[6] = SideLeft
;
1538 device
->RealOut
.ChannelName
[7] = SideRight
;
1541 /* Same as WFX order */
1548 SetDefaultWFXChannelOrder(device
);
1554 /* ALCcontext_DeferUpdates
1556 * Defers/suspends updates for the given context's listener and sources. This
1557 * does *NOT* stop mixing, but rather prevents certain property changes from
1560 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1562 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1565 /* ALCcontext_ProcessUpdates
1567 * Resumes update processing after being deferred.
1569 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1571 almtx_lock(&context
->PropLock
);
1572 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1574 /* Tell the mixer to stop applying updates, then wait for any active
1575 * updating to finish, before providing updates.
1577 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1578 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1581 if(!ATOMIC_EXCHANGE(&context
->PropsClean
, AL_TRUE
, almemory_order_acq_rel
))
1582 UpdateContextProps(context
);
1583 if(!ATOMIC_EXCHANGE(&context
->Listener
->PropsClean
, AL_TRUE
, almemory_order_acq_rel
))
1584 UpdateListenerProps(context
);
1585 UpdateAllEffectSlotProps(context
);
1586 UpdateAllSourceProps(context
);
1588 /* Now with all updates declared, let the mixer continue applying them
1589 * so they all happen at once.
1591 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1593 almtx_unlock(&context
->PropLock
);
1599 * Stores the latest ALC device error
1601 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1603 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1607 /* DebugBreak() will cause an exception if there is no debugger */
1608 if(IsDebuggerPresent())
1610 #elif defined(SIGTRAP)
1616 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1618 LastNullDeviceError
.store(errorCode
);
1622 static struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
, const ALfloat threshold
)
1624 return CompressorInit(device
->RealOut
.NumChannels
, device
->Frequency
,
1625 AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, AL_TRUE
, 0.001f
, 0.002f
,
1626 0.0f
, 0.0f
, threshold
, INFINITY
, 0.0f
, 0.020f
, 0.200f
);
1631 * Updates the device's base clock time with however many samples have been
1632 * done. This is used so frequency changes on the device don't cause the time
1633 * to jump forward or back. Must not be called while the device is running/
1636 static inline void UpdateClockBase(ALCdevice
*device
)
1638 IncrementRef(&device
->MixCount
);
1639 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1640 device
->SamplesDone
= 0;
1641 IncrementRef(&device
->MixCount
);
1644 /* UpdateDeviceParams
1646 * Updates device parameters according to the attribute list (caller is
1647 * responsible for holding the list lock).
1649 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1651 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1652 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1653 ALCenum gainLimiter
= device
->LimiterState
;
1654 const ALsizei old_sends
= device
->NumAuxSends
;
1655 ALsizei new_sends
= device
->NumAuxSends
;
1656 enum DevFmtChannels oldChans
;
1657 enum DevFmtType oldType
;
1658 ALboolean update_failed
;
1659 ALCsizei hrtf_id
= -1;
1660 ALCcontext
*context
;
1666 // Check for attributes
1667 if(device
->Type
== Loopback
)
1669 ALCsizei numMono
, numStereo
, numSends
;
1670 ALCenum alayout
= AL_NONE
;
1671 ALCenum ascale
= AL_NONE
;
1672 ALCenum schans
= AL_NONE
;
1673 ALCenum stype
= AL_NONE
;
1674 ALCsizei attrIdx
= 0;
1675 ALCsizei aorder
= 0;
1680 WARN("Missing attributes for loopback device\n");
1681 return ALC_INVALID_VALUE
;
1684 numMono
= device
->NumMonoSources
;
1685 numStereo
= device
->NumStereoSources
;
1686 numSends
= old_sends
;
1688 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1689 while(attrList
[attrIdx
])
1691 switch(attrList
[attrIdx
])
1693 case ALC_FORMAT_CHANNELS_SOFT
:
1694 schans
= attrList
[attrIdx
+ 1];
1695 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1696 if(!IsValidALCChannels(schans
))
1697 return ALC_INVALID_VALUE
;
1700 case ALC_FORMAT_TYPE_SOFT
:
1701 stype
= attrList
[attrIdx
+ 1];
1702 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1703 if(!IsValidALCType(stype
))
1704 return ALC_INVALID_VALUE
;
1708 freq
= attrList
[attrIdx
+ 1];
1709 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1710 if(freq
< MIN_OUTPUT_RATE
)
1711 return ALC_INVALID_VALUE
;
1714 case ALC_AMBISONIC_LAYOUT_SOFT
:
1715 alayout
= attrList
[attrIdx
+ 1];
1716 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1717 if(!IsValidAmbiLayout(alayout
))
1718 return ALC_INVALID_VALUE
;
1721 case ALC_AMBISONIC_SCALING_SOFT
:
1722 ascale
= attrList
[attrIdx
+ 1];
1723 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1724 if(!IsValidAmbiScaling(ascale
))
1725 return ALC_INVALID_VALUE
;
1728 case ALC_AMBISONIC_ORDER_SOFT
:
1729 aorder
= attrList
[attrIdx
+ 1];
1730 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1731 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1732 return ALC_INVALID_VALUE
;
1735 case ALC_MONO_SOURCES
:
1736 numMono
= attrList
[attrIdx
+ 1];
1737 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1738 numMono
= maxi(numMono
, 0);
1741 case ALC_STEREO_SOURCES
:
1742 numStereo
= attrList
[attrIdx
+ 1];
1743 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1744 numStereo
= maxi(numStereo
, 0);
1747 case ALC_MAX_AUXILIARY_SENDS
:
1748 numSends
= attrList
[attrIdx
+ 1];
1749 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1750 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1754 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1755 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1756 hrtf_appreq
= Hrtf_Disable
;
1757 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1758 hrtf_appreq
= Hrtf_Enable
;
1760 hrtf_appreq
= Hrtf_Default
;
1763 case ALC_HRTF_ID_SOFT
:
1764 hrtf_id
= attrList
[attrIdx
+ 1];
1765 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1768 case ALC_OUTPUT_LIMITER_SOFT
:
1769 gainLimiter
= attrList
[attrIdx
+ 1];
1770 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1774 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1775 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1783 if(!schans
|| !stype
|| !freq
)
1785 WARN("Missing format for loopback device\n");
1786 return ALC_INVALID_VALUE
;
1788 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1790 WARN("Missing ambisonic info for loopback device\n");
1791 return ALC_INVALID_VALUE
;
1794 if((device
->Flags
&DEVICE_RUNNING
))
1795 V0(device
->Backend
,stop
)();
1796 device
->Flags
&= ~DEVICE_RUNNING
;
1798 UpdateClockBase(device
);
1800 device
->Frequency
= freq
;
1801 device
->FmtChans
= static_cast<enum DevFmtChannels
>(schans
);
1802 device
->FmtType
= static_cast<enum DevFmtType
>(stype
);
1803 if(schans
== ALC_BFORMAT3D_SOFT
)
1805 device
->AmbiOrder
= aorder
;
1806 device
->AmbiLayout
= static_cast<enum AmbiLayout
>(alayout
);
1807 device
->AmbiScale
= static_cast<enum AmbiNorm
>(ascale
);
1810 if(numMono
> INT_MAX
-numStereo
)
1811 numMono
= INT_MAX
-numStereo
;
1812 numMono
+= numStereo
;
1813 if(ConfigValueInt(nullptr, nullptr, "sources", &numMono
))
1819 numMono
= maxi(numMono
, 256);
1820 numStereo
= mini(numStereo
, numMono
);
1821 numMono
-= numStereo
;
1822 device
->SourcesMax
= numMono
+ numStereo
;
1824 device
->NumMonoSources
= numMono
;
1825 device
->NumStereoSources
= numStereo
;
1827 if(ConfigValueInt(nullptr, nullptr, "sends", &new_sends
))
1828 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1830 new_sends
= numSends
;
1832 else if(attrList
&& attrList
[0])
1834 ALCsizei numMono
, numStereo
, numSends
;
1835 ALCsizei attrIdx
= 0;
1838 /* If a context is already running on the device, stop playback so the
1839 * device attributes can be updated. */
1840 if((device
->Flags
&DEVICE_RUNNING
))
1841 V0(device
->Backend
,stop
)();
1842 device
->Flags
&= ~DEVICE_RUNNING
;
1844 UpdateClockBase(device
);
1846 freq
= device
->Frequency
;
1847 numMono
= device
->NumMonoSources
;
1848 numStereo
= device
->NumStereoSources
;
1849 numSends
= old_sends
;
1851 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1852 while(attrList
[attrIdx
])
1854 switch(attrList
[attrIdx
])
1857 freq
= attrList
[attrIdx
+ 1];
1858 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1859 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1862 case ALC_MONO_SOURCES
:
1863 numMono
= attrList
[attrIdx
+ 1];
1864 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1865 numMono
= maxi(numMono
, 0);
1868 case ALC_STEREO_SOURCES
:
1869 numStereo
= attrList
[attrIdx
+ 1];
1870 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1871 numStereo
= maxi(numStereo
, 0);
1874 case ALC_MAX_AUXILIARY_SENDS
:
1875 numSends
= attrList
[attrIdx
+ 1];
1876 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1877 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1881 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1882 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1883 hrtf_appreq
= Hrtf_Disable
;
1884 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1885 hrtf_appreq
= Hrtf_Enable
;
1887 hrtf_appreq
= Hrtf_Default
;
1890 case ALC_HRTF_ID_SOFT
:
1891 hrtf_id
= attrList
[attrIdx
+ 1];
1892 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1895 case ALC_OUTPUT_LIMITER_SOFT
:
1896 gainLimiter
= attrList
[attrIdx
+ 1];
1897 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1901 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1902 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1910 ConfigValueUInt(device
->DeviceName
, nullptr, "frequency", &freq
);
1911 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1913 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1915 /* SSE and Neon do best with the update size being a multiple of 4 */
1916 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1917 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1919 device
->Frequency
= freq
;
1921 if(numMono
> INT_MAX
-numStereo
)
1922 numMono
= INT_MAX
-numStereo
;
1923 numMono
+= numStereo
;
1924 if(ConfigValueInt(device
->DeviceName
, nullptr, "sources", &numMono
))
1930 numMono
= maxi(numMono
, 256);
1931 numStereo
= mini(numStereo
, numMono
);
1932 numMono
-= numStereo
;
1933 device
->SourcesMax
= numMono
+ numStereo
;
1935 device
->NumMonoSources
= numMono
;
1936 device
->NumStereoSources
= numStereo
;
1938 if(ConfigValueInt(device
->DeviceName
, nullptr, "sends", &new_sends
))
1939 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1941 new_sends
= numSends
;
1944 if((device
->Flags
&DEVICE_RUNNING
))
1945 return ALC_NO_ERROR
;
1947 al_free(device
->Uhj_Encoder
);
1948 device
->Uhj_Encoder
= nullptr;
1950 al_free(device
->Bs2b
);
1951 device
->Bs2b
= nullptr;
1953 al_free(device
->ChannelDelay
[0].Buffer
);
1954 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1956 device
->ChannelDelay
[i
].Length
= 0;
1957 device
->ChannelDelay
[i
].Buffer
= nullptr;
1960 al_free(device
->Dry
.Buffer
);
1961 device
->Dry
.Buffer
= nullptr;
1962 device
->Dry
.NumChannels
= 0;
1963 device
->FOAOut
.Buffer
= nullptr;
1964 device
->FOAOut
.NumChannels
= 0;
1965 device
->RealOut
.Buffer
= nullptr;
1966 device
->RealOut
.NumChannels
= 0;
1968 UpdateClockBase(device
);
1969 device
->FixedLatency
= 0;
1971 device
->DitherSeed
= DITHER_RNG_SEED
;
1973 /*************************************************************************
1974 * Update device format request if HRTF is requested
1976 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
1977 if(device
->Type
!= Loopback
)
1980 if(ConfigValueStr(device
->DeviceName
, nullptr, "hrtf", &hrtf
))
1982 if(strcasecmp(hrtf
, "true") == 0)
1983 hrtf_userreq
= Hrtf_Enable
;
1984 else if(strcasecmp(hrtf
, "false") == 0)
1985 hrtf_userreq
= Hrtf_Disable
;
1986 else if(strcasecmp(hrtf
, "auto") != 0)
1987 ERR("Unexpected hrtf value: %s\n", hrtf
);
1990 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
1992 struct Hrtf
*hrtf
= nullptr;
1993 if(VECTOR_SIZE(device
->HrtfList
) == 0)
1995 VECTOR_DEINIT(device
->HrtfList
);
1996 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
1998 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2000 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2001 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2003 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2008 device
->FmtChans
= DevFmtStereo
;
2009 device
->Frequency
= hrtf
->sampleRate
;
2010 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2011 if(device
->HrtfHandle
)
2012 Hrtf_DecRef(device
->HrtfHandle
);
2013 device
->HrtfHandle
= hrtf
;
2017 hrtf_userreq
= Hrtf_Default
;
2018 hrtf_appreq
= Hrtf_Disable
;
2019 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2024 oldFreq
= device
->Frequency
;
2025 oldChans
= device
->FmtChans
;
2026 oldType
= device
->FmtType
;
2028 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2029 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2030 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2031 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2032 device
->UpdateSize
, device
->NumUpdates
2035 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2036 return ALC_INVALID_DEVICE
;
2038 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2040 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2041 DevFmtChannelsString(device
->FmtChans
));
2042 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2044 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2046 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2047 DevFmtTypeString(device
->FmtType
));
2048 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2050 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2052 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2053 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2056 if((device
->UpdateSize
&3) != 0)
2058 if((CPUCapFlags
&CPU_CAP_SSE
))
2059 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2060 if((CPUCapFlags
&CPU_CAP_NEON
))
2061 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2064 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2065 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2066 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2069 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2070 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2071 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2073 /* Allocate extra channels for any post-filter output. */
2074 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2075 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2077 TRACE("Allocating " SZFMT
" channels, " SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2078 device
->Dry
.Buffer
= static_cast<float(*)[BUFFERSIZE
]>(al_calloc(16, size
));
2079 if(!device
->Dry
.Buffer
)
2081 ERR("Failed to allocate " SZFMT
" bytes for mix buffer\n", size
);
2082 return ALC_INVALID_DEVICE
;
2085 if(device
->RealOut
.NumChannels
!= 0)
2086 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2087 device
->FOAOut
.NumChannels
;
2090 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2091 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2094 if(device
->FOAOut
.NumChannels
!= 0)
2095 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2098 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2099 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2102 device
->NumAuxSends
= new_sends
;
2103 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2104 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2105 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2107 device
->DitherDepth
= 0.0f
;
2108 if(GetConfigValueBool(device
->DeviceName
, nullptr, "dither", 1))
2111 ConfigValueInt(device
->DeviceName
, nullptr, "dither-depth", &depth
);
2114 switch(device
->FmtType
)
2133 depth
= clampi(depth
, 2, 24);
2134 device
->DitherDepth
= std::pow(2.0f
, (ALfloat
)(depth
-1));
2137 if(!(device
->DitherDepth
> 0.0f
))
2138 TRACE("Dithering disabled\n");
2140 TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device
->DitherDepth
)+0.5)+1,
2141 device
->DitherDepth
);
2143 device
->LimiterState
= gainLimiter
;
2144 if(ConfigValueBool(device
->DeviceName
, nullptr, "output-limiter", &val
))
2145 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2147 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2148 * ALC_FALSE. For ALC_DONT_CARE_SOFT, use the limiter for integer-based
2149 * output (where samples must be clamped), and don't for floating-point
2150 * (which can take unclamped samples).
2152 if(gainLimiter
== ALC_DONT_CARE_SOFT
)
2154 switch(device
->FmtType
)
2162 gainLimiter
= ALC_TRUE
;
2165 gainLimiter
= ALC_FALSE
;
2169 if(gainLimiter
!= ALC_FALSE
)
2171 ALfloat thrshld
= 1.0f
;
2172 switch(device
->FmtType
)
2176 thrshld
= 127.0f
/ 128.0f
;
2180 thrshld
= 32767.0f
/ 32768.0f
;
2187 if(device
->DitherDepth
> 0.0f
)
2188 thrshld
-= 1.0f
/ device
->DitherDepth
;
2190 al_free(device
->Limiter
);
2191 device
->Limiter
= CreateDeviceLimiter(device
, std::log10(thrshld
) * 20.0f
);
2192 device
->FixedLatency
+= (ALuint
)(GetCompressorLookAhead(device
->Limiter
) *
2193 DEVICE_CLOCK_RES
/ device
->Frequency
);
2197 al_free(device
->Limiter
);
2198 device
->Limiter
= nullptr;
2200 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2202 aluSelectPostProcess(device
);
2204 TRACE("Fixed device latency: %uns\n", device
->FixedLatency
);
2206 /* Need to delay returning failure until replacement Send arrays have been
2207 * allocated with the appropriate size.
2209 update_failed
= AL_FALSE
;
2211 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2214 SourceSubList
*sublist
, *subend
;
2215 struct ALvoiceProps
*vprops
;
2218 if(context
->DefaultSlot
)
2220 ALeffectslot
*slot
= context
->DefaultSlot
;
2221 ALeffectState
*state
= slot
->Effect
.State
;
2223 state
->OutBuffer
= device
->Dry
.Buffer
;
2224 state
->OutChannels
= device
->Dry
.NumChannels
;
2225 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2226 update_failed
= AL_TRUE
;
2228 UpdateEffectSlotProps(slot
, context
);
2231 almtx_lock(&context
->PropLock
);
2232 almtx_lock(&context
->EffectSlotLock
);
2233 for(pos
= 0;pos
< (ALsizei
)VECTOR_SIZE(context
->EffectSlotList
);pos
++)
2235 ALeffectslot
*slot
= VECTOR_ELEM(context
->EffectSlotList
, pos
);
2236 ALeffectState
*state
= slot
->Effect
.State
;
2238 state
->OutBuffer
= device
->Dry
.Buffer
;
2239 state
->OutChannels
= device
->Dry
.NumChannels
;
2240 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2241 update_failed
= AL_TRUE
;
2243 UpdateEffectSlotProps(slot
, context
);
2245 almtx_unlock(&context
->EffectSlotLock
);
2247 almtx_lock(&context
->SourceLock
);
2248 sublist
= VECTOR_BEGIN(context
->SourceList
);
2249 subend
= VECTOR_END(context
->SourceList
);
2250 for(;sublist
!= subend
;++sublist
)
2252 ALuint64 usemask
= ~sublist
->FreeMask
;
2255 ALsizei idx
= CTZ64(usemask
);
2256 ALsource
*source
= sublist
->Sources
+ idx
;
2258 usemask
&= ~(U64(1) << idx
);
2260 if(old_sends
!= device
->NumAuxSends
)
2262 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2265 memcpy(sends
, source
->Send
,
2266 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2268 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2270 if(source
->Send
[s
].Slot
)
2271 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2272 source
->Send
[s
].Slot
= nullptr;
2274 al_free(source
->Send
);
2275 source
->Send
= static_cast<decltype(source
->Send
)>(sends
);
2276 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2278 source
->Send
[s
].Slot
= nullptr;
2279 source
->Send
[s
].Gain
= 1.0f
;
2280 source
->Send
[s
].GainHF
= 1.0f
;
2281 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2282 source
->Send
[s
].GainLF
= 1.0f
;
2283 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2287 ATOMIC_STORE(&source
->PropsClean
, AL_FALSE
, almemory_order_release
);
2291 /* Clear any pre-existing voice property structs, in case the number of
2292 * auxiliary sends is changing. Active sources will have updates
2293 * respecified in UpdateAllSourceProps.
2295 vprops
= static_cast<ALvoiceProps
*>(ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
,
2296 static_cast<ALvoiceProps
*>(nullptr), almemory_order_acq_rel
));
2299 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2304 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2305 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2307 ALvoice
*voice
= context
->Voices
[pos
];
2309 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr),
2310 almemory_order_acq_rel
));
2312 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == nullptr)
2315 if(device
->AvgSpeakerDist
> 0.0f
)
2317 /* Reinitialize the NFC filters for new parameters. */
2318 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2319 (device
->AvgSpeakerDist
* device
->Frequency
);
2320 for(i
= 0;i
< voice
->NumChannels
;i
++)
2321 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2324 almtx_unlock(&context
->SourceLock
);
2326 ATOMIC_STORE(&context
->PropsClean
, AL_TRUE
, almemory_order_release
);
2327 UpdateContextProps(context
);
2328 ATOMIC_STORE(&context
->Listener
->PropsClean
, AL_TRUE
, almemory_order_release
);
2329 UpdateListenerProps(context
);
2330 UpdateAllSourceProps(context
);
2331 almtx_unlock(&context
->PropLock
);
2333 context
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2337 return ALC_INVALID_DEVICE
;
2339 if(!(device
->Flags
&DEVICE_PAUSED
))
2341 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2342 return ALC_INVALID_DEVICE
;
2343 device
->Flags
|= DEVICE_RUNNING
;
2346 return ALC_NO_ERROR
;
2350 static void InitDevice(ALCdevice
*device
, enum DeviceType type
)
2354 InitRef(&device
->ref
, 1);
2355 ATOMIC_INIT(&device
->Connected
, ALC_TRUE
);
2356 device
->Type
= type
;
2357 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
2360 device
->Render_Mode
= NormalRender
;
2361 device
->AvgSpeakerDist
= 0.0f
;
2362 device
->LimiterState
= ALC_DONT_CARE_SOFT
;
2364 ATOMIC_INIT(&device
->ContextList
, static_cast<ALCcontext
*>(nullptr));
2366 device
->ClockBase
= 0;
2367 device
->SamplesDone
= 0;
2368 device
->FixedLatency
= 0;
2370 device
->SourcesMax
= 0;
2371 device
->AuxiliaryEffectSlotMax
= 0;
2372 device
->NumAuxSends
= 0;
2374 device
->Dry
.Buffer
= nullptr;
2375 device
->Dry
.NumChannels
= 0;
2376 device
->FOAOut
.Buffer
= nullptr;
2377 device
->FOAOut
.NumChannels
= 0;
2378 device
->RealOut
.Buffer
= nullptr;
2379 device
->RealOut
.NumChannels
= 0;
2381 device
->DeviceName
= nullptr;
2383 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2385 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2386 device
->ChannelDelay
[i
].Length
= 0;
2387 device
->ChannelDelay
[i
].Buffer
= nullptr;
2390 device
->HrtfName
= nullptr;
2391 VECTOR_INIT(device
->HrtfList
);
2392 device
->HrtfHandle
= nullptr;
2393 device
->Hrtf
= nullptr;
2394 device
->Bs2b
= nullptr;
2395 device
->Uhj_Encoder
= nullptr;
2396 device
->AmbiDecoder
= nullptr;
2397 device
->AmbiUp
= nullptr;
2398 device
->Stablizer
= nullptr;
2399 device
->Limiter
= nullptr;
2401 VECTOR_INIT(device
->BufferList
);
2402 almtx_init(&device
->BufferLock
, almtx_plain
);
2404 VECTOR_INIT(device
->EffectList
);
2405 almtx_init(&device
->EffectLock
, almtx_plain
);
2407 VECTOR_INIT(device
->FilterList
);
2408 almtx_init(&device
->FilterLock
, almtx_plain
);
2410 almtx_init(&device
->BackendLock
, almtx_plain
);
2411 device
->Backend
= nullptr;
2413 ATOMIC_INIT(&device
->next
, static_cast<ALCdevice
*>(nullptr));
2418 * Frees the device structure, and destroys any objects the app failed to
2419 * delete. Called once there's no more references on the device.
2421 static ALCvoid
FreeDevice(ALCdevice
*device
)
2425 TRACE("%p\n", device
);
2428 DELETE_OBJ(device
->Backend
);
2429 device
->Backend
= nullptr;
2431 almtx_destroy(&device
->BackendLock
);
2433 ReleaseALBuffers(device
);
2434 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2435 VECTOR_FOR_EACH(BufferSubList
, device
->BufferList
, FREE_BUFFERSUBLIST
);
2436 #undef FREE_BUFFERSUBLIST
2437 VECTOR_DEINIT(device
->BufferList
);
2438 almtx_destroy(&device
->BufferLock
);
2440 ReleaseALEffects(device
);
2441 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2442 VECTOR_FOR_EACH(EffectSubList
, device
->EffectList
, FREE_EFFECTSUBLIST
);
2443 #undef FREE_EFFECTSUBLIST
2444 VECTOR_DEINIT(device
->EffectList
);
2445 almtx_destroy(&device
->EffectLock
);
2447 ReleaseALFilters(device
);
2448 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2449 VECTOR_FOR_EACH(FilterSubList
, device
->FilterList
, FREE_FILTERSUBLIST
);
2450 #undef FREE_FILTERSUBLIST
2451 VECTOR_DEINIT(device
->FilterList
);
2452 almtx_destroy(&device
->FilterLock
);
2454 al_free(device
->HrtfName
);
2455 device
->HrtfName
= nullptr;
2456 FreeHrtfList(&device
->HrtfList
);
2457 if(device
->HrtfHandle
)
2458 Hrtf_DecRef(device
->HrtfHandle
);
2459 device
->HrtfHandle
= nullptr;
2460 al_free(device
->Hrtf
);
2461 device
->Hrtf
= nullptr;
2463 al_free(device
->Bs2b
);
2464 device
->Bs2b
= nullptr;
2466 al_free(device
->Uhj_Encoder
);
2467 device
->Uhj_Encoder
= nullptr;
2469 bformatdec_free(&device
->AmbiDecoder
);
2470 ambiup_free(&device
->AmbiUp
);
2472 al_free(device
->Stablizer
);
2473 device
->Stablizer
= nullptr;
2475 al_free(device
->Limiter
);
2476 device
->Limiter
= nullptr;
2478 al_free(device
->ChannelDelay
[0].Buffer
);
2479 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2481 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2482 device
->ChannelDelay
[i
].Length
= 0;
2483 device
->ChannelDelay
[i
].Buffer
= nullptr;
2486 al_free(device
->DeviceName
);
2487 device
->DeviceName
= nullptr;
2489 al_free(device
->Dry
.Buffer
);
2490 device
->Dry
.Buffer
= nullptr;
2491 device
->Dry
.NumChannels
= 0;
2492 device
->FOAOut
.Buffer
= nullptr;
2493 device
->FOAOut
.NumChannels
= 0;
2494 device
->RealOut
.Buffer
= nullptr;
2495 device
->RealOut
.NumChannels
= 0;
2501 void ALCdevice_IncRef(ALCdevice
*device
)
2504 ref
= IncrementRef(&device
->ref
);
2505 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2508 void ALCdevice_DecRef(ALCdevice
*device
)
2511 ref
= DecrementRef(&device
->ref
);
2512 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2513 if(ref
== 0) FreeDevice(device
);
2518 * Checks if the device handle is valid, and increments its ref count if so.
2520 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2522 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2523 ALCdevice
*tmpDevice
{DeviceList
.load()};
2526 if(tmpDevice
== *device
)
2528 ALCdevice_IncRef(tmpDevice
);
2531 tmpDevice
= ATOMIC_LOAD(&tmpDevice
->next
, almemory_order_relaxed
);
2541 * Initializes context fields
2543 static ALvoid
InitContext(ALCcontext
*Context
)
2545 ALlistener
*listener
= Context
->Listener
;
2546 struct ALeffectslotArray
*auxslots
;
2548 //Initialise listener
2549 listener
->Gain
= 1.0f
;
2550 listener
->Position
[0] = 0.0f
;
2551 listener
->Position
[1] = 0.0f
;
2552 listener
->Position
[2] = 0.0f
;
2553 listener
->Velocity
[0] = 0.0f
;
2554 listener
->Velocity
[1] = 0.0f
;
2555 listener
->Velocity
[2] = 0.0f
;
2556 listener
->Forward
[0] = 0.0f
;
2557 listener
->Forward
[1] = 0.0f
;
2558 listener
->Forward
[2] = -1.0f
;
2559 listener
->Up
[0] = 0.0f
;
2560 listener
->Up
[1] = 1.0f
;
2561 listener
->Up
[2] = 0.0f
;
2562 ATOMIC_INIT(&listener
->PropsClean
, AL_TRUE
);
2564 ATOMIC_INIT(&listener
->Update
, static_cast<ALlistenerProps
*>(nullptr));
2567 InitRef(&Context
->UpdateCount
, 0);
2568 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2569 Context
->GainBoost
= 1.0f
;
2570 almtx_init(&Context
->PropLock
, almtx_plain
);
2571 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2572 VECTOR_INIT(Context
->SourceList
);
2573 Context
->NumSources
= 0;
2574 almtx_init(&Context
->SourceLock
, almtx_plain
);
2575 VECTOR_INIT(Context
->EffectSlotList
);
2576 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2578 if(Context
->DefaultSlot
)
2580 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2581 FAM_SIZE(struct ALeffectslotArray
, slot
, 1)));
2582 auxslots
->count
= 1;
2583 auxslots
->slot
[0] = Context
->DefaultSlot
;
2587 auxslots
= static_cast<ALeffectslotArray
*>(al_calloc(DEF_ALIGN
,
2588 sizeof(struct ALeffectslotArray
)));
2589 auxslots
->count
= 0;
2591 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2594 Context
->DistanceModel
= DefaultDistanceModel
;
2595 Context
->SourceDistanceModel
= AL_FALSE
;
2596 Context
->DopplerFactor
= 1.0f
;
2597 Context
->DopplerVelocity
= 1.0f
;
2598 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2599 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2600 ATOMIC_INIT(&Context
->PropsClean
, AL_TRUE
);
2601 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2602 alsem_init(&Context
->EventSem
, 0);
2603 Context
->AsyncEvents
= nullptr;
2604 ATOMIC_INIT(&Context
->EnabledEvts
, 0u);
2605 almtx_init(&Context
->EventCbLock
, almtx_plain
);
2606 Context
->EventCb
= nullptr;
2607 Context
->EventParam
= nullptr;
2609 ATOMIC_INIT(&Context
->Update
, static_cast<ALcontextProps
*>(nullptr));
2610 ATOMIC_INIT(&Context
->FreeContextProps
, static_cast<ALcontextProps
*>(nullptr));
2611 ATOMIC_INIT(&Context
->FreeListenerProps
, static_cast<ALlistenerProps
*>(nullptr));
2612 ATOMIC_INIT(&Context
->FreeVoiceProps
, static_cast<ALvoiceProps
*>(nullptr));
2613 ATOMIC_INIT(&Context
->FreeEffectslotProps
, static_cast<ALeffectslotProps
*>(nullptr));
2615 Context
->ExtensionList
= alExtList
;
2618 listener
->Params
.Matrix
= IdentityMatrixf
;
2619 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2620 listener
->Params
.Gain
= listener
->Gain
;
2621 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2622 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2623 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2624 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2625 listener
->Params
.MetersPerUnit
;
2626 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2627 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2630 Context
->AsyncEvents
= ll_ringbuffer_create(63, sizeof(AsyncEvent
), false);
2631 if(althrd_create(&Context
->EventThread
, EventThread
, Context
) != althrd_success
)
2632 ERR("Failed to start event thread! Expect problems.\n");
2638 * Cleans up the context, and destroys any remaining objects the app failed to
2639 * delete. Called once there's no more references on the context.
2641 static void FreeContext(ALCcontext
*context
)
2643 ALlistener
*listener
= context
->Listener
;
2644 struct ALeffectslotProps
*eprops
;
2645 struct ALlistenerProps
*lprops
;
2646 struct ALcontextProps
*cprops
;
2647 struct ALvoiceProps
*vprops
;
2651 TRACE("%p\n", context
);
2653 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != nullptr)
2655 TRACE("Freed unapplied context update %p\n", cprops
);
2660 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2663 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2668 TRACE("Freed " SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2670 if(context
->DefaultSlot
)
2672 DeinitEffectSlot(context
->DefaultSlot
);
2673 context
->DefaultSlot
= nullptr;
2676 al_free(ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
,
2677 static_cast<ALeffectslotArray
*>(nullptr), almemory_order_relaxed
));
2679 ReleaseALSources(context
);
2680 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2681 VECTOR_FOR_EACH(SourceSubList
, context
->SourceList
, FREE_SOURCESUBLIST
);
2682 #undef FREE_SOURCESUBLIST
2683 VECTOR_DEINIT(context
->SourceList
);
2684 context
->NumSources
= 0;
2685 almtx_destroy(&context
->SourceLock
);
2688 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2691 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2692 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2697 TRACE("Freed " SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2699 ReleaseALAuxiliaryEffectSlots(context
);
2700 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2701 VECTOR_FOR_EACH(ALeffectslotPtr
, context
->EffectSlotList
, FREE_EFFECTSLOTPTR
);
2702 #undef FREE_EFFECTSLOTPTR
2703 VECTOR_DEINIT(context
->EffectSlotList
);
2704 almtx_destroy(&context
->EffectSlotLock
);
2707 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2710 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2715 TRACE("Freed " SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2717 for(i
= 0;i
< context
->VoiceCount
;i
++)
2718 DeinitVoice(context
->Voices
[i
]);
2719 al_free(context
->Voices
);
2720 context
->Voices
= nullptr;
2721 context
->VoiceCount
= 0;
2722 context
->MaxVoices
= 0;
2724 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != nullptr)
2726 TRACE("Freed unapplied listener update %p\n", lprops
);
2730 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2733 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2738 TRACE("Freed " SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2740 almtx_destroy(&context
->EventCbLock
);
2741 alsem_destroy(&context
->EventSem
);
2743 ll_ringbuffer_free(context
->AsyncEvents
);
2744 context
->AsyncEvents
= nullptr;
2746 almtx_destroy(&context
->PropLock
);
2748 ALCdevice_DecRef(context
->Device
);
2749 context
->Device
= nullptr;
2751 //Invalidate context
2752 memset(context
, 0, sizeof(ALCcontext
));
2758 * Removes the context reference from the given device and removes it from
2759 * being current on the running thread or globally. Returns true if other
2760 * contexts still exist on the device.
2762 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2764 static const AsyncEvent kill_evt
= ASYNC_EVENT(EventType_KillThread
);
2765 ALCcontext
*origctx
, *newhead
;
2768 if(altss_get(LocalContext
) == context
)
2770 WARN("%p released while current on thread\n", context
);
2771 altss_set(LocalContext
, nullptr);
2772 ALCcontext_DecRef(context
);
2776 if(GlobalContext
.compare_exchange_strong(origctx
, nullptr))
2777 ALCcontext_DecRef(context
);
2779 V0(device
->Backend
,lock
)();
2781 newhead
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2782 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2786 /* origctx is what the desired context failed to match. Try
2787 * swapping out the next one in the list.
2791 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origctx
, newhead
));
2795 V0(device
->Backend
,unlock
)();
2797 /* Make sure the context is finished and no longer processing in the mixer
2798 * before sending the message queue kill event. The backend's lock does
2799 * this, although waiting for a non-odd mix count would work too.
2802 while(ll_ringbuffer_write(context
->AsyncEvents
, (const char*)&kill_evt
, 1) == 0)
2804 alsem_post(&context
->EventSem
);
2805 althrd_join(context
->EventThread
, nullptr);
2807 ALCcontext_DecRef(context
);
2811 static void ALCcontext_IncRef(ALCcontext
*context
)
2813 uint ref
= IncrementRef(&context
->ref
);
2814 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2817 void ALCcontext_DecRef(ALCcontext
*context
)
2819 uint ref
= DecrementRef(&context
->ref
);
2820 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2821 if(ref
== 0) FreeContext(context
);
2824 static void ReleaseThreadCtx(void *ptr
)
2826 ALCcontext
*context
= static_cast<ALCcontext
*>(ptr
);
2827 uint ref
= DecrementRef(&context
->ref
);
2828 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2829 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2834 * Checks that the given context is valid, and increments its reference count.
2836 static ALCboolean
VerifyContext(ALCcontext
**context
)
2838 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2839 ALCdevice
*dev
{DeviceList
.load()};
2842 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2847 ALCcontext_IncRef(ctx
);
2850 ctx
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
2852 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
2862 * Returns the currently active context for this thread, and adds a reference
2863 * without locking it.
2865 ALCcontext
*GetContextRef(void)
2867 ALCcontext
*context
{static_cast<ALCcontext
*>(altss_get(LocalContext
))};
2869 ALCcontext_IncRef(context
);
2872 std::lock_guard
<std::recursive_mutex
> _
{ListLock
};
2873 context
= GlobalContext
.load(std::memory_order_acquire
);
2874 if(context
) ALCcontext_IncRef(context
);
2881 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2883 ALCdevice
*device
= context
->Device
;
2884 ALsizei num_sends
= device
->NumAuxSends
;
2885 struct ALvoiceProps
*props
;
2886 size_t sizeof_props
;
2887 size_t sizeof_voice
;
2893 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2896 /* Allocate the voice pointers, voices, and the voices' stored source
2897 * property set (including the dynamically-sized Send[] array) in one
2900 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2901 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2902 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2904 voices
= static_cast<ALvoice
**>(al_calloc(16, RoundUp(size
*num_voices
, 16)));
2905 /* The voice and property objects are stored interleaved since they're
2908 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2909 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2913 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2914 const ALsizei s_count
= mini(old_sends
, num_sends
);
2916 for(;v
< v_count
;v
++)
2918 ALvoice
*old_voice
= context
->Voices
[v
];
2921 /* Copy the old voice data and source property set to the new
2924 memcpy(voice
, old_voice
, sizeof(*voice
));
2925 for(i
= 0;i
< s_count
;i
++)
2926 voice
->Send
[i
] = old_voice
->Send
[i
];
2928 memcpy(props
, old_voice
->Props
, sizeof(*props
));
2929 for(i
= 0;i
< s_count
;i
++)
2930 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2932 /* Set this voice's property set pointer and voice reference. */
2933 voice
->Props
= props
;
2936 /* Increment pointers to the next storage space. */
2937 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2938 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2940 /* Deinit any left over voices that weren't copied over to the new
2941 * array. NOTE: If this does anything, v equals num_voices and
2942 * num_voices is less than VoiceCount, so the following loop won't do
2945 for(;v
< context
->VoiceCount
;v
++)
2946 DeinitVoice(context
->Voices
[v
]);
2948 /* Finish setting the voices' property set pointers and references. */
2949 for(;v
< num_voices
;v
++)
2951 ATOMIC_INIT(&voice
->Update
, static_cast<ALvoiceProps
*>(nullptr));
2953 voice
->Props
= props
;
2956 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2957 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2960 al_free(context
->Voices
);
2961 context
->Voices
= voices
;
2962 context
->MaxVoices
= num_voices
;
2963 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2967 /************************************************
2968 * Standard ALC functions
2969 ************************************************/
2973 * Return last ALC generated error code for the given device
2975 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2979 if(VerifyDevice(&device
))
2981 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2982 ALCdevice_DecRef(device
);
2985 errorCode
= LastNullDeviceError
.exchange(ALC_NO_ERROR
);
2991 /* alcSuspendContext
2993 * Suspends updates for the given context
2995 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
3000 if(!VerifyContext(&context
))
3001 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3004 ALCcontext_DeferUpdates(context
);
3005 ALCcontext_DecRef(context
);
3009 /* alcProcessContext
3011 * Resumes processing updates for the given context
3013 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
3018 if(!VerifyContext(&context
))
3019 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3022 ALCcontext_ProcessUpdates(context
);
3023 ALCcontext_DecRef(context
);
3030 * Returns information about the device, and error strings
3032 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
3034 const ALCchar
*value
= nullptr;
3042 case ALC_INVALID_ENUM
:
3043 value
= alcErrInvalidEnum
;
3046 case ALC_INVALID_VALUE
:
3047 value
= alcErrInvalidValue
;
3050 case ALC_INVALID_DEVICE
:
3051 value
= alcErrInvalidDevice
;
3054 case ALC_INVALID_CONTEXT
:
3055 value
= alcErrInvalidContext
;
3058 case ALC_OUT_OF_MEMORY
:
3059 value
= alcErrOutOfMemory
;
3062 case ALC_DEVICE_SPECIFIER
:
3063 value
= alcDefaultName
;
3066 case ALC_ALL_DEVICES_SPECIFIER
:
3067 if(VerifyDevice(&Device
))
3069 value
= Device
->DeviceName
;
3070 ALCdevice_DecRef(Device
);
3074 ProbeAllDevicesList();
3075 value
= alcAllDevicesList
.c_str();
3079 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3080 if(VerifyDevice(&Device
))
3082 value
= Device
->DeviceName
;
3083 ALCdevice_DecRef(Device
);
3087 ProbeCaptureDeviceList();
3088 value
= alcCaptureDeviceList
.c_str();
3092 /* Default devices are always first in the list */
3093 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3094 value
= alcDefaultName
;
3097 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3098 if(alcAllDevicesList
.empty())
3099 ProbeAllDevicesList();
3101 /* Copy first entry as default. */
3102 alcDefaultAllDevicesSpecifier
= alcAllDevicesList
.c_str();
3103 value
= alcDefaultAllDevicesSpecifier
.c_str();
3106 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3107 if(alcCaptureDeviceList
.empty())
3108 ProbeCaptureDeviceList();
3110 /* Copy first entry as default. */
3111 alcCaptureDefaultDeviceSpecifier
= alcCaptureDeviceList
.c_str();
3112 value
= alcCaptureDefaultDeviceSpecifier
.c_str();
3115 case ALC_EXTENSIONS
:
3116 if(!VerifyDevice(&Device
))
3117 value
= alcNoDeviceExtList
;
3120 value
= alcExtensionList
;
3121 ALCdevice_DecRef(Device
);
3125 case ALC_HRTF_SPECIFIER_SOFT
:
3126 if(!VerifyDevice(&Device
))
3127 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3130 almtx_lock(&Device
->BackendLock
);
3131 value
= ((Device
->HrtfHandle
&& Device
->HrtfName
) ? Device
->HrtfName
: "");
3132 almtx_unlock(&Device
->BackendLock
);
3133 ALCdevice_DecRef(Device
);
3138 VerifyDevice(&Device
);
3139 alcSetError(Device
, ALC_INVALID_ENUM
);
3140 if(Device
) ALCdevice_DecRef(Device
);
3148 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3150 if(device
->Type
== Capture
) return 9;
3151 if(device
->Type
!= Loopback
) return 29;
3152 if(device
->FmtChans
== DevFmtAmbi3D
)
3157 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3161 if(size
<= 0 || values
== nullptr)
3163 alcSetError(device
, ALC_INVALID_VALUE
);
3171 case ALC_MAJOR_VERSION
:
3172 values
[0] = alcMajorVersion
;
3174 case ALC_MINOR_VERSION
:
3175 values
[0] = alcMinorVersion
;
3178 case ALC_ATTRIBUTES_SIZE
:
3179 case ALC_ALL_ATTRIBUTES
:
3183 case ALC_MONO_SOURCES
:
3184 case ALC_STEREO_SOURCES
:
3185 case ALC_CAPTURE_SAMPLES
:
3186 case ALC_FORMAT_CHANNELS_SOFT
:
3187 case ALC_FORMAT_TYPE_SOFT
:
3188 case ALC_AMBISONIC_LAYOUT_SOFT
:
3189 case ALC_AMBISONIC_SCALING_SOFT
:
3190 case ALC_AMBISONIC_ORDER_SOFT
:
3191 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3192 alcSetError(nullptr, ALC_INVALID_DEVICE
);
3196 alcSetError(nullptr, ALC_INVALID_ENUM
);
3202 if(device
->Type
== Capture
)
3206 case ALC_ATTRIBUTES_SIZE
:
3207 values
[0] = NumAttrsForDevice(device
);
3210 case ALC_ALL_ATTRIBUTES
:
3211 if(size
< NumAttrsForDevice(device
))
3213 alcSetError(device
, ALC_INVALID_VALUE
);
3218 almtx_lock(&device
->BackendLock
);
3219 values
[i
++] = ALC_MAJOR_VERSION
;
3220 values
[i
++] = alcMajorVersion
;
3221 values
[i
++] = ALC_MINOR_VERSION
;
3222 values
[i
++] = alcMinorVersion
;
3223 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3224 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3225 values
[i
++] = ALC_CONNECTED
;
3226 values
[i
++] = ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
);
3227 almtx_unlock(&device
->BackendLock
);
3232 case ALC_MAJOR_VERSION
:
3233 values
[0] = alcMajorVersion
;
3235 case ALC_MINOR_VERSION
:
3236 values
[0] = alcMinorVersion
;
3239 case ALC_CAPTURE_SAMPLES
:
3240 almtx_lock(&device
->BackendLock
);
3241 values
[0] = V0(device
->Backend
,availableSamples
)();
3242 almtx_unlock(&device
->BackendLock
);
3246 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3250 alcSetError(device
, ALC_INVALID_ENUM
);
3259 case ALC_ATTRIBUTES_SIZE
:
3260 values
[0] = NumAttrsForDevice(device
);
3263 case ALC_ALL_ATTRIBUTES
:
3264 if(size
< NumAttrsForDevice(device
))
3266 alcSetError(device
, ALC_INVALID_VALUE
);
3271 almtx_lock(&device
->BackendLock
);
3272 values
[i
++] = ALC_MAJOR_VERSION
;
3273 values
[i
++] = alcMajorVersion
;
3274 values
[i
++] = ALC_MINOR_VERSION
;
3275 values
[i
++] = alcMinorVersion
;
3276 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3277 values
[i
++] = alcEFXMajorVersion
;
3278 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3279 values
[i
++] = alcEFXMinorVersion
;
3281 values
[i
++] = ALC_FREQUENCY
;
3282 values
[i
++] = device
->Frequency
;
3283 if(device
->Type
!= Loopback
)
3285 values
[i
++] = ALC_REFRESH
;
3286 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3288 values
[i
++] = ALC_SYNC
;
3289 values
[i
++] = ALC_FALSE
;
3293 if(device
->FmtChans
== DevFmtAmbi3D
)
3295 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3296 values
[i
++] = device
->AmbiLayout
;
3298 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3299 values
[i
++] = device
->AmbiScale
;
3301 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3302 values
[i
++] = device
->AmbiOrder
;
3305 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3306 values
[i
++] = device
->FmtChans
;
3308 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3309 values
[i
++] = device
->FmtType
;
3312 values
[i
++] = ALC_MONO_SOURCES
;
3313 values
[i
++] = device
->NumMonoSources
;
3315 values
[i
++] = ALC_STEREO_SOURCES
;
3316 values
[i
++] = device
->NumStereoSources
;
3318 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3319 values
[i
++] = device
->NumAuxSends
;
3321 values
[i
++] = ALC_HRTF_SOFT
;
3322 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3324 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3325 values
[i
++] = device
->HrtfStatus
;
3327 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3328 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3330 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3331 values
[i
++] = MAX_AMBI_ORDER
;
3332 almtx_unlock(&device
->BackendLock
);
3337 case ALC_MAJOR_VERSION
:
3338 values
[0] = alcMajorVersion
;
3341 case ALC_MINOR_VERSION
:
3342 values
[0] = alcMinorVersion
;
3345 case ALC_EFX_MAJOR_VERSION
:
3346 values
[0] = alcEFXMajorVersion
;
3349 case ALC_EFX_MINOR_VERSION
:
3350 values
[0] = alcEFXMinorVersion
;
3354 values
[0] = device
->Frequency
;
3358 if(device
->Type
== Loopback
)
3360 alcSetError(device
, ALC_INVALID_DEVICE
);
3363 almtx_lock(&device
->BackendLock
);
3364 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3365 almtx_unlock(&device
->BackendLock
);
3369 if(device
->Type
== Loopback
)
3371 alcSetError(device
, ALC_INVALID_DEVICE
);
3374 values
[0] = ALC_FALSE
;
3377 case ALC_FORMAT_CHANNELS_SOFT
:
3378 if(device
->Type
!= Loopback
)
3380 alcSetError(device
, ALC_INVALID_DEVICE
);
3383 values
[0] = device
->FmtChans
;
3386 case ALC_FORMAT_TYPE_SOFT
:
3387 if(device
->Type
!= Loopback
)
3389 alcSetError(device
, ALC_INVALID_DEVICE
);
3392 values
[0] = device
->FmtType
;
3395 case ALC_AMBISONIC_LAYOUT_SOFT
:
3396 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3398 alcSetError(device
, ALC_INVALID_DEVICE
);
3401 values
[0] = device
->AmbiLayout
;
3404 case ALC_AMBISONIC_SCALING_SOFT
:
3405 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3407 alcSetError(device
, ALC_INVALID_DEVICE
);
3410 values
[0] = device
->AmbiScale
;
3413 case ALC_AMBISONIC_ORDER_SOFT
:
3414 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3416 alcSetError(device
, ALC_INVALID_DEVICE
);
3419 values
[0] = device
->AmbiOrder
;
3422 case ALC_MONO_SOURCES
:
3423 values
[0] = device
->NumMonoSources
;
3426 case ALC_STEREO_SOURCES
:
3427 values
[0] = device
->NumStereoSources
;
3430 case ALC_MAX_AUXILIARY_SENDS
:
3431 values
[0] = device
->NumAuxSends
;
3435 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3439 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3442 case ALC_HRTF_STATUS_SOFT
:
3443 values
[0] = device
->HrtfStatus
;
3446 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3447 almtx_lock(&device
->BackendLock
);
3448 FreeHrtfList(&device
->HrtfList
);
3449 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3450 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3451 almtx_unlock(&device
->BackendLock
);
3454 case ALC_OUTPUT_LIMITER_SOFT
:
3455 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3458 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3459 values
[0] = MAX_AMBI_ORDER
;
3463 alcSetError(device
, ALC_INVALID_ENUM
);
3471 * Returns information about the device and the version of OpenAL
3473 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3475 VerifyDevice(&device
);
3476 if(size
<= 0 || values
== nullptr)
3477 alcSetError(device
, ALC_INVALID_VALUE
);
3479 GetIntegerv(device
, param
, size
, values
);
3480 if(device
) ALCdevice_DecRef(device
);
3483 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3487 VerifyDevice(&device
);
3488 if(size
<= 0 || values
== nullptr)
3489 alcSetError(device
, ALC_INVALID_VALUE
);
3490 else if(!device
|| device
->Type
== Capture
)
3492 std::vector
<ALCint
> ivals(size
);
3493 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3494 for(i
= 0;i
< size
;i
++)
3495 values
[i
] = ivals
[i
];
3497 else /* render device */
3506 case ALC_ATTRIBUTES_SIZE
:
3507 *values
= NumAttrsForDevice(device
)+4;
3510 case ALC_ALL_ATTRIBUTES
:
3511 if(size
< NumAttrsForDevice(device
)+4)
3512 alcSetError(device
, ALC_INVALID_VALUE
);
3516 almtx_lock(&device
->BackendLock
);
3517 values
[i
++] = ALC_FREQUENCY
;
3518 values
[i
++] = device
->Frequency
;
3520 if(device
->Type
!= Loopback
)
3522 values
[i
++] = ALC_REFRESH
;
3523 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3525 values
[i
++] = ALC_SYNC
;
3526 values
[i
++] = ALC_FALSE
;
3530 if(device
->FmtChans
== DevFmtAmbi3D
)
3532 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3533 values
[i
++] = device
->AmbiLayout
;
3535 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3536 values
[i
++] = device
->AmbiScale
;
3538 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3539 values
[i
++] = device
->AmbiOrder
;
3542 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3543 values
[i
++] = device
->FmtChans
;
3545 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3546 values
[i
++] = device
->FmtType
;
3549 values
[i
++] = ALC_MONO_SOURCES
;
3550 values
[i
++] = device
->NumMonoSources
;
3552 values
[i
++] = ALC_STEREO_SOURCES
;
3553 values
[i
++] = device
->NumStereoSources
;
3555 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3556 values
[i
++] = device
->NumAuxSends
;
3558 values
[i
++] = ALC_HRTF_SOFT
;
3559 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3561 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3562 values
[i
++] = device
->HrtfStatus
;
3564 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3565 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3567 clock
= GetClockLatency(device
);
3568 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3569 values
[i
++] = clock
.ClockTime
;
3571 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3572 values
[i
++] = clock
.Latency
;
3573 almtx_unlock(&device
->BackendLock
);
3579 case ALC_DEVICE_CLOCK_SOFT
:
3580 almtx_lock(&device
->BackendLock
);
3582 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3584 basecount
= device
->ClockBase
;
3585 samplecount
= device
->SamplesDone
;
3586 } while(refcount
!= ReadRef(&device
->MixCount
));
3587 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3588 almtx_unlock(&device
->BackendLock
);
3591 case ALC_DEVICE_LATENCY_SOFT
:
3592 almtx_lock(&device
->BackendLock
);
3593 clock
= GetClockLatency(device
);
3594 almtx_unlock(&device
->BackendLock
);
3595 *values
= clock
.Latency
;
3598 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3600 alcSetError(device
, ALC_INVALID_VALUE
);
3603 almtx_lock(&device
->BackendLock
);
3604 clock
= GetClockLatency(device
);
3605 almtx_unlock(&device
->BackendLock
);
3606 values
[0] = clock
.ClockTime
;
3607 values
[1] = clock
.Latency
;
3612 std::vector
<ALCint
> ivals(size
);
3613 size
= GetIntegerv(device
, pname
, size
, ivals
.data());
3614 for(i
= 0;i
< size
;i
++)
3615 values
[i
] = ivals
[i
];
3620 ALCdevice_DecRef(device
);
3624 /* alcIsExtensionPresent
3626 * Determines if there is support for a particular extension
3628 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3630 ALCboolean bResult
= ALC_FALSE
;
3632 VerifyDevice(&device
);
3635 alcSetError(device
, ALC_INVALID_VALUE
);
3638 size_t len
= strlen(extName
);
3639 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3642 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3643 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3648 if((ptr
=strchr(ptr
, ' ')) != nullptr)
3652 } while(isspace(*ptr
));
3657 ALCdevice_DecRef(device
);
3662 /* alcGetProcAddress
3664 * Retrieves the function address for a particular extension function
3666 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3668 ALCvoid
*ptr
= nullptr;
3672 VerifyDevice(&device
);
3673 alcSetError(device
, ALC_INVALID_VALUE
);
3674 if(device
) ALCdevice_DecRef(device
);
3679 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3681 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3683 ptr
= alcFunctions
[i
].address
;
3695 * Get the value for a particular ALC enumeration name
3697 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3703 VerifyDevice(&device
);
3704 alcSetError(device
, ALC_INVALID_VALUE
);
3705 if(device
) ALCdevice_DecRef(device
);
3710 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3712 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3714 val
= alcEnumerations
[i
].value
;
3726 * Create and attach a context to the given device.
3728 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3730 ALCcontext
*ALContext
;
3734 /* Explicitly hold the list lock while taking the BackendLock in case the
3735 * device is asynchronously destropyed, to ensure this new context is
3736 * properly cleaned up after being made.
3738 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3739 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3740 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
3743 alcSetError(device
, ALC_INVALID_DEVICE
);
3744 if(device
) ALCdevice_DecRef(device
);
3747 almtx_lock(&device
->BackendLock
);
3750 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3752 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3753 ALContext
= static_cast<ALCcontext
*>(al_calloc(16,
3754 sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
)));
3756 ALContext
= static_cast<ALCcontext
*>(al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)));
3759 almtx_unlock(&device
->BackendLock
);
3761 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3762 ALCdevice_DecRef(device
);
3766 InitRef(&ALContext
->ref
, 1);
3767 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3768 ALContext
->DefaultSlot
= nullptr;
3770 ALContext
->Voices
= nullptr;
3771 ALContext
->VoiceCount
= 0;
3772 ALContext
->MaxVoices
= 0;
3773 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, static_cast<ALeffectslotArray
*>(nullptr));
3774 ALContext
->Device
= device
;
3775 ATOMIC_INIT(&ALContext
->next
, static_cast<ALCcontext
*>(nullptr));
3777 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3779 almtx_unlock(&device
->BackendLock
);
3782 ALContext
= nullptr;
3784 alcSetError(device
, err
);
3785 if(err
== ALC_INVALID_DEVICE
)
3787 V0(device
->Backend
,lock
)();
3788 aluHandleDisconnect(device
, "Device update failure");
3789 V0(device
->Backend
,unlock
)();
3791 ALCdevice_DecRef(device
);
3794 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3796 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3798 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3799 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3800 aluInitEffectPanning(ALContext
->DefaultSlot
);
3803 ALContext
->DefaultSlot
= nullptr;
3804 ERR("Failed to initialize the default effect slot\n");
3808 ALCdevice_IncRef(ALContext
->Device
);
3809 InitContext(ALContext
);
3811 if(ConfigValueFloat(device
->DeviceName
, nullptr, "volume-adjust", &valf
))
3813 if(!std::isfinite(valf
))
3814 ERR("volume-adjust must be finite: %f\n", valf
);
3817 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3819 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3820 ALContext
->GainBoost
= std::pow(10.0f
, db
/20.0f
);
3821 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3824 UpdateListenerProps(ALContext
);
3827 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3829 ATOMIC_STORE(&ALContext
->next
, head
, almemory_order_relaxed
);
3830 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3833 almtx_unlock(&device
->BackendLock
);
3835 if(ALContext
->DefaultSlot
)
3837 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3838 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3840 ERR("Failed to initialize the default effect\n");
3843 ALCdevice_DecRef(device
);
3845 TRACE("Created context %p\n", ALContext
);
3849 /* alcDestroyContext
3851 * Remove a context from its device
3853 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3855 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
3856 if(!VerifyContext(&context
))
3859 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3863 ALCdevice
* Device
{context
->Device
};
3866 almtx_lock(&Device
->BackendLock
);
3867 if(!ReleaseContext(context
, Device
))
3869 V0(Device
->Backend
,stop
)();
3870 Device
->Flags
&= ~DEVICE_RUNNING
;
3872 almtx_unlock(&Device
->BackendLock
);
3876 ALCcontext_DecRef(context
);
3880 /* alcGetCurrentContext
3882 * Returns the currently active context on the calling thread
3884 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3886 ALCcontext
*Context
{static_cast<ALCcontext
*>(altss_get(LocalContext
))};
3887 if(!Context
) Context
= GlobalContext
.load();
3891 /* alcGetThreadContext
3893 * Returns the currently active thread-local context
3895 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3897 return static_cast<ALCcontext
*>(altss_get(LocalContext
));
3901 /* alcMakeContextCurrent
3903 * Makes the given context the active process-wide context, and removes the
3904 * thread-local context for the calling thread.
3906 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3908 /* context must be valid or nullptr */
3909 if(context
&& !VerifyContext(&context
))
3911 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3914 /* context's reference count is already incremented */
3915 context
= GlobalContext
.exchange(context
);
3916 if(context
) ALCcontext_DecRef(context
);
3918 if((context
=static_cast<ALCcontext
*>(altss_get(LocalContext
))) != nullptr)
3920 altss_set(LocalContext
, nullptr);
3921 ALCcontext_DecRef(context
);
3927 /* alcSetThreadContext
3929 * Makes the given context the active context for the current thread
3931 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3933 /* context must be valid or nullptr */
3934 if(context
&& !VerifyContext(&context
))
3936 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3939 /* context's reference count is already incremented */
3940 ALCcontext
*old
{static_cast<ALCcontext
*>(altss_get(LocalContext
))};
3941 altss_set(LocalContext
, context
);
3942 if(old
) ALCcontext_DecRef(old
);
3948 /* alcGetContextsDevice
3950 * Returns the device that a particular context is attached to
3952 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3954 if(!VerifyContext(&Context
))
3956 alcSetError(nullptr, ALC_INVALID_CONTEXT
);
3959 ALCdevice
*Device
{Context
->Device
};
3960 ALCcontext_DecRef(Context
);
3968 * Opens the named device.
3970 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3978 if(!PlaybackBackend
.name
)
3980 alcSetError(nullptr, ALC_INVALID_VALUE
);
3984 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3986 /* Some old Windows apps hardcode these expecting OpenAL to use a
3987 * specific audio API, even when they're not enumerated. Creative's
3988 * router effectively ignores them too.
3990 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3991 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3994 deviceName
= nullptr;
3996 device
= static_cast<ALCdevice
*>(al_calloc(16, sizeof(ALCdevice
)));
3999 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4004 InitDevice(device
, Playback
);
4007 device
->FmtChans
= DevFmtChannelsDefault
;
4008 device
->FmtType
= DevFmtTypeDefault
;
4009 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4010 device
->IsHeadphones
= AL_FALSE
;
4011 device
->AmbiLayout
= AmbiLayout_Default
;
4012 device
->AmbiScale
= AmbiNorm_Default
;
4013 device
->LimiterState
= ALC_TRUE
;
4014 device
->NumUpdates
= 3;
4015 device
->UpdateSize
= 1024;
4017 device
->SourcesMax
= 256;
4018 device
->AuxiliaryEffectSlotMax
= 64;
4019 device
->NumAuxSends
= DEFAULT_SENDS
;
4021 if(ConfigValueStr(deviceName
, nullptr, "channels", &fmt
))
4023 static const struct {
4024 const char name
[16];
4025 enum DevFmtChannels chans
;
4028 { "mono", DevFmtMono
, 0 },
4029 { "stereo", DevFmtStereo
, 0 },
4030 { "quad", DevFmtQuad
, 0 },
4031 { "surround51", DevFmtX51
, 0 },
4032 { "surround61", DevFmtX61
, 0 },
4033 { "surround71", DevFmtX71
, 0 },
4034 { "surround51rear", DevFmtX51Rear
, 0 },
4035 { "ambi1", DevFmtAmbi3D
, 1 },
4036 { "ambi2", DevFmtAmbi3D
, 2 },
4037 { "ambi3", DevFmtAmbi3D
, 3 },
4041 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4043 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4045 device
->FmtChans
= chanlist
[i
].chans
;
4046 device
->AmbiOrder
= chanlist
[i
].order
;
4047 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4051 if(i
== COUNTOF(chanlist
))
4052 ERR("Unsupported channels: %s\n", fmt
);
4054 if(ConfigValueStr(deviceName
, nullptr, "sample-type", &fmt
))
4056 static const struct {
4057 const char name
[16];
4058 enum DevFmtType type
;
4060 { "int8", DevFmtByte
},
4061 { "uint8", DevFmtUByte
},
4062 { "int16", DevFmtShort
},
4063 { "uint16", DevFmtUShort
},
4064 { "int32", DevFmtInt
},
4065 { "uint32", DevFmtUInt
},
4066 { "float32", DevFmtFloat
},
4070 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4072 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4074 device
->FmtType
= typelist
[i
].type
;
4075 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4079 if(i
== COUNTOF(typelist
))
4080 ERR("Unsupported sample-type: %s\n", fmt
);
4083 if(ConfigValueUInt(deviceName
, nullptr, "frequency", &device
->Frequency
))
4085 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4086 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4087 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4088 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4091 ConfigValueUInt(deviceName
, nullptr, "periods", &device
->NumUpdates
);
4092 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4094 ConfigValueUInt(deviceName
, nullptr, "period_size", &device
->UpdateSize
);
4095 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4096 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4097 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4099 ConfigValueUInt(deviceName
, nullptr, "sources", &device
->SourcesMax
);
4100 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4102 ConfigValueUInt(deviceName
, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4103 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4104 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4106 if(ConfigValueInt(deviceName
, nullptr, "sends", &device
->NumAuxSends
))
4107 device
->NumAuxSends
= clampi(
4108 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4111 device
->NumStereoSources
= 1;
4112 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4114 device
->Backend
= PlaybackBackend
.getFactory().createBackend(device
, ALCbackend_Playback
);
4115 if(!device
->Backend
)
4118 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4122 // Find a playback device to open
4123 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4126 alcSetError(nullptr, err
);
4130 if(ConfigValueStr(device
->DeviceName
, nullptr, "ambi-format", &fmt
))
4132 if(strcasecmp(fmt
, "fuma") == 0)
4134 device
->AmbiLayout
= AmbiLayout_FuMa
;
4135 device
->AmbiScale
= AmbiNorm_FuMa
;
4137 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4139 device
->AmbiLayout
= AmbiLayout_ACN
;
4140 device
->AmbiScale
= AmbiNorm_SN3D
;
4142 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4144 device
->AmbiLayout
= AmbiLayout_ACN
;
4145 device
->AmbiScale
= AmbiNorm_N3D
;
4148 ERR("Unsupported ambi-format: %s\n", fmt
);
4152 ALCdevice
*head
{DeviceList
.load()};
4154 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4155 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4158 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
4164 * Closes the given device.
4166 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4168 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4169 ALCdevice
*iter
{DeviceList
.load()};
4173 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4174 } while(iter
!= nullptr);
4175 if(!iter
|| iter
->Type
== Capture
)
4177 alcSetError(iter
, ALC_INVALID_DEVICE
);
4180 almtx_lock(&device
->BackendLock
);
4182 ALCdevice
*origdev
{device
};
4183 ALCdevice
*nextdev
{ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
)};
4184 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4190 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4194 ALCcontext
*ctx
{ATOMIC_LOAD_SEQ(&device
->ContextList
)};
4195 while(ctx
!= nullptr)
4197 ALCcontext
*next
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
4198 WARN("Releasing context %p\n", ctx
);
4199 ReleaseContext(ctx
, device
);
4202 if((device
->Flags
&DEVICE_RUNNING
))
4203 V0(device
->Backend
,stop
)();
4204 device
->Flags
&= ~DEVICE_RUNNING
;
4205 almtx_unlock(&device
->BackendLock
);
4207 ALCdevice_DecRef(device
);
4213 /************************************************
4214 * ALC capture functions
4215 ************************************************/
4216 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4218 ALCdevice
*device
= nullptr;
4223 if(!CaptureBackend
.name
)
4225 alcSetError(nullptr, ALC_INVALID_VALUE
);
4231 alcSetError(nullptr, ALC_INVALID_VALUE
);
4235 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4236 deviceName
= nullptr;
4238 device
= static_cast<ALCdevice
*>(al_calloc(16, sizeof(ALCdevice
)));
4241 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4246 InitDevice(device
, Capture
);
4248 device
->Frequency
= frequency
;
4249 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4251 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4254 alcSetError(nullptr, ALC_INVALID_ENUM
);
4257 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4258 device
->IsHeadphones
= AL_FALSE
;
4259 device
->AmbiOrder
= 0;
4260 device
->AmbiLayout
= AmbiLayout_Default
;
4261 device
->AmbiScale
= AmbiNorm_Default
;
4263 device
->UpdateSize
= samples
;
4264 device
->NumUpdates
= 1;
4266 device
->Backend
= CaptureBackend
.getFactory().createBackend(device
, ALCbackend_Capture
);
4267 if(!device
->Backend
)
4270 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4274 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4275 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4276 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4278 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4281 alcSetError(nullptr, err
);
4286 ALCdevice
*head
{DeviceList
.load()};
4288 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4289 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4292 TRACE("Created device %p, \"%s\"\n", device
, device
->DeviceName
);
4296 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4298 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4300 ALCdevice
*iter
{DeviceList
.load()};
4304 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4305 } while(iter
!= nullptr);
4306 if(!iter
|| iter
->Type
!= Capture
)
4308 alcSetError(iter
, ALC_INVALID_DEVICE
);
4312 ALCdevice
*origdev
{device
};
4313 ALCdevice
*nextdev
{ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
)};
4314 if(!DeviceList
.compare_exchange_strong(origdev
, nextdev
))
4320 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4324 almtx_lock(&device
->BackendLock
);
4325 if((device
->Flags
&DEVICE_RUNNING
))
4326 V0(device
->Backend
,stop
)();
4327 device
->Flags
&= ~DEVICE_RUNNING
;
4328 almtx_unlock(&device
->BackendLock
);
4330 ALCdevice_DecRef(device
);
4335 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4337 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4338 alcSetError(device
, ALC_INVALID_DEVICE
);
4341 almtx_lock(&device
->BackendLock
);
4342 if(!ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
))
4343 alcSetError(device
, ALC_INVALID_DEVICE
);
4344 else if(!(device
->Flags
&DEVICE_RUNNING
))
4346 if(V0(device
->Backend
,start
)())
4347 device
->Flags
|= DEVICE_RUNNING
;
4350 aluHandleDisconnect(device
, "Device start failure");
4351 alcSetError(device
, ALC_INVALID_DEVICE
);
4354 almtx_unlock(&device
->BackendLock
);
4357 if(device
) ALCdevice_DecRef(device
);
4360 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4362 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4363 alcSetError(device
, ALC_INVALID_DEVICE
);
4366 almtx_lock(&device
->BackendLock
);
4367 if((device
->Flags
&DEVICE_RUNNING
))
4368 V0(device
->Backend
,stop
)();
4369 device
->Flags
&= ~DEVICE_RUNNING
;
4370 almtx_unlock(&device
->BackendLock
);
4373 if(device
) ALCdevice_DecRef(device
);
4376 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4378 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4379 alcSetError(device
, ALC_INVALID_DEVICE
);
4382 ALCenum err
= ALC_INVALID_VALUE
;
4384 almtx_lock(&device
->BackendLock
);
4385 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4386 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4387 almtx_unlock(&device
->BackendLock
);
4389 if(err
!= ALC_NO_ERROR
)
4390 alcSetError(device
, err
);
4392 if(device
) ALCdevice_DecRef(device
);
4396 /************************************************
4397 * ALC loopback functions
4398 ************************************************/
4400 /* alcLoopbackOpenDeviceSOFT
4402 * Open a loopback device, for manual rendering.
4404 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4408 /* Make sure the device name, if specified, is us. */
4409 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4411 alcSetError(nullptr, ALC_INVALID_VALUE
);
4415 ALCdevice
*device
{static_cast<ALCdevice
*>(al_calloc(16, sizeof(ALCdevice
)))};
4418 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4423 InitDevice(device
, Loopback
);
4425 device
->SourcesMax
= 256;
4426 device
->AuxiliaryEffectSlotMax
= 64;
4427 device
->NumAuxSends
= DEFAULT_SENDS
;
4430 device
->NumUpdates
= 0;
4431 device
->UpdateSize
= 0;
4433 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4434 device
->FmtChans
= DevFmtChannelsDefault
;
4435 device
->FmtType
= DevFmtTypeDefault
;
4436 device
->IsHeadphones
= AL_FALSE
;
4437 device
->AmbiLayout
= AmbiLayout_Default
;
4438 device
->AmbiScale
= AmbiNorm_Default
;
4440 ConfigValueUInt(nullptr, nullptr, "sources", &device
->SourcesMax
);
4441 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4443 ConfigValueUInt(nullptr, nullptr, "slots", &device
->AuxiliaryEffectSlotMax
);
4444 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4445 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4447 if(ConfigValueInt(nullptr, nullptr, "sends", &device
->NumAuxSends
))
4448 device
->NumAuxSends
= clampi(
4449 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4452 device
->NumStereoSources
= 1;
4453 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4455 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
4456 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4457 if(!device
->Backend
)
4460 alcSetError(nullptr, ALC_OUT_OF_MEMORY
);
4464 // Open the "backend"
4465 V(device
->Backend
,open
)("Loopback");
4468 ALCdevice
*head
{DeviceList
.load()};
4470 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4471 } while(!DeviceList
.compare_exchange_weak(head
, device
));
4474 TRACE("Created device %p\n", device
);
4478 /* alcIsRenderFormatSupportedSOFT
4480 * Determines if the loopback device supports the given format for rendering.
4482 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4484 ALCboolean ret
= ALC_FALSE
;
4486 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4487 alcSetError(device
, ALC_INVALID_DEVICE
);
4489 alcSetError(device
, ALC_INVALID_VALUE
);
4492 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4495 if(device
) ALCdevice_DecRef(device
);
4500 /* alcRenderSamplesSOFT
4502 * Renders some samples into a buffer, using the format last set by the
4503 * attributes given to alcCreateContext.
4505 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4507 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4508 alcSetError(device
, ALC_INVALID_DEVICE
);
4509 else if(samples
< 0 || (samples
> 0 && buffer
== nullptr))
4510 alcSetError(device
, ALC_INVALID_VALUE
);
4513 V0(device
->Backend
,lock
)();
4514 aluMixData(device
, buffer
, samples
);
4515 V0(device
->Backend
,unlock
)();
4517 if(device
) ALCdevice_DecRef(device
);
4521 /************************************************
4522 * ALC DSP pause/resume functions
4523 ************************************************/
4525 /* alcDevicePauseSOFT
4527 * Pause the DSP to stop audio processing.
4529 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4531 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4532 alcSetError(device
, ALC_INVALID_DEVICE
);
4535 almtx_lock(&device
->BackendLock
);
4536 if((device
->Flags
&DEVICE_RUNNING
))
4537 V0(device
->Backend
,stop
)();
4538 device
->Flags
&= ~DEVICE_RUNNING
;
4539 device
->Flags
|= DEVICE_PAUSED
;
4540 almtx_unlock(&device
->BackendLock
);
4542 if(device
) ALCdevice_DecRef(device
);
4545 /* alcDeviceResumeSOFT
4547 * Resume the DSP to restart audio processing.
4549 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4551 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4552 alcSetError(device
, ALC_INVALID_DEVICE
);
4555 almtx_lock(&device
->BackendLock
);
4556 if((device
->Flags
&DEVICE_PAUSED
))
4558 device
->Flags
&= ~DEVICE_PAUSED
;
4559 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != nullptr)
4561 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4562 device
->Flags
|= DEVICE_RUNNING
;
4565 V0(device
->Backend
,lock
)();
4566 aluHandleDisconnect(device
, "Device start failure");
4567 V0(device
->Backend
,unlock
)();
4568 alcSetError(device
, ALC_INVALID_DEVICE
);
4572 almtx_unlock(&device
->BackendLock
);
4574 if(device
) ALCdevice_DecRef(device
);
4578 /************************************************
4579 * ALC HRTF functions
4580 ************************************************/
4582 /* alcGetStringiSOFT
4584 * Gets a string parameter at the given index.
4586 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4588 const ALCchar
*str
= nullptr;
4590 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4591 alcSetError(device
, ALC_INVALID_DEVICE
);
4592 else switch(paramName
)
4594 case ALC_HRTF_SPECIFIER_SOFT
:
4595 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4596 str
= VECTOR_ELEM(device
->HrtfList
, index
).name
;
4598 alcSetError(device
, ALC_INVALID_VALUE
);
4602 alcSetError(device
, ALC_INVALID_ENUM
);
4605 if(device
) ALCdevice_DecRef(device
);
4610 /* alcResetDeviceSOFT
4612 * Resets the given device output, using the specified attribute list.
4614 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4618 std::unique_lock
<std::recursive_mutex
> listlock
{ListLock
};
4619 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4620 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
4623 alcSetError(device
, ALC_INVALID_DEVICE
);
4624 if(device
) ALCdevice_DecRef(device
);
4627 almtx_lock(&device
->BackendLock
);
4630 err
= UpdateDeviceParams(device
, attribs
);
4631 almtx_unlock(&device
->BackendLock
);
4633 if(err
!= ALC_NO_ERROR
)
4635 alcSetError(device
, err
);
4636 if(err
== ALC_INVALID_DEVICE
)
4638 V0(device
->Backend
,lock
)();
4639 aluHandleDisconnect(device
, "Device start failure");
4640 V0(device
->Backend
,unlock
)();
4642 ALCdevice_DecRef(device
);
4645 ALCdevice_DecRef(device
);