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
34 #include "alListener.h"
37 #include "alAuxEffectSlot.h"
39 #include "mastering.h"
40 #include "bformatdec.h"
43 #include "ringbuffer.h"
45 #include "fpu_modes.h"
52 #include "backends/base.h"
55 /************************************************
57 ************************************************/
60 ALCbackendFactory
* (*getFactory
)(void);
63 static struct BackendInfo BackendList
[] = {
65 { "jack", ALCjackBackendFactory_getFactory
},
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory
},
71 { "alsa", ALCalsaBackendFactory_getFactory
},
74 { "core", ALCcoreAudioBackendFactory_getFactory
},
77 { "oss", ALCossBackendFactory_getFactory
},
80 { "solaris", ALCsolarisBackendFactory_getFactory
},
83 { "sndio", ALCsndioBackendFactory_getFactory
},
86 { "qsa", ALCqsaBackendFactory_getFactory
},
89 { "wasapi", ALCwasapiBackendFactory_getFactory
},
92 { "dsound", ALCdsoundBackendFactory_getFactory
},
95 { "winmm", ALCwinmmBackendFactory_getFactory
},
98 { "port", ALCportBackendFactory_getFactory
},
101 { "opensl", ALCopenslBackendFactory_getFactory
},
104 { "sdl2", ALCsdl2BackendFactory_getFactory
},
107 { "null", ALCnullBackendFactory_getFactory
},
109 { "wave", ALCwaveBackendFactory_getFactory
},
112 static ALsizei BackendListSize
= COUNTOF(BackendList
);
115 static struct BackendInfo PlaybackBackend
;
116 static struct BackendInfo CaptureBackend
;
119 /************************************************
120 * Functions, enums, and errors
121 ************************************************/
122 #define DECL(x) { #x, (ALCvoid*)(x) }
123 static const struct {
124 const ALCchar
*funcName
;
127 DECL(alcCreateContext
),
128 DECL(alcMakeContextCurrent
),
129 DECL(alcProcessContext
),
130 DECL(alcSuspendContext
),
131 DECL(alcDestroyContext
),
132 DECL(alcGetCurrentContext
),
133 DECL(alcGetContextsDevice
),
135 DECL(alcCloseDevice
),
137 DECL(alcIsExtensionPresent
),
138 DECL(alcGetProcAddress
),
139 DECL(alcGetEnumValue
),
141 DECL(alcGetIntegerv
),
142 DECL(alcCaptureOpenDevice
),
143 DECL(alcCaptureCloseDevice
),
144 DECL(alcCaptureStart
),
145 DECL(alcCaptureStop
),
146 DECL(alcCaptureSamples
),
148 DECL(alcSetThreadContext
),
149 DECL(alcGetThreadContext
),
151 DECL(alcLoopbackOpenDeviceSOFT
),
152 DECL(alcIsRenderFormatSupportedSOFT
),
153 DECL(alcRenderSamplesSOFT
),
155 DECL(alcDevicePauseSOFT
),
156 DECL(alcDeviceResumeSOFT
),
158 DECL(alcGetStringiSOFT
),
159 DECL(alcResetDeviceSOFT
),
161 DECL(alcGetInteger64vSOFT
),
176 DECL(alIsExtensionPresent
),
177 DECL(alGetProcAddress
),
178 DECL(alGetEnumValue
),
185 DECL(alGetListenerf
),
186 DECL(alGetListener3f
),
187 DECL(alGetListenerfv
),
188 DECL(alGetListeneri
),
189 DECL(alGetListener3i
),
190 DECL(alGetListeneriv
),
192 DECL(alDeleteSources
),
208 DECL(alSourceRewindv
),
209 DECL(alSourcePausev
),
212 DECL(alSourceRewind
),
214 DECL(alSourceQueueBuffers
),
215 DECL(alSourceUnqueueBuffers
),
217 DECL(alDeleteBuffers
),
232 DECL(alDopplerFactor
),
233 DECL(alDopplerVelocity
),
234 DECL(alSpeedOfSound
),
235 DECL(alDistanceModel
),
238 DECL(alDeleteFilters
),
249 DECL(alDeleteEffects
),
259 DECL(alGenAuxiliaryEffectSlots
),
260 DECL(alDeleteAuxiliaryEffectSlots
),
261 DECL(alIsAuxiliaryEffectSlot
),
262 DECL(alAuxiliaryEffectSloti
),
263 DECL(alAuxiliaryEffectSlotiv
),
264 DECL(alAuxiliaryEffectSlotf
),
265 DECL(alAuxiliaryEffectSlotfv
),
266 DECL(alGetAuxiliaryEffectSloti
),
267 DECL(alGetAuxiliaryEffectSlotiv
),
268 DECL(alGetAuxiliaryEffectSlotf
),
269 DECL(alGetAuxiliaryEffectSlotfv
),
271 DECL(alDeferUpdatesSOFT
),
272 DECL(alProcessUpdatesSOFT
),
275 DECL(alSource3dSOFT
),
276 DECL(alSourcedvSOFT
),
277 DECL(alGetSourcedSOFT
),
278 DECL(alGetSource3dSOFT
),
279 DECL(alGetSourcedvSOFT
),
280 DECL(alSourcei64SOFT
),
281 DECL(alSource3i64SOFT
),
282 DECL(alSourcei64vSOFT
),
283 DECL(alGetSourcei64SOFT
),
284 DECL(alGetSource3i64SOFT
),
285 DECL(alGetSourcei64vSOFT
),
287 DECL(alGetStringiSOFT
),
289 DECL(alBufferStorageSOFT
),
290 DECL(alMapBufferSOFT
),
291 DECL(alUnmapBufferSOFT
),
292 DECL(alFlushMappedBufferSOFT
),
294 DECL(alEventControlSOFT
),
295 DECL(alEventCallbackSOFT
),
296 DECL(alGetPointerSOFT
),
297 DECL(alGetPointervSOFT
),
301 #define DECL(x) { #x, (x) }
302 static const struct {
303 const ALCchar
*enumName
;
305 } alcEnumerations
[] = {
310 DECL(ALC_MAJOR_VERSION
),
311 DECL(ALC_MINOR_VERSION
),
312 DECL(ALC_ATTRIBUTES_SIZE
),
313 DECL(ALC_ALL_ATTRIBUTES
),
314 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
315 DECL(ALC_DEVICE_SPECIFIER
),
316 DECL(ALC_ALL_DEVICES_SPECIFIER
),
317 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
318 DECL(ALC_EXTENSIONS
),
322 DECL(ALC_MONO_SOURCES
),
323 DECL(ALC_STEREO_SOURCES
),
324 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
325 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
326 DECL(ALC_CAPTURE_SAMPLES
),
329 DECL(ALC_EFX_MAJOR_VERSION
),
330 DECL(ALC_EFX_MINOR_VERSION
),
331 DECL(ALC_MAX_AUXILIARY_SENDS
),
333 DECL(ALC_FORMAT_CHANNELS_SOFT
),
334 DECL(ALC_FORMAT_TYPE_SOFT
),
337 DECL(ALC_STEREO_SOFT
),
339 DECL(ALC_5POINT1_SOFT
),
340 DECL(ALC_6POINT1_SOFT
),
341 DECL(ALC_7POINT1_SOFT
),
342 DECL(ALC_BFORMAT3D_SOFT
),
345 DECL(ALC_UNSIGNED_BYTE_SOFT
),
346 DECL(ALC_SHORT_SOFT
),
347 DECL(ALC_UNSIGNED_SHORT_SOFT
),
349 DECL(ALC_UNSIGNED_INT_SOFT
),
350 DECL(ALC_FLOAT_SOFT
),
353 DECL(ALC_DONT_CARE_SOFT
),
354 DECL(ALC_HRTF_STATUS_SOFT
),
355 DECL(ALC_HRTF_DISABLED_SOFT
),
356 DECL(ALC_HRTF_ENABLED_SOFT
),
357 DECL(ALC_HRTF_DENIED_SOFT
),
358 DECL(ALC_HRTF_REQUIRED_SOFT
),
359 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
360 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
361 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
362 DECL(ALC_HRTF_SPECIFIER_SOFT
),
363 DECL(ALC_HRTF_ID_SOFT
),
365 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
366 DECL(ALC_AMBISONIC_SCALING_SOFT
),
367 DECL(ALC_AMBISONIC_ORDER_SOFT
),
373 DECL(ALC_OUTPUT_LIMITER_SOFT
),
376 DECL(ALC_INVALID_DEVICE
),
377 DECL(ALC_INVALID_CONTEXT
),
378 DECL(ALC_INVALID_ENUM
),
379 DECL(ALC_INVALID_VALUE
),
380 DECL(ALC_OUT_OF_MEMORY
),
388 DECL(AL_SOURCE_RELATIVE
),
389 DECL(AL_CONE_INNER_ANGLE
),
390 DECL(AL_CONE_OUTER_ANGLE
),
400 DECL(AL_ORIENTATION
),
401 DECL(AL_REFERENCE_DISTANCE
),
402 DECL(AL_ROLLOFF_FACTOR
),
403 DECL(AL_CONE_OUTER_GAIN
),
404 DECL(AL_MAX_DISTANCE
),
406 DECL(AL_SAMPLE_OFFSET
),
407 DECL(AL_BYTE_OFFSET
),
408 DECL(AL_SOURCE_TYPE
),
411 DECL(AL_UNDETERMINED
),
412 DECL(AL_METERS_PER_UNIT
),
413 DECL(AL_LOOP_POINTS_SOFT
),
414 DECL(AL_DIRECT_CHANNELS_SOFT
),
416 DECL(AL_DIRECT_FILTER
),
417 DECL(AL_AUXILIARY_SEND_FILTER
),
418 DECL(AL_AIR_ABSORPTION_FACTOR
),
419 DECL(AL_ROOM_ROLLOFF_FACTOR
),
420 DECL(AL_CONE_OUTER_GAINHF
),
421 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
422 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
423 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
425 DECL(AL_SOURCE_STATE
),
431 DECL(AL_BUFFERS_QUEUED
),
432 DECL(AL_BUFFERS_PROCESSED
),
434 DECL(AL_FORMAT_MONO8
),
435 DECL(AL_FORMAT_MONO16
),
436 DECL(AL_FORMAT_MONO_FLOAT32
),
437 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
438 DECL(AL_FORMAT_STEREO8
),
439 DECL(AL_FORMAT_STEREO16
),
440 DECL(AL_FORMAT_STEREO_FLOAT32
),
441 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
442 DECL(AL_FORMAT_MONO_IMA4
),
443 DECL(AL_FORMAT_STEREO_IMA4
),
444 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
445 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
446 DECL(AL_FORMAT_QUAD8_LOKI
),
447 DECL(AL_FORMAT_QUAD16_LOKI
),
448 DECL(AL_FORMAT_QUAD8
),
449 DECL(AL_FORMAT_QUAD16
),
450 DECL(AL_FORMAT_QUAD32
),
451 DECL(AL_FORMAT_51CHN8
),
452 DECL(AL_FORMAT_51CHN16
),
453 DECL(AL_FORMAT_51CHN32
),
454 DECL(AL_FORMAT_61CHN8
),
455 DECL(AL_FORMAT_61CHN16
),
456 DECL(AL_FORMAT_61CHN32
),
457 DECL(AL_FORMAT_71CHN8
),
458 DECL(AL_FORMAT_71CHN16
),
459 DECL(AL_FORMAT_71CHN32
),
460 DECL(AL_FORMAT_REAR8
),
461 DECL(AL_FORMAT_REAR16
),
462 DECL(AL_FORMAT_REAR32
),
463 DECL(AL_FORMAT_MONO_MULAW
),
464 DECL(AL_FORMAT_MONO_MULAW_EXT
),
465 DECL(AL_FORMAT_STEREO_MULAW
),
466 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
467 DECL(AL_FORMAT_QUAD_MULAW
),
468 DECL(AL_FORMAT_51CHN_MULAW
),
469 DECL(AL_FORMAT_61CHN_MULAW
),
470 DECL(AL_FORMAT_71CHN_MULAW
),
471 DECL(AL_FORMAT_REAR_MULAW
),
472 DECL(AL_FORMAT_MONO_ALAW_EXT
),
473 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
475 DECL(AL_FORMAT_BFORMAT2D_8
),
476 DECL(AL_FORMAT_BFORMAT2D_16
),
477 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
478 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
479 DECL(AL_FORMAT_BFORMAT3D_8
),
480 DECL(AL_FORMAT_BFORMAT3D_16
),
481 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
482 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
488 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
489 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
491 DECL(AL_SOURCE_RADIUS
),
493 DECL(AL_STEREO_ANGLES
),
500 DECL(AL_INVALID_NAME
),
501 DECL(AL_INVALID_ENUM
),
502 DECL(AL_INVALID_VALUE
),
503 DECL(AL_INVALID_OPERATION
),
504 DECL(AL_OUT_OF_MEMORY
),
511 DECL(AL_DOPPLER_FACTOR
),
512 DECL(AL_DOPPLER_VELOCITY
),
513 DECL(AL_DISTANCE_MODEL
),
514 DECL(AL_SPEED_OF_SOUND
),
515 DECL(AL_SOURCE_DISTANCE_MODEL
),
516 DECL(AL_DEFERRED_UPDATES_SOFT
),
517 DECL(AL_GAIN_LIMIT_SOFT
),
519 DECL(AL_INVERSE_DISTANCE
),
520 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
521 DECL(AL_LINEAR_DISTANCE
),
522 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
523 DECL(AL_EXPONENT_DISTANCE
),
524 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
526 DECL(AL_FILTER_TYPE
),
527 DECL(AL_FILTER_NULL
),
528 DECL(AL_FILTER_LOWPASS
),
529 DECL(AL_FILTER_HIGHPASS
),
530 DECL(AL_FILTER_BANDPASS
),
532 DECL(AL_LOWPASS_GAIN
),
533 DECL(AL_LOWPASS_GAINHF
),
535 DECL(AL_HIGHPASS_GAIN
),
536 DECL(AL_HIGHPASS_GAINLF
),
538 DECL(AL_BANDPASS_GAIN
),
539 DECL(AL_BANDPASS_GAINHF
),
540 DECL(AL_BANDPASS_GAINLF
),
542 DECL(AL_EFFECT_TYPE
),
543 DECL(AL_EFFECT_NULL
),
544 DECL(AL_EFFECT_REVERB
),
545 DECL(AL_EFFECT_EAXREVERB
),
546 DECL(AL_EFFECT_CHORUS
),
547 DECL(AL_EFFECT_DISTORTION
),
548 DECL(AL_EFFECT_ECHO
),
549 DECL(AL_EFFECT_FLANGER
),
551 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
552 DECL(AL_EFFECT_VOCAL_MORPHER
),
553 DECL(AL_EFFECT_PITCH_SHIFTER
),
555 DECL(AL_EFFECT_RING_MODULATOR
),
557 DECL(AL_EFFECT_AUTOWAH
),
559 DECL(AL_EFFECT_COMPRESSOR
),
560 DECL(AL_EFFECT_EQUALIZER
),
561 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
562 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
564 DECL(AL_EFFECTSLOT_EFFECT
),
565 DECL(AL_EFFECTSLOT_GAIN
),
566 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
567 DECL(AL_EFFECTSLOT_NULL
),
569 DECL(AL_EAXREVERB_DENSITY
),
570 DECL(AL_EAXREVERB_DIFFUSION
),
571 DECL(AL_EAXREVERB_GAIN
),
572 DECL(AL_EAXREVERB_GAINHF
),
573 DECL(AL_EAXREVERB_GAINLF
),
574 DECL(AL_EAXREVERB_DECAY_TIME
),
575 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
576 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
577 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
578 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
579 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
580 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
581 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
582 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
583 DECL(AL_EAXREVERB_ECHO_TIME
),
584 DECL(AL_EAXREVERB_ECHO_DEPTH
),
585 DECL(AL_EAXREVERB_MODULATION_TIME
),
586 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
587 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
588 DECL(AL_EAXREVERB_HFREFERENCE
),
589 DECL(AL_EAXREVERB_LFREFERENCE
),
590 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
591 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
593 DECL(AL_REVERB_DENSITY
),
594 DECL(AL_REVERB_DIFFUSION
),
595 DECL(AL_REVERB_GAIN
),
596 DECL(AL_REVERB_GAINHF
),
597 DECL(AL_REVERB_DECAY_TIME
),
598 DECL(AL_REVERB_DECAY_HFRATIO
),
599 DECL(AL_REVERB_REFLECTIONS_GAIN
),
600 DECL(AL_REVERB_REFLECTIONS_DELAY
),
601 DECL(AL_REVERB_LATE_REVERB_GAIN
),
602 DECL(AL_REVERB_LATE_REVERB_DELAY
),
603 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
604 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
605 DECL(AL_REVERB_DECAY_HFLIMIT
),
607 DECL(AL_CHORUS_WAVEFORM
),
608 DECL(AL_CHORUS_PHASE
),
609 DECL(AL_CHORUS_RATE
),
610 DECL(AL_CHORUS_DEPTH
),
611 DECL(AL_CHORUS_FEEDBACK
),
612 DECL(AL_CHORUS_DELAY
),
614 DECL(AL_DISTORTION_EDGE
),
615 DECL(AL_DISTORTION_GAIN
),
616 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
617 DECL(AL_DISTORTION_EQCENTER
),
618 DECL(AL_DISTORTION_EQBANDWIDTH
),
621 DECL(AL_ECHO_LRDELAY
),
622 DECL(AL_ECHO_DAMPING
),
623 DECL(AL_ECHO_FEEDBACK
),
624 DECL(AL_ECHO_SPREAD
),
626 DECL(AL_FLANGER_WAVEFORM
),
627 DECL(AL_FLANGER_PHASE
),
628 DECL(AL_FLANGER_RATE
),
629 DECL(AL_FLANGER_DEPTH
),
630 DECL(AL_FLANGER_FEEDBACK
),
631 DECL(AL_FLANGER_DELAY
),
633 DECL(AL_RING_MODULATOR_FREQUENCY
),
634 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
635 DECL(AL_RING_MODULATOR_WAVEFORM
),
637 DECL(AL_COMPRESSOR_ONOFF
),
639 DECL(AL_EQUALIZER_LOW_GAIN
),
640 DECL(AL_EQUALIZER_LOW_CUTOFF
),
641 DECL(AL_EQUALIZER_MID1_GAIN
),
642 DECL(AL_EQUALIZER_MID1_CENTER
),
643 DECL(AL_EQUALIZER_MID1_WIDTH
),
644 DECL(AL_EQUALIZER_MID2_GAIN
),
645 DECL(AL_EQUALIZER_MID2_CENTER
),
646 DECL(AL_EQUALIZER_MID2_WIDTH
),
647 DECL(AL_EQUALIZER_HIGH_GAIN
),
648 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
650 DECL(AL_DEDICATED_GAIN
),
652 DECL(AL_NUM_RESAMPLERS_SOFT
),
653 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
654 DECL(AL_SOURCE_RESAMPLER_SOFT
),
655 DECL(AL_RESAMPLER_NAME_SOFT
),
657 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
660 DECL(AL_MAP_READ_BIT_SOFT
),
661 DECL(AL_MAP_WRITE_BIT_SOFT
),
662 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
663 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
665 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
666 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
667 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
668 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
669 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
670 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
671 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
675 static const ALCchar alcNoError
[] = "No Error";
676 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
677 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
678 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
679 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
680 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
683 /************************************************
685 ************************************************/
687 /* Enumerated device names */
688 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
690 static al_string alcAllDevicesList
;
691 static al_string alcCaptureDeviceList
;
693 /* Default is always the first in the list */
694 static ALCchar
*alcDefaultAllDevicesSpecifier
;
695 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
697 /* Default context extensions */
698 static const ALchar alExtList
[] =
702 "AL_EXT_EXPONENT_DISTANCE "
705 "AL_EXT_LINEAR_DISTANCE "
708 "AL_EXT_MULAW_BFORMAT "
709 "AL_EXT_MULAW_MCFORMATS "
711 "AL_EXT_source_distance_model "
712 "AL_EXT_SOURCE_RADIUS "
713 "AL_EXT_STEREO_ANGLES "
714 "AL_LOKI_quadriphonic "
715 "AL_SOFT_block_alignment "
716 "AL_SOFT_deferred_updates "
717 "AL_SOFT_direct_channels "
719 "AL_SOFT_gain_clamp_ex "
720 "AL_SOFT_loop_points "
721 "AL_SOFTX_map_buffer "
723 "AL_SOFT_source_latency "
724 "AL_SOFT_source_length "
725 "AL_SOFT_source_resampler "
726 "AL_SOFT_source_spatialize";
728 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
730 /* Thread-local current context */
731 static altss_t LocalContext
;
732 /* Process-wide current context */
733 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
735 /* Mixing thread piority level */
740 enum LogLevel LogLevel
= LogWarning
;
742 enum LogLevel LogLevel
= LogError
;
745 /* Flag to trap ALC device errors */
746 static ALCboolean TrapALCError
= ALC_FALSE
;
748 /* One-time configuration init control */
749 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
751 /* Default effect that applies to sources that don't have an effect on send 0 */
752 static ALeffect DefaultEffect
;
754 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
757 static ALCboolean SuspendDefers
= ALC_TRUE
;
760 /************************************************
762 ************************************************/
763 static const ALCchar alcNoDeviceExtList
[] =
764 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
765 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
766 static const ALCchar alcExtensionList
[] =
767 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
768 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
769 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
770 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
771 static const ALCint alcMajorVersion
= 1;
772 static const ALCint alcMinorVersion
= 1;
774 static const ALCint alcEFXMajorVersion
= 1;
775 static const ALCint alcEFXMinorVersion
= 0;
778 /************************************************
780 ************************************************/
781 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
783 static almtx_t ListLock
;
784 static inline void LockLists(void)
786 int ret
= almtx_lock(&ListLock
);
787 assert(ret
== althrd_success
);
789 static inline void UnlockLists(void)
791 int ret
= almtx_unlock(&ListLock
);
792 assert(ret
== althrd_success
);
795 /************************************************
796 * Library initialization
797 ************************************************/
799 static void alc_init(void);
800 static void alc_deinit(void);
801 static void alc_deinit_safe(void);
803 #ifndef AL_LIBTYPE_STATIC
804 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
808 case DLL_PROCESS_ATTACH
:
809 /* Pin the DLL so we won't get unloaded until the process terminates */
810 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
811 (WCHAR
*)hModule
, &hModule
);
815 case DLL_THREAD_DETACH
:
816 althrd_thread_detach();
819 case DLL_PROCESS_DETACH
:
828 #elif defined(_MSC_VER)
829 #pragma section(".CRT$XCU",read)
830 static void alc_constructor(void);
831 static void alc_destructor(void);
832 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
834 static void alc_constructor(void)
836 atexit(alc_destructor
);
840 static void alc_destructor(void)
844 #elif defined(HAVE_GCC_DESTRUCTOR)
845 static void alc_init(void) __attribute__((constructor
));
846 static void alc_deinit(void) __attribute__((destructor
));
848 #error "No static initialization available on this platform!"
851 #elif defined(HAVE_GCC_DESTRUCTOR)
853 static void alc_init(void) __attribute__((constructor
));
854 static void alc_deinit(void) __attribute__((destructor
));
857 #error "No global initialization available on this platform!"
860 static void ReleaseThreadCtx(void *ptr
);
861 static void alc_init(void)
868 AL_STRING_INIT(alcAllDevicesList
);
869 AL_STRING_INIT(alcCaptureDeviceList
);
871 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
872 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
875 str
= getenv("__ALSOFT_REVERSE_Z");
876 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
879 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
880 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
881 OverrideReverbSpeedOfSound
= AL_TRUE
;
883 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
884 assert(ret
== althrd_success
);
886 ret
= almtx_init(&ListLock
, almtx_recursive
);
887 assert(ret
== althrd_success
);
890 static void alc_initconfig(void)
892 const char *devs
, *str
;
897 str
= getenv("ALSOFT_LOGLEVEL");
900 long lvl
= strtol(str
, NULL
, 0);
901 if(lvl
>= NoLog
&& lvl
<= LogRef
)
905 str
= getenv("ALSOFT_LOGFILE");
908 FILE *logfile
= al_fopen(str
, "wt");
909 if(logfile
) LogFile
= logfile
;
910 else ERR("Failed to open log file '%s'\n", str
);
913 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
914 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
919 if(BackendListSize
> 0)
920 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
921 for(i
= 1;i
< BackendListSize
;i
++)
922 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
923 TRACE("Supported backends: %s\n", buf
);
927 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
930 if(strcasecmp(str
, "ignore") == 0)
932 SuspendDefers
= ALC_FALSE
;
933 TRACE("Selected context suspend behavior, \"ignore\"\n");
936 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
940 #if defined(HAVE_SSE4_1)
941 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
942 #elif defined(HAVE_SSE3)
943 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
944 #elif defined(HAVE_SSE2)
945 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
946 #elif defined(HAVE_SSE)
947 capfilter
|= CPU_CAP_SSE
;
950 capfilter
|= CPU_CAP_NEON
;
952 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
954 if(strcasecmp(str
, "all") == 0)
959 const char *next
= str
;
963 while(isspace(str
[0]))
965 next
= strchr(str
, ',');
967 if(!str
[0] || str
[0] == ',')
970 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
971 while(len
> 0 && isspace(str
[len
-1]))
973 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
974 capfilter
&= ~CPU_CAP_SSE
;
975 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
976 capfilter
&= ~CPU_CAP_SSE2
;
977 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
978 capfilter
&= ~CPU_CAP_SSE3
;
979 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
980 capfilter
&= ~CPU_CAP_SSE4_1
;
981 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
982 capfilter
&= ~CPU_CAP_NEON
;
984 WARN("Invalid CPU extension \"%s\"\n", str
);
988 FillCPUCaps(capfilter
);
995 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1000 str
= getenv("ALSOFT_TRAP_ERROR");
1001 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1003 TrapALError
= AL_TRUE
;
1004 TrapALCError
= AL_TRUE
;
1008 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1009 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1010 TrapALError
= AL_TRUE
;
1011 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1013 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1014 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1015 TrapALCError
= ALC_TRUE
;
1016 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1019 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1020 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1022 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1023 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1027 const char *next
= devs
;
1028 int endlist
, delitem
;
1033 while(isspace(devs
[0]))
1035 next
= strchr(devs
, ',');
1037 delitem
= (devs
[0] == '-');
1038 if(devs
[0] == '-') devs
++;
1040 if(!devs
[0] || devs
[0] == ',')
1047 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1048 while(len
> 0 && isspace(devs
[len
-1]))
1051 /* HACK: For backwards compatibility, convert backend references of
1052 * mmdevapi to wasapi. This should eventually be removed.
1054 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1060 for(n
= i
;n
< BackendListSize
;n
++)
1062 if(len
== strlen(BackendList
[n
].name
) &&
1063 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1067 for(;n
+1 < BackendListSize
;n
++)
1068 BackendList
[n
] = BackendList
[n
+1];
1073 struct BackendInfo Bkp
= BackendList
[n
];
1075 BackendList
[n
] = BackendList
[n
-1];
1076 BackendList
[n
] = Bkp
;
1086 BackendListSize
= i
;
1089 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1091 ALCbackendFactory
*factory
;
1092 BackendList
[n
] = BackendList
[i
];
1094 factory
= BackendList
[n
].getFactory();
1095 if(!V0(factory
,init
)())
1097 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1101 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1102 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1104 PlaybackBackend
= BackendList
[n
];
1105 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1107 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1109 CaptureBackend
= BackendList
[n
];
1110 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1114 BackendListSize
= n
;
1117 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1121 if(!PlaybackBackend
.name
)
1122 WARN("No playback backend available!\n");
1123 if(!CaptureBackend
.name
)
1124 WARN("No capture backend available!\n");
1126 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1129 const char *next
= str
;
1133 next
= strchr(str
, ',');
1135 if(!str
[0] || next
== str
)
1138 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1139 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1141 if(len
== strlen(EffectList
[n
].name
) &&
1142 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1143 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1148 InitEffect(&DefaultEffect
);
1149 str
= getenv("ALSOFT_DEFAULT_REVERB");
1150 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1151 LoadReverbPreset(str
, &DefaultEffect
);
1153 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1158 static JavaVM
*gJavaVM
;
1159 static pthread_key_t gJVMThreadKey
;
1161 static void CleanupJNIEnv(void* UNUSED(ptr
))
1163 JCALL0(gJavaVM
,DetachCurrentThread
)();
1166 void *Android_GetJNIEnv(void)
1170 WARN("gJavaVM is NULL!\n");
1174 /* http://developer.android.com/guide/practices/jni.html
1176 * All threads are Linux threads, scheduled by the kernel. They're usually
1177 * started from managed code (using Thread.start), but they can also be
1178 * created elsewhere and then attached to the JavaVM. For example, a thread
1179 * started with pthread_create can be attached with the JNI
1180 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1181 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1182 * Attaching a natively-created thread causes a java.lang.Thread object to
1183 * be constructed and added to the "main" ThreadGroup, making it visible to
1184 * the debugger. Calling AttachCurrentThread on an already-attached thread
1187 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1190 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1193 ERR("Failed to attach current thread\n");
1196 pthread_setspecific(gJVMThreadKey
, env
);
1201 /* Automatically called by JNI. */
1202 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1208 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1210 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1214 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1215 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1217 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1218 ERR("pthread_key_create failed: %d\n", err
);
1219 pthread_setspecific(gJVMThreadKey
, env
);
1220 return JNI_VERSION_1_4
;
1225 /************************************************
1226 * Library deinitialization
1227 ************************************************/
1228 static void alc_cleanup(void)
1232 AL_STRING_DEINIT(alcAllDevicesList
);
1233 AL_STRING_DEINIT(alcCaptureDeviceList
);
1235 free(alcDefaultAllDevicesSpecifier
);
1236 alcDefaultAllDevicesSpecifier
= NULL
;
1237 free(alcCaptureDefaultDeviceSpecifier
);
1238 alcCaptureDefaultDeviceSpecifier
= NULL
;
1240 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1245 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
1246 } while(dev
!= NULL
);
1247 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1251 static void alc_deinit_safe(void)
1258 almtx_destroy(&ListLock
);
1259 altss_delete(LocalContext
);
1261 if(LogFile
!= stderr
)
1268 static void alc_deinit(void)
1274 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1275 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1277 for(i
= 0;i
< BackendListSize
;i
++)
1279 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1280 V0(factory
,deinit
)();
1283 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1284 V0(factory
,deinit
)();
1291 /************************************************
1292 * Device enumeration
1293 ************************************************/
1294 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1301 if(backendinfo
->getFactory
)
1303 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1304 V(factory
,probe
)(type
);
1309 static void ProbeAllDevicesList(void)
1310 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1311 static void ProbeCaptureDeviceList(void)
1312 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1314 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1316 size_t len
= strlen(name
);
1318 alstr_append_range(devnames
, name
, name
+len
+1);
1320 void AppendAllDevicesList(const ALCchar
*name
)
1321 { AppendDevice(name
, &alcAllDevicesList
); }
1322 void AppendCaptureDeviceList(const ALCchar
*name
)
1323 { AppendDevice(name
, &alcCaptureDeviceList
); }
1326 /************************************************
1327 * Device format information
1328 ************************************************/
1329 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1333 case DevFmtByte
: return "Signed Byte";
1334 case DevFmtUByte
: return "Unsigned Byte";
1335 case DevFmtShort
: return "Signed Short";
1336 case DevFmtUShort
: return "Unsigned Short";
1337 case DevFmtInt
: return "Signed Int";
1338 case DevFmtUInt
: return "Unsigned Int";
1339 case DevFmtFloat
: return "Float";
1341 return "(unknown type)";
1343 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1347 case DevFmtMono
: return "Mono";
1348 case DevFmtStereo
: return "Stereo";
1349 case DevFmtQuad
: return "Quadraphonic";
1350 case DevFmtX51
: return "5.1 Surround";
1351 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1352 case DevFmtX61
: return "6.1 Surround";
1353 case DevFmtX71
: return "7.1 Surround";
1354 case DevFmtAmbi3D
: return "Ambisonic 3D";
1356 return "(unknown channels)";
1359 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1360 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1364 case DevFmtByte
: return sizeof(ALbyte
);
1365 case DevFmtUByte
: return sizeof(ALubyte
);
1366 case DevFmtShort
: return sizeof(ALshort
);
1367 case DevFmtUShort
: return sizeof(ALushort
);
1368 case DevFmtInt
: return sizeof(ALint
);
1369 case DevFmtUInt
: return sizeof(ALuint
);
1370 case DevFmtFloat
: return sizeof(ALfloat
);
1374 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1378 case DevFmtMono
: return 1;
1379 case DevFmtStereo
: return 2;
1380 case DevFmtQuad
: return 4;
1381 case DevFmtX51
: return 6;
1382 case DevFmtX51Rear
: return 6;
1383 case DevFmtX61
: return 7;
1384 case DevFmtX71
: return 8;
1385 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1386 (ambiorder
== 2) ? 9 :
1387 (ambiorder
== 1) ? 4 : 1;
1392 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1393 enum DevFmtType
*type
)
1395 static const struct {
1397 enum DevFmtChannels channels
;
1398 enum DevFmtType type
;
1400 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1401 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1402 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1404 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1405 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1406 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1408 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1409 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1410 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1412 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1413 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1414 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1416 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1417 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1418 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1420 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1421 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1422 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1426 for(i
= 0;i
< COUNTOF(list
);i
++)
1428 if(list
[i
].format
== format
)
1430 *chans
= list
[i
].channels
;
1431 *type
= list
[i
].type
;
1439 static ALCboolean
IsValidALCType(ALCenum type
)
1444 case ALC_UNSIGNED_BYTE_SOFT
:
1445 case ALC_SHORT_SOFT
:
1446 case ALC_UNSIGNED_SHORT_SOFT
:
1448 case ALC_UNSIGNED_INT_SOFT
:
1449 case ALC_FLOAT_SOFT
:
1455 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1460 case ALC_STEREO_SOFT
:
1462 case ALC_5POINT1_SOFT
:
1463 case ALC_6POINT1_SOFT
:
1464 case ALC_7POINT1_SOFT
:
1465 case ALC_BFORMAT3D_SOFT
:
1471 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1482 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1494 /************************************************
1495 * Miscellaneous ALC helpers
1496 ************************************************/
1498 /* SetDefaultWFXChannelOrder
1500 * Sets the default channel order used by WaveFormatEx.
1502 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1506 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1507 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1509 switch(device
->FmtChans
)
1512 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1515 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1516 device
->RealOut
.ChannelName
[1] = FrontRight
;
1519 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1520 device
->RealOut
.ChannelName
[1] = FrontRight
;
1521 device
->RealOut
.ChannelName
[2] = BackLeft
;
1522 device
->RealOut
.ChannelName
[3] = BackRight
;
1525 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1526 device
->RealOut
.ChannelName
[1] = FrontRight
;
1527 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1528 device
->RealOut
.ChannelName
[3] = LFE
;
1529 device
->RealOut
.ChannelName
[4] = SideLeft
;
1530 device
->RealOut
.ChannelName
[5] = SideRight
;
1533 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1534 device
->RealOut
.ChannelName
[1] = FrontRight
;
1535 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1536 device
->RealOut
.ChannelName
[3] = LFE
;
1537 device
->RealOut
.ChannelName
[4] = BackLeft
;
1538 device
->RealOut
.ChannelName
[5] = BackRight
;
1541 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1542 device
->RealOut
.ChannelName
[1] = FrontRight
;
1543 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1544 device
->RealOut
.ChannelName
[3] = LFE
;
1545 device
->RealOut
.ChannelName
[4] = BackCenter
;
1546 device
->RealOut
.ChannelName
[5] = SideLeft
;
1547 device
->RealOut
.ChannelName
[6] = SideRight
;
1550 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1551 device
->RealOut
.ChannelName
[1] = FrontRight
;
1552 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1553 device
->RealOut
.ChannelName
[3] = LFE
;
1554 device
->RealOut
.ChannelName
[4] = BackLeft
;
1555 device
->RealOut
.ChannelName
[5] = BackRight
;
1556 device
->RealOut
.ChannelName
[6] = SideLeft
;
1557 device
->RealOut
.ChannelName
[7] = SideRight
;
1560 device
->RealOut
.ChannelName
[0] = Aux0
;
1561 if(device
->AmbiOrder
> 0)
1563 device
->RealOut
.ChannelName
[1] = Aux1
;
1564 device
->RealOut
.ChannelName
[2] = Aux2
;
1565 device
->RealOut
.ChannelName
[3] = Aux3
;
1567 if(device
->AmbiOrder
> 1)
1569 device
->RealOut
.ChannelName
[4] = Aux4
;
1570 device
->RealOut
.ChannelName
[5] = Aux5
;
1571 device
->RealOut
.ChannelName
[6] = Aux6
;
1572 device
->RealOut
.ChannelName
[7] = Aux7
;
1573 device
->RealOut
.ChannelName
[8] = Aux8
;
1575 if(device
->AmbiOrder
> 2)
1577 device
->RealOut
.ChannelName
[9] = Aux9
;
1578 device
->RealOut
.ChannelName
[10] = Aux10
;
1579 device
->RealOut
.ChannelName
[11] = Aux11
;
1580 device
->RealOut
.ChannelName
[12] = Aux12
;
1581 device
->RealOut
.ChannelName
[13] = Aux13
;
1582 device
->RealOut
.ChannelName
[14] = Aux14
;
1583 device
->RealOut
.ChannelName
[15] = Aux15
;
1589 /* SetDefaultChannelOrder
1591 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1593 void SetDefaultChannelOrder(ALCdevice
*device
)
1597 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1598 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1600 switch(device
->FmtChans
)
1603 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1604 device
->RealOut
.ChannelName
[1] = FrontRight
;
1605 device
->RealOut
.ChannelName
[2] = BackLeft
;
1606 device
->RealOut
.ChannelName
[3] = BackRight
;
1607 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1608 device
->RealOut
.ChannelName
[5] = LFE
;
1611 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1612 device
->RealOut
.ChannelName
[1] = FrontRight
;
1613 device
->RealOut
.ChannelName
[2] = BackLeft
;
1614 device
->RealOut
.ChannelName
[3] = BackRight
;
1615 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1616 device
->RealOut
.ChannelName
[5] = LFE
;
1617 device
->RealOut
.ChannelName
[6] = SideLeft
;
1618 device
->RealOut
.ChannelName
[7] = SideRight
;
1621 /* Same as WFX order */
1628 SetDefaultWFXChannelOrder(device
);
1633 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1634 extern inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
);
1637 /* ALCcontext_DeferUpdates
1639 * Defers/suspends updates for the given context's listener and sources. This
1640 * does *NOT* stop mixing, but rather prevents certain property changes from
1643 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1645 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1648 /* ALCcontext_ProcessUpdates
1650 * Resumes update processing after being deferred.
1652 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1654 almtx_lock(&context
->PropLock
);
1655 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1657 /* Tell the mixer to stop applying updates, then wait for any active
1658 * updating to finish, before providing updates.
1660 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1661 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1664 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1665 UpdateContextProps(context
);
1666 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1667 UpdateListenerProps(context
);
1668 UpdateAllEffectSlotProps(context
);
1669 UpdateAllSourceProps(context
);
1671 /* Now with all updates declared, let the mixer continue applying them
1672 * so they all happen at once.
1674 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1676 almtx_unlock(&context
->PropLock
);
1682 * Stores the latest ALC device error
1684 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1686 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1690 /* DebugBreak() will cause an exception if there is no debugger */
1691 if(IsDebuggerPresent())
1693 #elif defined(SIGTRAP)
1699 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1701 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1705 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1707 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1708 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1713 * Updates the device's base clock time with however many samples have been
1714 * done. This is used so frequency changes on the device don't cause the time
1715 * to jump forward or back. Must not be called while the device is running/
1718 static inline void UpdateClockBase(ALCdevice
*device
)
1720 IncrementRef(&device
->MixCount
);
1721 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1722 device
->SamplesDone
= 0;
1723 IncrementRef(&device
->MixCount
);
1726 /* UpdateDeviceParams
1728 * Updates device parameters according to the attribute list (caller is
1729 * responsible for holding the list lock).
1731 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1733 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1734 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1735 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1736 const ALsizei old_sends
= device
->NumAuxSends
;
1737 ALsizei new_sends
= device
->NumAuxSends
;
1738 enum DevFmtChannels oldChans
;
1739 enum DevFmtType oldType
;
1740 ALboolean update_failed
;
1741 ALCsizei hrtf_id
= -1;
1742 ALCcontext
*context
;
1748 // Check for attributes
1749 if(device
->Type
== Loopback
)
1751 ALCsizei numMono
, numStereo
, numSends
;
1752 ALCenum alayout
= AL_NONE
;
1753 ALCenum ascale
= AL_NONE
;
1754 ALCenum schans
= AL_NONE
;
1755 ALCenum stype
= AL_NONE
;
1756 ALCsizei attrIdx
= 0;
1757 ALCsizei aorder
= 0;
1762 WARN("Missing attributes for loopback device\n");
1763 return ALC_INVALID_VALUE
;
1766 numMono
= device
->NumMonoSources
;
1767 numStereo
= device
->NumStereoSources
;
1768 numSends
= old_sends
;
1770 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1771 while(attrList
[attrIdx
])
1773 switch(attrList
[attrIdx
])
1775 case ALC_FORMAT_CHANNELS_SOFT
:
1776 schans
= attrList
[attrIdx
+ 1];
1777 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1778 if(!IsValidALCChannels(schans
))
1779 return ALC_INVALID_VALUE
;
1782 case ALC_FORMAT_TYPE_SOFT
:
1783 stype
= attrList
[attrIdx
+ 1];
1784 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1785 if(!IsValidALCType(stype
))
1786 return ALC_INVALID_VALUE
;
1790 freq
= attrList
[attrIdx
+ 1];
1791 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1792 if(freq
< MIN_OUTPUT_RATE
)
1793 return ALC_INVALID_VALUE
;
1796 case ALC_AMBISONIC_LAYOUT_SOFT
:
1797 alayout
= attrList
[attrIdx
+ 1];
1798 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1799 if(!IsValidAmbiLayout(alayout
))
1800 return ALC_INVALID_VALUE
;
1803 case ALC_AMBISONIC_SCALING_SOFT
:
1804 ascale
= attrList
[attrIdx
+ 1];
1805 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1806 if(!IsValidAmbiScaling(ascale
))
1807 return ALC_INVALID_VALUE
;
1810 case ALC_AMBISONIC_ORDER_SOFT
:
1811 aorder
= attrList
[attrIdx
+ 1];
1812 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1813 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1814 return ALC_INVALID_VALUE
;
1817 case ALC_MONO_SOURCES
:
1818 numMono
= attrList
[attrIdx
+ 1];
1819 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1820 numMono
= maxi(numMono
, 0);
1823 case ALC_STEREO_SOURCES
:
1824 numStereo
= attrList
[attrIdx
+ 1];
1825 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1826 numStereo
= maxi(numStereo
, 0);
1829 case ALC_MAX_AUXILIARY_SENDS
:
1830 numSends
= attrList
[attrIdx
+ 1];
1831 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1832 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1836 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1837 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1838 hrtf_appreq
= Hrtf_Disable
;
1839 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1840 hrtf_appreq
= Hrtf_Enable
;
1842 hrtf_appreq
= Hrtf_Default
;
1845 case ALC_HRTF_ID_SOFT
:
1846 hrtf_id
= attrList
[attrIdx
+ 1];
1847 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1850 case ALC_OUTPUT_LIMITER_SOFT
:
1851 gainLimiter
= attrList
[attrIdx
+ 1];
1852 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1856 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1857 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1865 if(!schans
|| !stype
|| !freq
)
1867 WARN("Missing format for loopback device\n");
1868 return ALC_INVALID_VALUE
;
1870 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1872 WARN("Missing ambisonic info for loopback device\n");
1873 return ALC_INVALID_VALUE
;
1876 if((device
->Flags
&DEVICE_RUNNING
))
1877 V0(device
->Backend
,stop
)();
1878 device
->Flags
&= ~DEVICE_RUNNING
;
1880 UpdateClockBase(device
);
1882 device
->Frequency
= freq
;
1883 device
->FmtChans
= schans
;
1884 device
->FmtType
= stype
;
1885 if(schans
== ALC_BFORMAT3D_SOFT
)
1887 device
->AmbiOrder
= aorder
;
1888 device
->AmbiLayout
= alayout
;
1889 device
->AmbiScale
= ascale
;
1892 if(numMono
> INT_MAX
-numStereo
)
1893 numMono
= INT_MAX
-numStereo
;
1894 numMono
+= numStereo
;
1895 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1901 numMono
= maxi(numMono
, 256);
1902 numStereo
= mini(numStereo
, numMono
);
1903 numMono
-= numStereo
;
1904 device
->SourcesMax
= numMono
+ numStereo
;
1906 device
->NumMonoSources
= numMono
;
1907 device
->NumStereoSources
= numStereo
;
1909 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1910 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1912 new_sends
= numSends
;
1914 else if(attrList
&& attrList
[0])
1916 ALCsizei numMono
, numStereo
, numSends
;
1917 ALCsizei attrIdx
= 0;
1920 /* If a context is already running on the device, stop playback so the
1921 * device attributes can be updated. */
1922 if((device
->Flags
&DEVICE_RUNNING
))
1923 V0(device
->Backend
,stop
)();
1924 device
->Flags
&= ~DEVICE_RUNNING
;
1926 UpdateClockBase(device
);
1928 freq
= device
->Frequency
;
1929 numMono
= device
->NumMonoSources
;
1930 numStereo
= device
->NumStereoSources
;
1931 numSends
= old_sends
;
1933 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1934 while(attrList
[attrIdx
])
1936 switch(attrList
[attrIdx
])
1939 freq
= attrList
[attrIdx
+ 1];
1940 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1941 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1944 case ALC_MONO_SOURCES
:
1945 numMono
= attrList
[attrIdx
+ 1];
1946 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1947 numMono
= maxi(numMono
, 0);
1950 case ALC_STEREO_SOURCES
:
1951 numStereo
= attrList
[attrIdx
+ 1];
1952 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1953 numStereo
= maxi(numStereo
, 0);
1956 case ALC_MAX_AUXILIARY_SENDS
:
1957 numSends
= attrList
[attrIdx
+ 1];
1958 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1959 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1963 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1964 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1965 hrtf_appreq
= Hrtf_Disable
;
1966 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1967 hrtf_appreq
= Hrtf_Enable
;
1969 hrtf_appreq
= Hrtf_Default
;
1972 case ALC_HRTF_ID_SOFT
:
1973 hrtf_id
= attrList
[attrIdx
+ 1];
1974 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1977 case ALC_OUTPUT_LIMITER_SOFT
:
1978 gainLimiter
= attrList
[attrIdx
+ 1];
1979 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1983 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1984 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1992 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
1993 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1995 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1997 /* SSE and Neon do best with the update size being a multiple of 4 */
1998 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1999 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2001 device
->Frequency
= freq
;
2003 if(numMono
> INT_MAX
-numStereo
)
2004 numMono
= INT_MAX
-numStereo
;
2005 numMono
+= numStereo
;
2006 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2012 numMono
= maxi(numMono
, 256);
2013 numStereo
= mini(numStereo
, numMono
);
2014 numMono
-= numStereo
;
2015 device
->SourcesMax
= numMono
+ numStereo
;
2017 device
->NumMonoSources
= numMono
;
2018 device
->NumStereoSources
= numStereo
;
2020 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2021 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2023 new_sends
= numSends
;
2026 if((device
->Flags
&DEVICE_RUNNING
))
2027 return ALC_NO_ERROR
;
2029 al_free(device
->Uhj_Encoder
);
2030 device
->Uhj_Encoder
= NULL
;
2032 al_free(device
->Bs2b
);
2033 device
->Bs2b
= NULL
;
2035 al_free(device
->ChannelDelay
[0].Buffer
);
2036 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2038 device
->ChannelDelay
[i
].Length
= 0;
2039 device
->ChannelDelay
[i
].Buffer
= NULL
;
2042 al_free(device
->Dry
.Buffer
);
2043 device
->Dry
.Buffer
= NULL
;
2044 device
->Dry
.NumChannels
= 0;
2045 device
->FOAOut
.Buffer
= NULL
;
2046 device
->FOAOut
.NumChannels
= 0;
2047 device
->RealOut
.Buffer
= NULL
;
2048 device
->RealOut
.NumChannels
= 0;
2050 UpdateClockBase(device
);
2052 device
->DitherSeed
= DITHER_RNG_SEED
;
2054 /*************************************************************************
2055 * Update device format request if HRTF is requested
2057 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2058 if(device
->Type
!= Loopback
)
2061 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2063 if(strcasecmp(hrtf
, "true") == 0)
2064 hrtf_userreq
= Hrtf_Enable
;
2065 else if(strcasecmp(hrtf
, "false") == 0)
2066 hrtf_userreq
= Hrtf_Disable
;
2067 else if(strcasecmp(hrtf
, "auto") != 0)
2068 ERR("Unexpected hrtf value: %s\n", hrtf
);
2071 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2073 struct Hrtf
*hrtf
= NULL
;
2074 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2076 VECTOR_DEINIT(device
->HrtfList
);
2077 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2079 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2081 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2082 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2084 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2089 device
->FmtChans
= DevFmtStereo
;
2090 device
->Frequency
= hrtf
->sampleRate
;
2091 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2092 if(device
->HrtfHandle
)
2093 Hrtf_DecRef(device
->HrtfHandle
);
2094 device
->HrtfHandle
= hrtf
;
2098 hrtf_userreq
= Hrtf_Default
;
2099 hrtf_appreq
= Hrtf_Disable
;
2100 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2105 oldFreq
= device
->Frequency
;
2106 oldChans
= device
->FmtChans
;
2107 oldType
= device
->FmtType
;
2109 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2110 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2111 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2112 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2113 device
->UpdateSize
, device
->NumUpdates
2116 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2117 return ALC_INVALID_DEVICE
;
2119 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2121 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2122 DevFmtChannelsString(device
->FmtChans
));
2123 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2125 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2128 DevFmtTypeString(device
->FmtType
));
2129 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2131 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2133 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2134 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2137 if((device
->UpdateSize
&3) != 0)
2139 if((CPUCapFlags
&CPU_CAP_SSE
))
2140 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2141 if((CPUCapFlags
&CPU_CAP_NEON
))
2142 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2145 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2146 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2147 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2150 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2151 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2152 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2154 /* Allocate extra channels for any post-filter output. */
2155 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2156 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2158 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2159 device
->Dry
.Buffer
= al_calloc(16, size
);
2160 if(!device
->Dry
.Buffer
)
2162 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2163 return ALC_INVALID_DEVICE
;
2166 if(device
->RealOut
.NumChannels
!= 0)
2167 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2168 device
->FOAOut
.NumChannels
;
2171 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2172 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2175 if(device
->FOAOut
.NumChannels
!= 0)
2176 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2179 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2180 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2183 device
->NumAuxSends
= new_sends
;
2184 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2185 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2186 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2188 device
->DitherDepth
= 0.0f
;
2189 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2192 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2195 switch(device
->FmtType
)
2213 device
->DitherDepth
= (depth
> 0) ? powf(2.0f
, (ALfloat
)(depth
-1)) : 0.0f
;
2215 if(!(device
->DitherDepth
> 0.0f
))
2216 TRACE("Dithering disabled\n");
2218 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2219 device
->DitherDepth
);
2221 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2222 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2223 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2224 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2227 if(gainLimiter
!= ALC_FALSE
)
2229 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2231 al_free(device
->Limiter
);
2232 device
->Limiter
= CreateDeviceLimiter(device
);
2237 al_free(device
->Limiter
);
2238 device
->Limiter
= NULL
;
2240 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2242 aluSelectPostProcess(device
);
2244 /* Need to delay returning failure until replacement Send arrays have been
2245 * allocated with the appropriate size.
2247 update_failed
= AL_FALSE
;
2249 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2252 SourceSubList
*sublist
, *subend
;
2253 struct ALvoiceProps
*vprops
;
2256 if(context
->DefaultSlot
)
2258 ALeffectslot
*slot
= context
->DefaultSlot
;
2259 ALeffectState
*state
= slot
->Effect
.State
;
2261 state
->OutBuffer
= device
->Dry
.Buffer
;
2262 state
->OutChannels
= device
->Dry
.NumChannels
;
2263 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2264 update_failed
= AL_TRUE
;
2266 UpdateEffectSlotProps(slot
, context
);
2269 almtx_lock(&context
->PropLock
);
2270 almtx_lock(&context
->EffectSlotLock
);
2271 for(pos
= 0;pos
< (ALsizei
)VECTOR_SIZE(context
->EffectSlotList
);pos
++)
2273 ALeffectslot
*slot
= VECTOR_ELEM(context
->EffectSlotList
, pos
);
2274 ALeffectState
*state
= slot
->Effect
.State
;
2276 state
->OutBuffer
= device
->Dry
.Buffer
;
2277 state
->OutChannels
= device
->Dry
.NumChannels
;
2278 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2279 update_failed
= AL_TRUE
;
2281 UpdateEffectSlotProps(slot
, context
);
2283 almtx_unlock(&context
->EffectSlotLock
);
2285 almtx_lock(&context
->SourceLock
);
2286 sublist
= VECTOR_BEGIN(context
->SourceList
);
2287 subend
= VECTOR_END(context
->SourceList
);
2288 for(;sublist
!= subend
;++sublist
)
2290 ALuint64 usemask
= ~sublist
->FreeMask
;
2293 ALsizei idx
= CTZ64(usemask
);
2294 ALsource
*source
= sublist
->Sources
+ idx
;
2296 usemask
&= ~(U64(1) << idx
);
2298 if(old_sends
!= device
->NumAuxSends
)
2300 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2303 memcpy(sends
, source
->Send
,
2304 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2306 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2308 if(source
->Send
[s
].Slot
)
2309 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2310 source
->Send
[s
].Slot
= NULL
;
2312 al_free(source
->Send
);
2313 source
->Send
= sends
;
2314 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2316 source
->Send
[s
].Slot
= NULL
;
2317 source
->Send
[s
].Gain
= 1.0f
;
2318 source
->Send
[s
].GainHF
= 1.0f
;
2319 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2320 source
->Send
[s
].GainLF
= 1.0f
;
2321 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2325 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2329 /* Clear any pre-existing voice property structs, in case the number of
2330 * auxiliary sends is changing. Active sources will have updates
2331 * respecified in UpdateAllSourceProps.
2333 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2336 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2341 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2342 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2344 ALvoice
*voice
= context
->Voices
[pos
];
2346 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2348 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2351 if(device
->AvgSpeakerDist
> 0.0f
)
2353 /* Reinitialize the NFC filters for new parameters. */
2354 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2355 (device
->AvgSpeakerDist
* device
->Frequency
);
2356 for(i
= 0;i
< voice
->NumChannels
;i
++)
2357 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2360 almtx_unlock(&context
->SourceLock
);
2362 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2363 UpdateContextProps(context
);
2364 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2365 UpdateListenerProps(context
);
2366 UpdateAllSourceProps(context
);
2367 almtx_unlock(&context
->PropLock
);
2369 context
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2373 return ALC_INVALID_DEVICE
;
2375 if(!(device
->Flags
&DEVICE_PAUSED
))
2377 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2378 return ALC_INVALID_DEVICE
;
2379 device
->Flags
|= DEVICE_RUNNING
;
2382 return ALC_NO_ERROR
;
2386 static void InitDevice(ALCdevice
*device
, enum DeviceType type
)
2390 InitRef(&device
->ref
, 1);
2391 ATOMIC_INIT(&device
->Connected
, ALC_TRUE
);
2392 device
->Type
= type
;
2393 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
2396 device
->Render_Mode
= NormalRender
;
2397 device
->AvgSpeakerDist
= 0.0f
;
2399 ATOMIC_INIT(&device
->ContextList
, NULL
);
2401 device
->ClockBase
= 0;
2402 device
->SamplesDone
= 0;
2404 device
->SourcesMax
= 0;
2405 device
->AuxiliaryEffectSlotMax
= 0;
2406 device
->NumAuxSends
= 0;
2408 device
->Dry
.Buffer
= NULL
;
2409 device
->Dry
.NumChannels
= 0;
2410 device
->FOAOut
.Buffer
= NULL
;
2411 device
->FOAOut
.NumChannels
= 0;
2412 device
->RealOut
.Buffer
= NULL
;
2413 device
->RealOut
.NumChannels
= 0;
2415 AL_STRING_INIT(device
->DeviceName
);
2417 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2419 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2420 device
->ChannelDelay
[i
].Length
= 0;
2421 device
->ChannelDelay
[i
].Buffer
= NULL
;
2424 AL_STRING_INIT(device
->HrtfName
);
2425 VECTOR_INIT(device
->HrtfList
);
2426 device
->HrtfHandle
= NULL
;
2427 device
->Hrtf
= NULL
;
2428 device
->Bs2b
= NULL
;
2429 device
->Uhj_Encoder
= NULL
;
2430 device
->AmbiDecoder
= NULL
;
2431 device
->AmbiUp
= NULL
;
2432 device
->Stablizer
= NULL
;
2433 device
->Limiter
= NULL
;
2435 VECTOR_INIT(device
->BufferList
);
2436 almtx_init(&device
->BufferLock
, almtx_plain
);
2438 VECTOR_INIT(device
->EffectList
);
2439 almtx_init(&device
->EffectLock
, almtx_plain
);
2441 VECTOR_INIT(device
->FilterList
);
2442 almtx_init(&device
->FilterLock
, almtx_plain
);
2444 almtx_init(&device
->BackendLock
, almtx_plain
);
2445 device
->Backend
= NULL
;
2447 ATOMIC_INIT(&device
->next
, NULL
);
2452 * Frees the device structure, and destroys any objects the app failed to
2453 * delete. Called once there's no more references on the device.
2455 static ALCvoid
FreeDevice(ALCdevice
*device
)
2459 TRACE("%p\n", device
);
2462 DELETE_OBJ(device
->Backend
);
2463 device
->Backend
= NULL
;
2465 almtx_destroy(&device
->BackendLock
);
2467 ReleaseALBuffers(device
);
2468 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2469 VECTOR_FOR_EACH(BufferSubList
, device
->BufferList
, FREE_BUFFERSUBLIST
);
2470 #undef FREE_BUFFERSUBLIST
2471 VECTOR_DEINIT(device
->BufferList
);
2472 almtx_destroy(&device
->BufferLock
);
2474 ReleaseALEffects(device
);
2475 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2476 VECTOR_FOR_EACH(EffectSubList
, device
->EffectList
, FREE_EFFECTSUBLIST
);
2477 #undef FREE_EFFECTSUBLIST
2478 VECTOR_DEINIT(device
->EffectList
);
2479 almtx_destroy(&device
->EffectLock
);
2481 ReleaseALFilters(device
);
2482 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2483 VECTOR_FOR_EACH(FilterSubList
, device
->FilterList
, FREE_FILTERSUBLIST
);
2484 #undef FREE_FILTERSUBLIST
2485 VECTOR_DEINIT(device
->FilterList
);
2486 almtx_destroy(&device
->FilterLock
);
2488 AL_STRING_DEINIT(device
->HrtfName
);
2489 FreeHrtfList(&device
->HrtfList
);
2490 if(device
->HrtfHandle
)
2491 Hrtf_DecRef(device
->HrtfHandle
);
2492 device
->HrtfHandle
= NULL
;
2493 al_free(device
->Hrtf
);
2494 device
->Hrtf
= NULL
;
2496 al_free(device
->Bs2b
);
2497 device
->Bs2b
= NULL
;
2499 al_free(device
->Uhj_Encoder
);
2500 device
->Uhj_Encoder
= NULL
;
2502 bformatdec_free(&device
->AmbiDecoder
);
2503 ambiup_free(&device
->AmbiUp
);
2505 al_free(device
->Stablizer
);
2506 device
->Stablizer
= NULL
;
2508 al_free(device
->Limiter
);
2509 device
->Limiter
= NULL
;
2511 al_free(device
->ChannelDelay
[0].Buffer
);
2512 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2514 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2515 device
->ChannelDelay
[i
].Length
= 0;
2516 device
->ChannelDelay
[i
].Buffer
= NULL
;
2519 AL_STRING_DEINIT(device
->DeviceName
);
2521 al_free(device
->Dry
.Buffer
);
2522 device
->Dry
.Buffer
= NULL
;
2523 device
->Dry
.NumChannels
= 0;
2524 device
->FOAOut
.Buffer
= NULL
;
2525 device
->FOAOut
.NumChannels
= 0;
2526 device
->RealOut
.Buffer
= NULL
;
2527 device
->RealOut
.NumChannels
= 0;
2533 void ALCdevice_IncRef(ALCdevice
*device
)
2536 ref
= IncrementRef(&device
->ref
);
2537 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2540 void ALCdevice_DecRef(ALCdevice
*device
)
2543 ref
= DecrementRef(&device
->ref
);
2544 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2545 if(ref
== 0) FreeDevice(device
);
2550 * Checks if the device handle is valid, and increments its ref count if so.
2552 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2554 ALCdevice
*tmpDevice
;
2557 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2560 if(tmpDevice
== *device
)
2562 ALCdevice_IncRef(tmpDevice
);
2566 tmpDevice
= ATOMIC_LOAD(&tmpDevice
->next
, almemory_order_relaxed
);
2577 * Initializes context fields
2579 static ALvoid
InitContext(ALCcontext
*Context
)
2581 ALlistener
*listener
= Context
->Listener
;
2582 struct ALeffectslotArray
*auxslots
;
2584 //Initialise listener
2585 listener
->Gain
= 1.0f
;
2586 listener
->Position
[0] = 0.0f
;
2587 listener
->Position
[1] = 0.0f
;
2588 listener
->Position
[2] = 0.0f
;
2589 listener
->Velocity
[0] = 0.0f
;
2590 listener
->Velocity
[1] = 0.0f
;
2591 listener
->Velocity
[2] = 0.0f
;
2592 listener
->Forward
[0] = 0.0f
;
2593 listener
->Forward
[1] = 0.0f
;
2594 listener
->Forward
[2] = -1.0f
;
2595 listener
->Up
[0] = 0.0f
;
2596 listener
->Up
[1] = 1.0f
;
2597 listener
->Up
[2] = 0.0f
;
2598 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2600 ATOMIC_INIT(&listener
->Update
, NULL
);
2603 InitRef(&Context
->UpdateCount
, 0);
2604 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2605 Context
->GainBoost
= 1.0f
;
2606 almtx_init(&Context
->PropLock
, almtx_plain
);
2607 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2608 VECTOR_INIT(Context
->SourceList
);
2609 Context
->NumSources
= 0;
2610 almtx_init(&Context
->SourceLock
, almtx_plain
);
2611 VECTOR_INIT(Context
->EffectSlotList
);
2612 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2614 if(Context
->DefaultSlot
)
2616 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2617 auxslots
->count
= 1;
2618 auxslots
->slot
[0] = Context
->DefaultSlot
;
2622 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2623 auxslots
->count
= 0;
2625 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2628 Context
->DistanceModel
= DefaultDistanceModel
;
2629 Context
->SourceDistanceModel
= AL_FALSE
;
2630 Context
->DopplerFactor
= 1.0f
;
2631 Context
->DopplerVelocity
= 1.0f
;
2632 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2633 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2634 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2635 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2636 almtx_init(&Context
->EventThrdLock
, almtx_plain
);
2637 alsem_init(&Context
->EventSem
, 0);
2638 Context
->AsyncEvents
= NULL
;
2639 ATOMIC_INIT(&Context
->EnabledEvts
, 0);
2640 almtx_init(&Context
->EventCbLock
, almtx_plain
);
2641 Context
->EventCb
= NULL
;
2642 Context
->EventParam
= NULL
;
2644 ATOMIC_INIT(&Context
->Update
, NULL
);
2645 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2646 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2647 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2648 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2650 Context
->ExtensionList
= alExtList
;
2653 listener
->Params
.Matrix
= IdentityMatrixf
;
2654 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2655 listener
->Params
.Gain
= listener
->Gain
;
2656 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2657 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2658 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2659 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2660 listener
->Params
.MetersPerUnit
;
2661 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2662 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2668 * Cleans up the context, and destroys any remaining objects the app failed to
2669 * delete. Called once there's no more references on the context.
2671 static void FreeContext(ALCcontext
*context
)
2673 ALlistener
*listener
= context
->Listener
;
2674 struct ALeffectslotArray
*auxslots
;
2675 struct ALeffectslotProps
*eprops
;
2676 struct ALlistenerProps
*lprops
;
2677 struct ALcontextProps
*cprops
;
2678 struct ALvoiceProps
*vprops
;
2682 TRACE("%p\n", context
);
2684 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2686 TRACE("Freed unapplied context update %p\n", cprops
);
2691 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2694 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2699 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2701 if(context
->DefaultSlot
)
2703 DeinitEffectSlot(context
->DefaultSlot
);
2704 context
->DefaultSlot
= NULL
;
2707 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2710 ReleaseALSources(context
);
2711 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2712 VECTOR_FOR_EACH(SourceSubList
, context
->SourceList
, FREE_SOURCESUBLIST
);
2713 #undef FREE_SOURCESUBLIST
2714 VECTOR_DEINIT(context
->SourceList
);
2715 context
->NumSources
= 0;
2716 almtx_destroy(&context
->SourceLock
);
2719 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2722 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2723 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2728 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2730 ReleaseALAuxiliaryEffectSlots(context
);
2731 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2732 VECTOR_FOR_EACH(ALeffectslotPtr
, context
->EffectSlotList
, FREE_EFFECTSLOTPTR
);
2733 #undef FREE_EFFECTSLOTPTR
2734 VECTOR_DEINIT(context
->EffectSlotList
);
2735 almtx_destroy(&context
->EffectSlotLock
);
2738 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2741 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2746 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2748 for(i
= 0;i
< context
->VoiceCount
;i
++)
2749 DeinitVoice(context
->Voices
[i
]);
2750 al_free(context
->Voices
);
2751 context
->Voices
= NULL
;
2752 context
->VoiceCount
= 0;
2753 context
->MaxVoices
= 0;
2755 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2757 TRACE("Freed unapplied listener update %p\n", lprops
);
2761 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2764 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2769 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2771 if(ATOMIC_EXCHANGE(&context
->EnabledEvts
, 0, almemory_order_acq_rel
))
2773 static const AsyncEvent kill_evt
= { 0 };
2774 while(ll_ringbuffer_write(context
->AsyncEvents
, (const char*)&kill_evt
, 1) == 0)
2776 alsem_post(&context
->EventSem
);
2777 althrd_join(context
->EventThread
, NULL
);
2780 almtx_destroy(&context
->EventCbLock
);
2781 almtx_destroy(&context
->EventThrdLock
);
2782 alsem_destroy(&context
->EventSem
);
2784 ll_ringbuffer_free(context
->AsyncEvents
);
2785 context
->AsyncEvents
= NULL
;
2787 almtx_destroy(&context
->PropLock
);
2789 ALCdevice_DecRef(context
->Device
);
2790 context
->Device
= NULL
;
2792 //Invalidate context
2793 memset(context
, 0, sizeof(ALCcontext
));
2799 * Removes the context reference from the given device and removes it from
2800 * being current on the running thread or globally. Returns true if other
2801 * contexts still exist on the device.
2803 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2805 ALCcontext
*origctx
, *newhead
;
2808 if(altss_get(LocalContext
) == context
)
2810 WARN("%p released while current on thread\n", context
);
2811 altss_set(LocalContext
, NULL
);
2812 ALCcontext_DecRef(context
);
2816 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2817 ALCcontext_DecRef(context
);
2819 V0(device
->Backend
,lock
)();
2821 newhead
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2822 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2826 /* origctx is what the desired context failed to match. Try
2827 * swapping out the next one in the list.
2831 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origctx
, newhead
));
2835 V0(device
->Backend
,unlock
)();
2837 ALCcontext_DecRef(context
);
2841 static void ALCcontext_IncRef(ALCcontext
*context
)
2843 uint ref
= IncrementRef(&context
->ref
);
2844 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2847 void ALCcontext_DecRef(ALCcontext
*context
)
2849 uint ref
= DecrementRef(&context
->ref
);
2850 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2851 if(ref
== 0) FreeContext(context
);
2854 static void ReleaseThreadCtx(void *ptr
)
2856 ALCcontext
*context
= ptr
;
2857 uint ref
= DecrementRef(&context
->ref
);
2858 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2859 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2864 * Checks that the given context is valid, and increments its reference count.
2866 static ALCboolean
VerifyContext(ALCcontext
**context
)
2871 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2874 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2879 ALCcontext_IncRef(ctx
);
2883 ctx
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
2885 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
2896 * Returns the currently active context for this thread, and adds a reference
2897 * without locking it.
2899 ALCcontext
*GetContextRef(void)
2901 ALCcontext
*context
;
2903 context
= altss_get(LocalContext
);
2905 ALCcontext_IncRef(context
);
2909 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2911 ALCcontext_IncRef(context
);
2919 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2921 ALCdevice
*device
= context
->Device
;
2922 ALsizei num_sends
= device
->NumAuxSends
;
2923 struct ALvoiceProps
*props
;
2924 size_t sizeof_props
;
2925 size_t sizeof_voice
;
2931 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2934 /* Allocate the voice pointers, voices, and the voices' stored source
2935 * property set (including the dynamically-sized Send[] array) in one
2938 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2939 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2940 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2942 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2943 /* The voice and property objects are stored interleaved since they're
2946 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2947 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2951 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2952 const ALsizei s_count
= mini(old_sends
, num_sends
);
2954 for(;v
< v_count
;v
++)
2956 ALvoice
*old_voice
= context
->Voices
[v
];
2959 /* Copy the old voice data and source property set to the new
2962 *voice
= *old_voice
;
2963 for(i
= 0;i
< s_count
;i
++)
2964 voice
->Send
[i
] = old_voice
->Send
[i
];
2965 *props
= *(old_voice
->Props
);
2966 for(i
= 0;i
< s_count
;i
++)
2967 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2969 /* Set this voice's property set pointer and voice reference. */
2970 voice
->Props
= props
;
2973 /* Increment pointers to the next storage space. */
2974 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2975 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2977 /* Deinit any left over voices that weren't copied over to the new
2978 * array. NOTE: If this does anything, v equals num_voices and
2979 * num_voices is less than VoiceCount, so the following loop won't do
2982 for(;v
< context
->VoiceCount
;v
++)
2983 DeinitVoice(context
->Voices
[v
]);
2985 /* Finish setting the voices' property set pointers and references. */
2986 for(;v
< num_voices
;v
++)
2988 ATOMIC_INIT(&voice
->Update
, NULL
);
2990 voice
->Props
= props
;
2993 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2994 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2997 al_free(context
->Voices
);
2998 context
->Voices
= voices
;
2999 context
->MaxVoices
= num_voices
;
3000 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
3004 /************************************************
3005 * Standard ALC functions
3006 ************************************************/
3010 * Return last ALC generated error code for the given device
3012 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
3016 if(VerifyDevice(&device
))
3018 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3019 ALCdevice_DecRef(device
);
3022 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
3028 /* alcSuspendContext
3030 * Suspends updates for the given context
3032 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
3037 if(!VerifyContext(&context
))
3038 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3041 ALCcontext_DeferUpdates(context
);
3042 ALCcontext_DecRef(context
);
3046 /* alcProcessContext
3048 * Resumes processing updates for the given context
3050 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
3055 if(!VerifyContext(&context
))
3056 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3059 ALCcontext_ProcessUpdates(context
);
3060 ALCcontext_DecRef(context
);
3067 * Returns information about the device, and error strings
3069 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
3071 const ALCchar
*value
= NULL
;
3079 case ALC_INVALID_ENUM
:
3080 value
= alcErrInvalidEnum
;
3083 case ALC_INVALID_VALUE
:
3084 value
= alcErrInvalidValue
;
3087 case ALC_INVALID_DEVICE
:
3088 value
= alcErrInvalidDevice
;
3091 case ALC_INVALID_CONTEXT
:
3092 value
= alcErrInvalidContext
;
3095 case ALC_OUT_OF_MEMORY
:
3096 value
= alcErrOutOfMemory
;
3099 case ALC_DEVICE_SPECIFIER
:
3100 value
= alcDefaultName
;
3103 case ALC_ALL_DEVICES_SPECIFIER
:
3104 if(VerifyDevice(&Device
))
3106 value
= alstr_get_cstr(Device
->DeviceName
);
3107 ALCdevice_DecRef(Device
);
3111 ProbeAllDevicesList();
3112 value
= alstr_get_cstr(alcAllDevicesList
);
3116 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3117 if(VerifyDevice(&Device
))
3119 value
= alstr_get_cstr(Device
->DeviceName
);
3120 ALCdevice_DecRef(Device
);
3124 ProbeCaptureDeviceList();
3125 value
= alstr_get_cstr(alcCaptureDeviceList
);
3129 /* Default devices are always first in the list */
3130 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3131 value
= alcDefaultName
;
3134 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3135 if(alstr_empty(alcAllDevicesList
))
3136 ProbeAllDevicesList();
3138 VerifyDevice(&Device
);
3140 free(alcDefaultAllDevicesSpecifier
);
3141 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3142 if(!alcDefaultAllDevicesSpecifier
)
3143 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3145 value
= alcDefaultAllDevicesSpecifier
;
3146 if(Device
) ALCdevice_DecRef(Device
);
3149 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3150 if(alstr_empty(alcCaptureDeviceList
))
3151 ProbeCaptureDeviceList();
3153 VerifyDevice(&Device
);
3155 free(alcCaptureDefaultDeviceSpecifier
);
3156 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3157 if(!alcCaptureDefaultDeviceSpecifier
)
3158 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3160 value
= alcCaptureDefaultDeviceSpecifier
;
3161 if(Device
) ALCdevice_DecRef(Device
);
3164 case ALC_EXTENSIONS
:
3165 if(!VerifyDevice(&Device
))
3166 value
= alcNoDeviceExtList
;
3169 value
= alcExtensionList
;
3170 ALCdevice_DecRef(Device
);
3174 case ALC_HRTF_SPECIFIER_SOFT
:
3175 if(!VerifyDevice(&Device
))
3176 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3179 almtx_lock(&Device
->BackendLock
);
3180 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3181 almtx_unlock(&Device
->BackendLock
);
3182 ALCdevice_DecRef(Device
);
3187 VerifyDevice(&Device
);
3188 alcSetError(Device
, ALC_INVALID_ENUM
);
3189 if(Device
) ALCdevice_DecRef(Device
);
3197 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3199 if(device
->Type
== Capture
) return 9;
3200 if(device
->Type
!= Loopback
) return 29;
3201 if(device
->FmtChans
== DevFmtAmbi3D
)
3206 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3210 if(size
<= 0 || values
== NULL
)
3212 alcSetError(device
, ALC_INVALID_VALUE
);
3220 case ALC_MAJOR_VERSION
:
3221 values
[0] = alcMajorVersion
;
3223 case ALC_MINOR_VERSION
:
3224 values
[0] = alcMinorVersion
;
3227 case ALC_ATTRIBUTES_SIZE
:
3228 case ALC_ALL_ATTRIBUTES
:
3232 case ALC_MONO_SOURCES
:
3233 case ALC_STEREO_SOURCES
:
3234 case ALC_CAPTURE_SAMPLES
:
3235 case ALC_FORMAT_CHANNELS_SOFT
:
3236 case ALC_FORMAT_TYPE_SOFT
:
3237 case ALC_AMBISONIC_LAYOUT_SOFT
:
3238 case ALC_AMBISONIC_SCALING_SOFT
:
3239 case ALC_AMBISONIC_ORDER_SOFT
:
3240 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3241 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3245 alcSetError(NULL
, ALC_INVALID_ENUM
);
3251 if(device
->Type
== Capture
)
3255 case ALC_ATTRIBUTES_SIZE
:
3256 values
[0] = NumAttrsForDevice(device
);
3259 case ALC_ALL_ATTRIBUTES
:
3260 if(size
< NumAttrsForDevice(device
))
3262 alcSetError(device
, ALC_INVALID_VALUE
);
3267 almtx_lock(&device
->BackendLock
);
3268 values
[i
++] = ALC_MAJOR_VERSION
;
3269 values
[i
++] = alcMajorVersion
;
3270 values
[i
++] = ALC_MINOR_VERSION
;
3271 values
[i
++] = alcMinorVersion
;
3272 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3273 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3274 values
[i
++] = ALC_CONNECTED
;
3275 values
[i
++] = ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
);
3276 almtx_unlock(&device
->BackendLock
);
3281 case ALC_MAJOR_VERSION
:
3282 values
[0] = alcMajorVersion
;
3284 case ALC_MINOR_VERSION
:
3285 values
[0] = alcMinorVersion
;
3288 case ALC_CAPTURE_SAMPLES
:
3289 almtx_lock(&device
->BackendLock
);
3290 values
[0] = V0(device
->Backend
,availableSamples
)();
3291 almtx_unlock(&device
->BackendLock
);
3295 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3299 alcSetError(device
, ALC_INVALID_ENUM
);
3308 case ALC_ATTRIBUTES_SIZE
:
3309 values
[0] = NumAttrsForDevice(device
);
3312 case ALC_ALL_ATTRIBUTES
:
3313 if(size
< NumAttrsForDevice(device
))
3315 alcSetError(device
, ALC_INVALID_VALUE
);
3320 almtx_lock(&device
->BackendLock
);
3321 values
[i
++] = ALC_MAJOR_VERSION
;
3322 values
[i
++] = alcMajorVersion
;
3323 values
[i
++] = ALC_MINOR_VERSION
;
3324 values
[i
++] = alcMinorVersion
;
3325 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3326 values
[i
++] = alcEFXMajorVersion
;
3327 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3328 values
[i
++] = alcEFXMinorVersion
;
3330 values
[i
++] = ALC_FREQUENCY
;
3331 values
[i
++] = device
->Frequency
;
3332 if(device
->Type
!= Loopback
)
3334 values
[i
++] = ALC_REFRESH
;
3335 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3337 values
[i
++] = ALC_SYNC
;
3338 values
[i
++] = ALC_FALSE
;
3342 if(device
->FmtChans
== DevFmtAmbi3D
)
3344 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3345 values
[i
++] = device
->AmbiLayout
;
3347 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3348 values
[i
++] = device
->AmbiScale
;
3350 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3351 values
[i
++] = device
->AmbiOrder
;
3354 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3355 values
[i
++] = device
->FmtChans
;
3357 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3358 values
[i
++] = device
->FmtType
;
3361 values
[i
++] = ALC_MONO_SOURCES
;
3362 values
[i
++] = device
->NumMonoSources
;
3364 values
[i
++] = ALC_STEREO_SOURCES
;
3365 values
[i
++] = device
->NumStereoSources
;
3367 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3368 values
[i
++] = device
->NumAuxSends
;
3370 values
[i
++] = ALC_HRTF_SOFT
;
3371 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3373 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3374 values
[i
++] = device
->HrtfStatus
;
3376 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3377 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3379 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3380 values
[i
++] = MAX_AMBI_ORDER
;
3381 almtx_unlock(&device
->BackendLock
);
3386 case ALC_MAJOR_VERSION
:
3387 values
[0] = alcMajorVersion
;
3390 case ALC_MINOR_VERSION
:
3391 values
[0] = alcMinorVersion
;
3394 case ALC_EFX_MAJOR_VERSION
:
3395 values
[0] = alcEFXMajorVersion
;
3398 case ALC_EFX_MINOR_VERSION
:
3399 values
[0] = alcEFXMinorVersion
;
3403 values
[0] = device
->Frequency
;
3407 if(device
->Type
== Loopback
)
3409 alcSetError(device
, ALC_INVALID_DEVICE
);
3412 almtx_lock(&device
->BackendLock
);
3413 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3414 almtx_unlock(&device
->BackendLock
);
3418 if(device
->Type
== Loopback
)
3420 alcSetError(device
, ALC_INVALID_DEVICE
);
3423 values
[0] = ALC_FALSE
;
3426 case ALC_FORMAT_CHANNELS_SOFT
:
3427 if(device
->Type
!= Loopback
)
3429 alcSetError(device
, ALC_INVALID_DEVICE
);
3432 values
[0] = device
->FmtChans
;
3435 case ALC_FORMAT_TYPE_SOFT
:
3436 if(device
->Type
!= Loopback
)
3438 alcSetError(device
, ALC_INVALID_DEVICE
);
3441 values
[0] = device
->FmtType
;
3444 case ALC_AMBISONIC_LAYOUT_SOFT
:
3445 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3447 alcSetError(device
, ALC_INVALID_DEVICE
);
3450 values
[0] = device
->AmbiLayout
;
3453 case ALC_AMBISONIC_SCALING_SOFT
:
3454 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3456 alcSetError(device
, ALC_INVALID_DEVICE
);
3459 values
[0] = device
->AmbiScale
;
3462 case ALC_AMBISONIC_ORDER_SOFT
:
3463 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3465 alcSetError(device
, ALC_INVALID_DEVICE
);
3468 values
[0] = device
->AmbiOrder
;
3471 case ALC_MONO_SOURCES
:
3472 values
[0] = device
->NumMonoSources
;
3475 case ALC_STEREO_SOURCES
:
3476 values
[0] = device
->NumStereoSources
;
3479 case ALC_MAX_AUXILIARY_SENDS
:
3480 values
[0] = device
->NumAuxSends
;
3484 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3488 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3491 case ALC_HRTF_STATUS_SOFT
:
3492 values
[0] = device
->HrtfStatus
;
3495 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3496 almtx_lock(&device
->BackendLock
);
3497 FreeHrtfList(&device
->HrtfList
);
3498 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3499 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3500 almtx_unlock(&device
->BackendLock
);
3503 case ALC_OUTPUT_LIMITER_SOFT
:
3504 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3507 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3508 values
[0] = MAX_AMBI_ORDER
;
3512 alcSetError(device
, ALC_INVALID_ENUM
);
3520 * Returns information about the device and the version of OpenAL
3522 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3524 VerifyDevice(&device
);
3525 if(size
<= 0 || values
== NULL
)
3526 alcSetError(device
, ALC_INVALID_VALUE
);
3528 GetIntegerv(device
, param
, size
, values
);
3529 if(device
) ALCdevice_DecRef(device
);
3532 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3537 VerifyDevice(&device
);
3538 if(size
<= 0 || values
== NULL
)
3539 alcSetError(device
, ALC_INVALID_VALUE
);
3540 else if(!device
|| device
->Type
== Capture
)
3542 ivals
= malloc(size
* sizeof(ALCint
));
3543 size
= GetIntegerv(device
, pname
, size
, ivals
);
3544 for(i
= 0;i
< size
;i
++)
3545 values
[i
] = ivals
[i
];
3548 else /* render device */
3557 case ALC_ATTRIBUTES_SIZE
:
3558 *values
= NumAttrsForDevice(device
)+4;
3561 case ALC_ALL_ATTRIBUTES
:
3562 if(size
< NumAttrsForDevice(device
)+4)
3563 alcSetError(device
, ALC_INVALID_VALUE
);
3567 almtx_lock(&device
->BackendLock
);
3568 values
[i
++] = ALC_FREQUENCY
;
3569 values
[i
++] = device
->Frequency
;
3571 if(device
->Type
!= Loopback
)
3573 values
[i
++] = ALC_REFRESH
;
3574 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3576 values
[i
++] = ALC_SYNC
;
3577 values
[i
++] = ALC_FALSE
;
3581 if(device
->FmtChans
== DevFmtAmbi3D
)
3583 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3584 values
[i
++] = device
->AmbiLayout
;
3586 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3587 values
[i
++] = device
->AmbiScale
;
3589 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3590 values
[i
++] = device
->AmbiOrder
;
3593 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3594 values
[i
++] = device
->FmtChans
;
3596 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3597 values
[i
++] = device
->FmtType
;
3600 values
[i
++] = ALC_MONO_SOURCES
;
3601 values
[i
++] = device
->NumMonoSources
;
3603 values
[i
++] = ALC_STEREO_SOURCES
;
3604 values
[i
++] = device
->NumStereoSources
;
3606 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3607 values
[i
++] = device
->NumAuxSends
;
3609 values
[i
++] = ALC_HRTF_SOFT
;
3610 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3612 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3613 values
[i
++] = device
->HrtfStatus
;
3615 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3616 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3618 clock
= V0(device
->Backend
,getClockLatency
)();
3619 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3620 values
[i
++] = clock
.ClockTime
;
3622 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3623 values
[i
++] = clock
.Latency
;
3624 almtx_unlock(&device
->BackendLock
);
3630 case ALC_DEVICE_CLOCK_SOFT
:
3631 almtx_lock(&device
->BackendLock
);
3633 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3635 basecount
= device
->ClockBase
;
3636 samplecount
= device
->SamplesDone
;
3637 } while(refcount
!= ReadRef(&device
->MixCount
));
3638 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3639 almtx_unlock(&device
->BackendLock
);
3642 case ALC_DEVICE_LATENCY_SOFT
:
3643 almtx_lock(&device
->BackendLock
);
3644 clock
= V0(device
->Backend
,getClockLatency
)();
3645 almtx_unlock(&device
->BackendLock
);
3646 *values
= clock
.Latency
;
3649 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3651 alcSetError(device
, ALC_INVALID_VALUE
);
3654 almtx_lock(&device
->BackendLock
);
3655 clock
= V0(device
->Backend
,getClockLatency
)();
3656 almtx_unlock(&device
->BackendLock
);
3657 values
[0] = clock
.ClockTime
;
3658 values
[1] = clock
.Latency
;
3663 ivals
= malloc(size
* sizeof(ALCint
));
3664 size
= GetIntegerv(device
, pname
, size
, ivals
);
3665 for(i
= 0;i
< size
;i
++)
3666 values
[i
] = ivals
[i
];
3672 ALCdevice_DecRef(device
);
3676 /* alcIsExtensionPresent
3678 * Determines if there is support for a particular extension
3680 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3682 ALCboolean bResult
= ALC_FALSE
;
3684 VerifyDevice(&device
);
3687 alcSetError(device
, ALC_INVALID_VALUE
);
3690 size_t len
= strlen(extName
);
3691 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3694 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3695 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3700 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3704 } while(isspace(*ptr
));
3709 ALCdevice_DecRef(device
);
3714 /* alcGetProcAddress
3716 * Retrieves the function address for a particular extension function
3718 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3720 ALCvoid
*ptr
= NULL
;
3724 VerifyDevice(&device
);
3725 alcSetError(device
, ALC_INVALID_VALUE
);
3726 if(device
) ALCdevice_DecRef(device
);
3731 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3733 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3735 ptr
= alcFunctions
[i
].address
;
3747 * Get the value for a particular ALC enumeration name
3749 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3755 VerifyDevice(&device
);
3756 alcSetError(device
, ALC_INVALID_VALUE
);
3757 if(device
) ALCdevice_DecRef(device
);
3762 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3764 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3766 val
= alcEnumerations
[i
].value
;
3778 * Create and attach a context to the given device.
3780 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3782 ALCcontext
*ALContext
;
3786 /* Explicitly hold the list lock while taking the BackendLock in case the
3787 * device is asynchronously destropyed, to ensure this new context is
3788 * properly cleaned up after being made.
3791 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3792 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
3795 alcSetError(device
, ALC_INVALID_DEVICE
);
3796 if(device
) ALCdevice_DecRef(device
);
3799 almtx_lock(&device
->BackendLock
);
3802 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3804 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3805 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3807 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3810 almtx_unlock(&device
->BackendLock
);
3812 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3813 ALCdevice_DecRef(device
);
3817 InitRef(&ALContext
->ref
, 1);
3818 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3819 ALContext
->DefaultSlot
= NULL
;
3821 ALContext
->Voices
= NULL
;
3822 ALContext
->VoiceCount
= 0;
3823 ALContext
->MaxVoices
= 0;
3824 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3825 ALContext
->Device
= device
;
3826 ATOMIC_INIT(&ALContext
->next
, NULL
);
3828 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3830 almtx_unlock(&device
->BackendLock
);
3835 alcSetError(device
, err
);
3836 if(err
== ALC_INVALID_DEVICE
)
3838 V0(device
->Backend
,lock
)();
3839 aluHandleDisconnect(device
, "Device update failure");
3840 V0(device
->Backend
,unlock
)();
3842 ALCdevice_DecRef(device
);
3845 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3847 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3849 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3850 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3851 aluInitEffectPanning(ALContext
->DefaultSlot
);
3854 ALContext
->DefaultSlot
= NULL
;
3855 ERR("Failed to initialize the default effect slot\n");
3859 ALCdevice_IncRef(ALContext
->Device
);
3860 InitContext(ALContext
);
3862 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3865 ERR("volume-adjust must be finite: %f\n", valf
);
3868 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3870 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3871 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3872 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3875 UpdateListenerProps(ALContext
);
3878 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3880 ATOMIC_STORE(&ALContext
->next
, head
, almemory_order_relaxed
);
3881 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3884 almtx_unlock(&device
->BackendLock
);
3886 if(ALContext
->DefaultSlot
)
3888 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3889 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3891 ERR("Failed to initialize the default effect\n");
3894 ALCdevice_DecRef(device
);
3896 TRACE("Created context %p\n", ALContext
);
3900 /* alcDestroyContext
3902 * Remove a context from its device
3904 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3909 if(!VerifyContext(&context
))
3912 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3916 Device
= context
->Device
;
3919 almtx_lock(&Device
->BackendLock
);
3920 if(!ReleaseContext(context
, Device
))
3922 V0(Device
->Backend
,stop
)();
3923 Device
->Flags
&= ~DEVICE_RUNNING
;
3925 almtx_unlock(&Device
->BackendLock
);
3929 ALCcontext_DecRef(context
);
3933 /* alcGetCurrentContext
3935 * Returns the currently active context on the calling thread
3937 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3939 ALCcontext
*Context
= altss_get(LocalContext
);
3940 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3944 /* alcGetThreadContext
3946 * Returns the currently active thread-local context
3948 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3950 return altss_get(LocalContext
);
3954 /* alcMakeContextCurrent
3956 * Makes the given context the active process-wide context, and removes the
3957 * thread-local context for the calling thread.
3959 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3961 /* context must be valid or NULL */
3962 if(context
&& !VerifyContext(&context
))
3964 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3967 /* context's reference count is already incremented */
3968 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3969 if(context
) ALCcontext_DecRef(context
);
3971 if((context
=altss_get(LocalContext
)) != NULL
)
3973 altss_set(LocalContext
, NULL
);
3974 ALCcontext_DecRef(context
);
3980 /* alcSetThreadContext
3982 * Makes the given context the active context for the current thread
3984 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3988 /* context must be valid or NULL */
3989 if(context
&& !VerifyContext(&context
))
3991 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3994 /* context's reference count is already incremented */
3995 old
= altss_get(LocalContext
);
3996 altss_set(LocalContext
, context
);
3997 if(old
) ALCcontext_DecRef(old
);
4003 /* alcGetContextsDevice
4005 * Returns the device that a particular context is attached to
4007 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
4011 if(!VerifyContext(&Context
))
4013 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
4016 Device
= Context
->Device
;
4017 ALCcontext_DecRef(Context
);
4025 * Opens the named device.
4027 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
4029 ALCbackendFactory
*factory
;
4036 if(!PlaybackBackend
.name
)
4038 alcSetError(NULL
, ALC_INVALID_VALUE
);
4042 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
4044 /* Some old Windows apps hardcode these expecting OpenAL to use a
4045 * specific audio API, even when they're not enumerated. Creative's
4046 * router effectively ignores them too.
4048 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
4049 || strcasecmp(deviceName
, "MMSYSTEM") == 0
4054 device
= al_calloc(16, sizeof(ALCdevice
));
4057 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4062 InitDevice(device
, Playback
);
4065 device
->FmtChans
= DevFmtChannelsDefault
;
4066 device
->FmtType
= DevFmtTypeDefault
;
4067 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4068 device
->IsHeadphones
= AL_FALSE
;
4069 device
->AmbiLayout
= AmbiLayout_Default
;
4070 device
->AmbiScale
= AmbiNorm_Default
;
4071 device
->NumUpdates
= 3;
4072 device
->UpdateSize
= 1024;
4074 device
->SourcesMax
= 256;
4075 device
->AuxiliaryEffectSlotMax
= 64;
4076 device
->NumAuxSends
= DEFAULT_SENDS
;
4078 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
4080 static const struct {
4081 const char name
[16];
4082 enum DevFmtChannels chans
;
4085 { "mono", DevFmtMono
, 0 },
4086 { "stereo", DevFmtStereo
, 0 },
4087 { "quad", DevFmtQuad
, 0 },
4088 { "surround51", DevFmtX51
, 0 },
4089 { "surround61", DevFmtX61
, 0 },
4090 { "surround71", DevFmtX71
, 0 },
4091 { "surround51rear", DevFmtX51Rear
, 0 },
4092 { "ambi1", DevFmtAmbi3D
, 1 },
4093 { "ambi2", DevFmtAmbi3D
, 2 },
4094 { "ambi3", DevFmtAmbi3D
, 3 },
4098 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4100 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4102 device
->FmtChans
= chanlist
[i
].chans
;
4103 device
->AmbiOrder
= chanlist
[i
].order
;
4104 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4108 if(i
== COUNTOF(chanlist
))
4109 ERR("Unsupported channels: %s\n", fmt
);
4111 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4113 static const struct {
4114 const char name
[16];
4115 enum DevFmtType type
;
4117 { "int8", DevFmtByte
},
4118 { "uint8", DevFmtUByte
},
4119 { "int16", DevFmtShort
},
4120 { "uint16", DevFmtUShort
},
4121 { "int32", DevFmtInt
},
4122 { "uint32", DevFmtUInt
},
4123 { "float32", DevFmtFloat
},
4127 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4129 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4131 device
->FmtType
= typelist
[i
].type
;
4132 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4136 if(i
== COUNTOF(typelist
))
4137 ERR("Unsupported sample-type: %s\n", fmt
);
4140 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4142 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4143 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4144 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4145 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4148 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4149 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4151 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4152 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4153 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4154 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4156 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4157 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4159 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4160 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4161 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4163 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4164 device
->NumAuxSends
= clampi(
4165 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4168 device
->NumStereoSources
= 1;
4169 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4171 factory
= PlaybackBackend
.getFactory();
4172 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
4173 if(!device
->Backend
)
4176 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4180 // Find a playback device to open
4181 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4184 alcSetError(NULL
, err
);
4188 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4190 if(strcasecmp(fmt
, "fuma") == 0)
4192 device
->AmbiLayout
= AmbiLayout_FuMa
;
4193 device
->AmbiScale
= AmbiNorm_FuMa
;
4195 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4197 device
->AmbiLayout
= AmbiLayout_ACN
;
4198 device
->AmbiScale
= AmbiNorm_SN3D
;
4200 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4202 device
->AmbiLayout
= AmbiLayout_ACN
;
4203 device
->AmbiScale
= AmbiNorm_N3D
;
4206 ERR("Unsupported ambi-format: %s\n", fmt
);
4209 device
->Limiter
= CreateDeviceLimiter(device
);
4212 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4214 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4215 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4218 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4224 * Closes the given device.
4226 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4228 ALCdevice
*iter
, *origdev
, *nextdev
;
4232 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4236 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4237 } while(iter
!= NULL
);
4238 if(!iter
|| iter
->Type
== Capture
)
4240 alcSetError(iter
, ALC_INVALID_DEVICE
);
4244 almtx_lock(&device
->BackendLock
);
4247 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4248 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4254 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4258 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4261 ALCcontext
*next
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
4262 WARN("Releasing context %p\n", ctx
);
4263 ReleaseContext(ctx
, device
);
4266 if((device
->Flags
&DEVICE_RUNNING
))
4267 V0(device
->Backend
,stop
)();
4268 device
->Flags
&= ~DEVICE_RUNNING
;
4269 almtx_unlock(&device
->BackendLock
);
4271 ALCdevice_DecRef(device
);
4277 /************************************************
4278 * ALC capture functions
4279 ************************************************/
4280 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4282 ALCbackendFactory
*factory
;
4283 ALCdevice
*device
= NULL
;
4288 if(!CaptureBackend
.name
)
4290 alcSetError(NULL
, ALC_INVALID_VALUE
);
4296 alcSetError(NULL
, ALC_INVALID_VALUE
);
4300 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4303 device
= al_calloc(16, sizeof(ALCdevice
));
4306 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4311 InitDevice(device
, Capture
);
4313 device
->Frequency
= frequency
;
4314 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4316 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4319 alcSetError(NULL
, ALC_INVALID_ENUM
);
4322 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4323 device
->IsHeadphones
= AL_FALSE
;
4324 device
->AmbiOrder
= 0;
4325 device
->AmbiLayout
= AmbiLayout_Default
;
4326 device
->AmbiScale
= AmbiNorm_Default
;
4328 device
->UpdateSize
= samples
;
4329 device
->NumUpdates
= 1;
4331 factory
= CaptureBackend
.getFactory();
4332 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4333 if(!device
->Backend
)
4336 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4340 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4341 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4342 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4344 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4347 alcSetError(NULL
, err
);
4352 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4354 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4355 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4358 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4362 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4364 ALCdevice
*iter
, *origdev
, *nextdev
;
4367 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4371 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4372 } while(iter
!= NULL
);
4373 if(!iter
|| iter
->Type
!= Capture
)
4375 alcSetError(iter
, ALC_INVALID_DEVICE
);
4381 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4382 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4388 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4392 ALCdevice_DecRef(device
);
4397 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4399 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4400 alcSetError(device
, ALC_INVALID_DEVICE
);
4403 almtx_lock(&device
->BackendLock
);
4404 if(!ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
))
4405 alcSetError(device
, ALC_INVALID_DEVICE
);
4406 else if(!(device
->Flags
&DEVICE_RUNNING
))
4408 if(V0(device
->Backend
,start
)())
4409 device
->Flags
|= DEVICE_RUNNING
;
4412 aluHandleDisconnect(device
, "Device start failure");
4413 alcSetError(device
, ALC_INVALID_DEVICE
);
4416 almtx_unlock(&device
->BackendLock
);
4419 if(device
) ALCdevice_DecRef(device
);
4422 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4424 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4425 alcSetError(device
, ALC_INVALID_DEVICE
);
4428 almtx_lock(&device
->BackendLock
);
4429 if((device
->Flags
&DEVICE_RUNNING
))
4430 V0(device
->Backend
,stop
)();
4431 device
->Flags
&= ~DEVICE_RUNNING
;
4432 almtx_unlock(&device
->BackendLock
);
4435 if(device
) ALCdevice_DecRef(device
);
4438 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4440 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4441 alcSetError(device
, ALC_INVALID_DEVICE
);
4444 ALCenum err
= ALC_INVALID_VALUE
;
4446 almtx_lock(&device
->BackendLock
);
4447 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4448 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4449 almtx_unlock(&device
->BackendLock
);
4451 if(err
!= ALC_NO_ERROR
)
4452 alcSetError(device
, err
);
4454 if(device
) ALCdevice_DecRef(device
);
4458 /************************************************
4459 * ALC loopback functions
4460 ************************************************/
4462 /* alcLoopbackOpenDeviceSOFT
4464 * Open a loopback device, for manual rendering.
4466 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4468 ALCbackendFactory
*factory
;
4473 /* Make sure the device name, if specified, is us. */
4474 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4476 alcSetError(NULL
, ALC_INVALID_VALUE
);
4480 device
= al_calloc(16, sizeof(ALCdevice
));
4483 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4488 InitDevice(device
, Loopback
);
4490 device
->SourcesMax
= 256;
4491 device
->AuxiliaryEffectSlotMax
= 64;
4492 device
->NumAuxSends
= DEFAULT_SENDS
;
4495 device
->NumUpdates
= 0;
4496 device
->UpdateSize
= 0;
4498 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4499 device
->FmtChans
= DevFmtChannelsDefault
;
4500 device
->FmtType
= DevFmtTypeDefault
;
4501 device
->IsHeadphones
= AL_FALSE
;
4502 device
->AmbiLayout
= AmbiLayout_Default
;
4503 device
->AmbiScale
= AmbiNorm_Default
;
4505 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4506 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4508 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4509 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4510 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4512 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4513 device
->NumAuxSends
= clampi(
4514 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4517 device
->NumStereoSources
= 1;
4518 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4520 factory
= ALCloopbackFactory_getFactory();
4521 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4522 if(!device
->Backend
)
4525 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4529 // Open the "backend"
4530 V(device
->Backend
,open
)("Loopback");
4532 device
->Limiter
= CreateDeviceLimiter(device
);
4535 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4537 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4538 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4541 TRACE("Created device %p\n", device
);
4545 /* alcIsRenderFormatSupportedSOFT
4547 * Determines if the loopback device supports the given format for rendering.
4549 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4551 ALCboolean ret
= ALC_FALSE
;
4553 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4554 alcSetError(device
, ALC_INVALID_DEVICE
);
4556 alcSetError(device
, ALC_INVALID_VALUE
);
4559 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4562 if(device
) ALCdevice_DecRef(device
);
4567 /* alcRenderSamplesSOFT
4569 * Renders some samples into a buffer, using the format last set by the
4570 * attributes given to alcCreateContext.
4572 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4574 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4575 alcSetError(device
, ALC_INVALID_DEVICE
);
4576 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4577 alcSetError(device
, ALC_INVALID_VALUE
);
4580 V0(device
->Backend
,lock
)();
4581 aluMixData(device
, buffer
, samples
);
4582 V0(device
->Backend
,unlock
)();
4584 if(device
) ALCdevice_DecRef(device
);
4588 /************************************************
4589 * ALC DSP pause/resume functions
4590 ************************************************/
4592 /* alcDevicePauseSOFT
4594 * Pause the DSP to stop audio processing.
4596 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4598 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4599 alcSetError(device
, ALC_INVALID_DEVICE
);
4602 almtx_lock(&device
->BackendLock
);
4603 if((device
->Flags
&DEVICE_RUNNING
))
4604 V0(device
->Backend
,stop
)();
4605 device
->Flags
&= ~DEVICE_RUNNING
;
4606 device
->Flags
|= DEVICE_PAUSED
;
4607 almtx_unlock(&device
->BackendLock
);
4609 if(device
) ALCdevice_DecRef(device
);
4612 /* alcDeviceResumeSOFT
4614 * Resume the DSP to restart audio processing.
4616 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4618 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4619 alcSetError(device
, ALC_INVALID_DEVICE
);
4622 almtx_lock(&device
->BackendLock
);
4623 if((device
->Flags
&DEVICE_PAUSED
))
4625 device
->Flags
&= ~DEVICE_PAUSED
;
4626 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4628 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4629 device
->Flags
|= DEVICE_RUNNING
;
4632 V0(device
->Backend
,lock
)();
4633 aluHandleDisconnect(device
, "Device start failure");
4634 V0(device
->Backend
,unlock
)();
4635 alcSetError(device
, ALC_INVALID_DEVICE
);
4639 almtx_unlock(&device
->BackendLock
);
4641 if(device
) ALCdevice_DecRef(device
);
4645 /************************************************
4646 * ALC HRTF functions
4647 ************************************************/
4649 /* alcGetStringiSOFT
4651 * Gets a string parameter at the given index.
4653 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4655 const ALCchar
*str
= NULL
;
4657 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4658 alcSetError(device
, ALC_INVALID_DEVICE
);
4659 else switch(paramName
)
4661 case ALC_HRTF_SPECIFIER_SOFT
:
4662 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4663 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4665 alcSetError(device
, ALC_INVALID_VALUE
);
4669 alcSetError(device
, ALC_INVALID_ENUM
);
4672 if(device
) ALCdevice_DecRef(device
);
4677 /* alcResetDeviceSOFT
4679 * Resets the given device output, using the specified attribute list.
4681 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4686 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4687 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
4690 alcSetError(device
, ALC_INVALID_DEVICE
);
4691 if(device
) ALCdevice_DecRef(device
);
4694 almtx_lock(&device
->BackendLock
);
4697 err
= UpdateDeviceParams(device
, attribs
);
4698 almtx_unlock(&device
->BackendLock
);
4700 if(err
!= ALC_NO_ERROR
)
4702 alcSetError(device
, err
);
4703 if(err
== ALC_INVALID_DEVICE
)
4705 V0(device
->Backend
,lock
)();
4706 aluHandleDisconnect(device
, "Device start failure");
4707 V0(device
->Backend
,unlock
)();
4709 ALCdevice_DecRef(device
);
4712 ALCdevice_DecRef(device
);