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"
39 #include "alAuxEffectSlot.h"
41 #include "mastering.h"
42 #include "bformatdec.h"
45 #include "ringbuffer.h"
47 #include "fpu_modes.h"
54 #include "backends/base.h"
57 /************************************************
59 ************************************************/
62 ALCbackendFactory
* (*getFactory
)(void);
65 static struct BackendInfo BackendList
[] = {
67 { "jack", ALCjackBackendFactory_getFactory
},
69 #ifdef HAVE_PULSEAUDIO
70 { "pulse", ALCpulseBackendFactory_getFactory
},
73 { "alsa", ALCalsaBackendFactory_getFactory
},
76 { "core", ALCcoreAudioBackendFactory_getFactory
},
79 { "oss", ALCossBackendFactory_getFactory
},
82 { "solaris", ALCsolarisBackendFactory_getFactory
},
85 { "sndio", ALCsndioBackendFactory_getFactory
},
88 { "qsa", ALCqsaBackendFactory_getFactory
},
91 { "wasapi", ALCwasapiBackendFactory_getFactory
},
94 { "dsound", ALCdsoundBackendFactory_getFactory
},
97 { "winmm", ALCwinmmBackendFactory_getFactory
},
100 { "port", ALCportBackendFactory_getFactory
},
103 { "opensl", ALCopenslBackendFactory_getFactory
},
106 { "sdl2", ALCsdl2BackendFactory_getFactory
},
109 { "null", ALCnullBackendFactory_getFactory
},
111 { "wave", ALCwaveBackendFactory_getFactory
},
114 static ALsizei BackendListSize
= COUNTOF(BackendList
);
117 static struct BackendInfo PlaybackBackend
;
118 static struct BackendInfo CaptureBackend
;
121 /************************************************
122 * Functions, enums, and errors
123 ************************************************/
124 #define DECL(x) { #x, (ALCvoid*)(x) }
125 static const struct {
126 const ALCchar
*funcName
;
129 DECL(alcCreateContext
),
130 DECL(alcMakeContextCurrent
),
131 DECL(alcProcessContext
),
132 DECL(alcSuspendContext
),
133 DECL(alcDestroyContext
),
134 DECL(alcGetCurrentContext
),
135 DECL(alcGetContextsDevice
),
137 DECL(alcCloseDevice
),
139 DECL(alcIsExtensionPresent
),
140 DECL(alcGetProcAddress
),
141 DECL(alcGetEnumValue
),
143 DECL(alcGetIntegerv
),
144 DECL(alcCaptureOpenDevice
),
145 DECL(alcCaptureCloseDevice
),
146 DECL(alcCaptureStart
),
147 DECL(alcCaptureStop
),
148 DECL(alcCaptureSamples
),
150 DECL(alcSetThreadContext
),
151 DECL(alcGetThreadContext
),
153 DECL(alcLoopbackOpenDeviceSOFT
),
154 DECL(alcIsRenderFormatSupportedSOFT
),
155 DECL(alcRenderSamplesSOFT
),
157 DECL(alcDevicePauseSOFT
),
158 DECL(alcDeviceResumeSOFT
),
160 DECL(alcGetStringiSOFT
),
161 DECL(alcResetDeviceSOFT
),
163 DECL(alcGetInteger64vSOFT
),
178 DECL(alIsExtensionPresent
),
179 DECL(alGetProcAddress
),
180 DECL(alGetEnumValue
),
187 DECL(alGetListenerf
),
188 DECL(alGetListener3f
),
189 DECL(alGetListenerfv
),
190 DECL(alGetListeneri
),
191 DECL(alGetListener3i
),
192 DECL(alGetListeneriv
),
194 DECL(alDeleteSources
),
210 DECL(alSourceRewindv
),
211 DECL(alSourcePausev
),
214 DECL(alSourceRewind
),
216 DECL(alSourceQueueBuffers
),
217 DECL(alSourceUnqueueBuffers
),
219 DECL(alDeleteBuffers
),
234 DECL(alDopplerFactor
),
235 DECL(alDopplerVelocity
),
236 DECL(alSpeedOfSound
),
237 DECL(alDistanceModel
),
240 DECL(alDeleteFilters
),
251 DECL(alDeleteEffects
),
261 DECL(alGenAuxiliaryEffectSlots
),
262 DECL(alDeleteAuxiliaryEffectSlots
),
263 DECL(alIsAuxiliaryEffectSlot
),
264 DECL(alAuxiliaryEffectSloti
),
265 DECL(alAuxiliaryEffectSlotiv
),
266 DECL(alAuxiliaryEffectSlotf
),
267 DECL(alAuxiliaryEffectSlotfv
),
268 DECL(alGetAuxiliaryEffectSloti
),
269 DECL(alGetAuxiliaryEffectSlotiv
),
270 DECL(alGetAuxiliaryEffectSlotf
),
271 DECL(alGetAuxiliaryEffectSlotfv
),
273 DECL(alDeferUpdatesSOFT
),
274 DECL(alProcessUpdatesSOFT
),
277 DECL(alSource3dSOFT
),
278 DECL(alSourcedvSOFT
),
279 DECL(alGetSourcedSOFT
),
280 DECL(alGetSource3dSOFT
),
281 DECL(alGetSourcedvSOFT
),
282 DECL(alSourcei64SOFT
),
283 DECL(alSource3i64SOFT
),
284 DECL(alSourcei64vSOFT
),
285 DECL(alGetSourcei64SOFT
),
286 DECL(alGetSource3i64SOFT
),
287 DECL(alGetSourcei64vSOFT
),
289 DECL(alGetStringiSOFT
),
291 DECL(alBufferStorageSOFT
),
292 DECL(alMapBufferSOFT
),
293 DECL(alUnmapBufferSOFT
),
294 DECL(alFlushMappedBufferSOFT
),
296 DECL(alEventControlSOFT
),
297 DECL(alEventCallbackSOFT
),
298 DECL(alGetPointerSOFT
),
299 DECL(alGetPointervSOFT
),
303 #define DECL(x) { #x, (x) }
304 static const struct {
305 const ALCchar
*enumName
;
307 } alcEnumerations
[] = {
312 DECL(ALC_MAJOR_VERSION
),
313 DECL(ALC_MINOR_VERSION
),
314 DECL(ALC_ATTRIBUTES_SIZE
),
315 DECL(ALC_ALL_ATTRIBUTES
),
316 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
317 DECL(ALC_DEVICE_SPECIFIER
),
318 DECL(ALC_ALL_DEVICES_SPECIFIER
),
319 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
320 DECL(ALC_EXTENSIONS
),
324 DECL(ALC_MONO_SOURCES
),
325 DECL(ALC_STEREO_SOURCES
),
326 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
327 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
328 DECL(ALC_CAPTURE_SAMPLES
),
331 DECL(ALC_EFX_MAJOR_VERSION
),
332 DECL(ALC_EFX_MINOR_VERSION
),
333 DECL(ALC_MAX_AUXILIARY_SENDS
),
335 DECL(ALC_FORMAT_CHANNELS_SOFT
),
336 DECL(ALC_FORMAT_TYPE_SOFT
),
339 DECL(ALC_STEREO_SOFT
),
341 DECL(ALC_5POINT1_SOFT
),
342 DECL(ALC_6POINT1_SOFT
),
343 DECL(ALC_7POINT1_SOFT
),
344 DECL(ALC_BFORMAT3D_SOFT
),
347 DECL(ALC_UNSIGNED_BYTE_SOFT
),
348 DECL(ALC_SHORT_SOFT
),
349 DECL(ALC_UNSIGNED_SHORT_SOFT
),
351 DECL(ALC_UNSIGNED_INT_SOFT
),
352 DECL(ALC_FLOAT_SOFT
),
355 DECL(ALC_DONT_CARE_SOFT
),
356 DECL(ALC_HRTF_STATUS_SOFT
),
357 DECL(ALC_HRTF_DISABLED_SOFT
),
358 DECL(ALC_HRTF_ENABLED_SOFT
),
359 DECL(ALC_HRTF_DENIED_SOFT
),
360 DECL(ALC_HRTF_REQUIRED_SOFT
),
361 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
362 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
363 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
364 DECL(ALC_HRTF_SPECIFIER_SOFT
),
365 DECL(ALC_HRTF_ID_SOFT
),
367 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
368 DECL(ALC_AMBISONIC_SCALING_SOFT
),
369 DECL(ALC_AMBISONIC_ORDER_SOFT
),
375 DECL(ALC_OUTPUT_LIMITER_SOFT
),
378 DECL(ALC_INVALID_DEVICE
),
379 DECL(ALC_INVALID_CONTEXT
),
380 DECL(ALC_INVALID_ENUM
),
381 DECL(ALC_INVALID_VALUE
),
382 DECL(ALC_OUT_OF_MEMORY
),
390 DECL(AL_SOURCE_RELATIVE
),
391 DECL(AL_CONE_INNER_ANGLE
),
392 DECL(AL_CONE_OUTER_ANGLE
),
402 DECL(AL_ORIENTATION
),
403 DECL(AL_REFERENCE_DISTANCE
),
404 DECL(AL_ROLLOFF_FACTOR
),
405 DECL(AL_CONE_OUTER_GAIN
),
406 DECL(AL_MAX_DISTANCE
),
408 DECL(AL_SAMPLE_OFFSET
),
409 DECL(AL_BYTE_OFFSET
),
410 DECL(AL_SOURCE_TYPE
),
413 DECL(AL_UNDETERMINED
),
414 DECL(AL_METERS_PER_UNIT
),
415 DECL(AL_LOOP_POINTS_SOFT
),
416 DECL(AL_DIRECT_CHANNELS_SOFT
),
418 DECL(AL_DIRECT_FILTER
),
419 DECL(AL_AUXILIARY_SEND_FILTER
),
420 DECL(AL_AIR_ABSORPTION_FACTOR
),
421 DECL(AL_ROOM_ROLLOFF_FACTOR
),
422 DECL(AL_CONE_OUTER_GAINHF
),
423 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
424 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
425 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
427 DECL(AL_SOURCE_STATE
),
433 DECL(AL_BUFFERS_QUEUED
),
434 DECL(AL_BUFFERS_PROCESSED
),
436 DECL(AL_FORMAT_MONO8
),
437 DECL(AL_FORMAT_MONO16
),
438 DECL(AL_FORMAT_MONO_FLOAT32
),
439 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
440 DECL(AL_FORMAT_STEREO8
),
441 DECL(AL_FORMAT_STEREO16
),
442 DECL(AL_FORMAT_STEREO_FLOAT32
),
443 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
444 DECL(AL_FORMAT_MONO_IMA4
),
445 DECL(AL_FORMAT_STEREO_IMA4
),
446 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
447 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
448 DECL(AL_FORMAT_QUAD8_LOKI
),
449 DECL(AL_FORMAT_QUAD16_LOKI
),
450 DECL(AL_FORMAT_QUAD8
),
451 DECL(AL_FORMAT_QUAD16
),
452 DECL(AL_FORMAT_QUAD32
),
453 DECL(AL_FORMAT_51CHN8
),
454 DECL(AL_FORMAT_51CHN16
),
455 DECL(AL_FORMAT_51CHN32
),
456 DECL(AL_FORMAT_61CHN8
),
457 DECL(AL_FORMAT_61CHN16
),
458 DECL(AL_FORMAT_61CHN32
),
459 DECL(AL_FORMAT_71CHN8
),
460 DECL(AL_FORMAT_71CHN16
),
461 DECL(AL_FORMAT_71CHN32
),
462 DECL(AL_FORMAT_REAR8
),
463 DECL(AL_FORMAT_REAR16
),
464 DECL(AL_FORMAT_REAR32
),
465 DECL(AL_FORMAT_MONO_MULAW
),
466 DECL(AL_FORMAT_MONO_MULAW_EXT
),
467 DECL(AL_FORMAT_STEREO_MULAW
),
468 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
469 DECL(AL_FORMAT_QUAD_MULAW
),
470 DECL(AL_FORMAT_51CHN_MULAW
),
471 DECL(AL_FORMAT_61CHN_MULAW
),
472 DECL(AL_FORMAT_71CHN_MULAW
),
473 DECL(AL_FORMAT_REAR_MULAW
),
474 DECL(AL_FORMAT_MONO_ALAW_EXT
),
475 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
477 DECL(AL_FORMAT_BFORMAT2D_8
),
478 DECL(AL_FORMAT_BFORMAT2D_16
),
479 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
480 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
481 DECL(AL_FORMAT_BFORMAT3D_8
),
482 DECL(AL_FORMAT_BFORMAT3D_16
),
483 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
484 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
490 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
491 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
493 DECL(AL_SOURCE_RADIUS
),
495 DECL(AL_STEREO_ANGLES
),
502 DECL(AL_INVALID_NAME
),
503 DECL(AL_INVALID_ENUM
),
504 DECL(AL_INVALID_VALUE
),
505 DECL(AL_INVALID_OPERATION
),
506 DECL(AL_OUT_OF_MEMORY
),
513 DECL(AL_DOPPLER_FACTOR
),
514 DECL(AL_DOPPLER_VELOCITY
),
515 DECL(AL_DISTANCE_MODEL
),
516 DECL(AL_SPEED_OF_SOUND
),
517 DECL(AL_SOURCE_DISTANCE_MODEL
),
518 DECL(AL_DEFERRED_UPDATES_SOFT
),
519 DECL(AL_GAIN_LIMIT_SOFT
),
521 DECL(AL_INVERSE_DISTANCE
),
522 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
523 DECL(AL_LINEAR_DISTANCE
),
524 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
525 DECL(AL_EXPONENT_DISTANCE
),
526 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
528 DECL(AL_FILTER_TYPE
),
529 DECL(AL_FILTER_NULL
),
530 DECL(AL_FILTER_LOWPASS
),
531 DECL(AL_FILTER_HIGHPASS
),
532 DECL(AL_FILTER_BANDPASS
),
534 DECL(AL_LOWPASS_GAIN
),
535 DECL(AL_LOWPASS_GAINHF
),
537 DECL(AL_HIGHPASS_GAIN
),
538 DECL(AL_HIGHPASS_GAINLF
),
540 DECL(AL_BANDPASS_GAIN
),
541 DECL(AL_BANDPASS_GAINHF
),
542 DECL(AL_BANDPASS_GAINLF
),
544 DECL(AL_EFFECT_TYPE
),
545 DECL(AL_EFFECT_NULL
),
546 DECL(AL_EFFECT_REVERB
),
547 DECL(AL_EFFECT_EAXREVERB
),
548 DECL(AL_EFFECT_CHORUS
),
549 DECL(AL_EFFECT_DISTORTION
),
550 DECL(AL_EFFECT_ECHO
),
551 DECL(AL_EFFECT_FLANGER
),
552 DECL(AL_EFFECT_PITCH_SHIFTER
),
554 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
555 DECL(AL_EFFECT_VOCAL_MORPHER
),
557 DECL(AL_EFFECT_RING_MODULATOR
),
559 DECL(AL_EFFECT_AUTOWAH
),
561 DECL(AL_EFFECT_COMPRESSOR
),
562 DECL(AL_EFFECT_EQUALIZER
),
563 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
564 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
566 DECL(AL_EFFECTSLOT_EFFECT
),
567 DECL(AL_EFFECTSLOT_GAIN
),
568 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
569 DECL(AL_EFFECTSLOT_NULL
),
571 DECL(AL_EAXREVERB_DENSITY
),
572 DECL(AL_EAXREVERB_DIFFUSION
),
573 DECL(AL_EAXREVERB_GAIN
),
574 DECL(AL_EAXREVERB_GAINHF
),
575 DECL(AL_EAXREVERB_GAINLF
),
576 DECL(AL_EAXREVERB_DECAY_TIME
),
577 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
578 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
579 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
580 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
581 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
582 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
583 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
584 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
585 DECL(AL_EAXREVERB_ECHO_TIME
),
586 DECL(AL_EAXREVERB_ECHO_DEPTH
),
587 DECL(AL_EAXREVERB_MODULATION_TIME
),
588 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
589 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
590 DECL(AL_EAXREVERB_HFREFERENCE
),
591 DECL(AL_EAXREVERB_LFREFERENCE
),
592 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
593 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
595 DECL(AL_REVERB_DENSITY
),
596 DECL(AL_REVERB_DIFFUSION
),
597 DECL(AL_REVERB_GAIN
),
598 DECL(AL_REVERB_GAINHF
),
599 DECL(AL_REVERB_DECAY_TIME
),
600 DECL(AL_REVERB_DECAY_HFRATIO
),
601 DECL(AL_REVERB_REFLECTIONS_GAIN
),
602 DECL(AL_REVERB_REFLECTIONS_DELAY
),
603 DECL(AL_REVERB_LATE_REVERB_GAIN
),
604 DECL(AL_REVERB_LATE_REVERB_DELAY
),
605 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
606 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
607 DECL(AL_REVERB_DECAY_HFLIMIT
),
609 DECL(AL_CHORUS_WAVEFORM
),
610 DECL(AL_CHORUS_PHASE
),
611 DECL(AL_CHORUS_RATE
),
612 DECL(AL_CHORUS_DEPTH
),
613 DECL(AL_CHORUS_FEEDBACK
),
614 DECL(AL_CHORUS_DELAY
),
616 DECL(AL_DISTORTION_EDGE
),
617 DECL(AL_DISTORTION_GAIN
),
618 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
619 DECL(AL_DISTORTION_EQCENTER
),
620 DECL(AL_DISTORTION_EQBANDWIDTH
),
623 DECL(AL_ECHO_LRDELAY
),
624 DECL(AL_ECHO_DAMPING
),
625 DECL(AL_ECHO_FEEDBACK
),
626 DECL(AL_ECHO_SPREAD
),
628 DECL(AL_FLANGER_WAVEFORM
),
629 DECL(AL_FLANGER_PHASE
),
630 DECL(AL_FLANGER_RATE
),
631 DECL(AL_FLANGER_DEPTH
),
632 DECL(AL_FLANGER_FEEDBACK
),
633 DECL(AL_FLANGER_DELAY
),
635 DECL(AL_RING_MODULATOR_FREQUENCY
),
636 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
637 DECL(AL_RING_MODULATOR_WAVEFORM
),
639 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
640 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
642 DECL(AL_COMPRESSOR_ONOFF
),
644 DECL(AL_EQUALIZER_LOW_GAIN
),
645 DECL(AL_EQUALIZER_LOW_CUTOFF
),
646 DECL(AL_EQUALIZER_MID1_GAIN
),
647 DECL(AL_EQUALIZER_MID1_CENTER
),
648 DECL(AL_EQUALIZER_MID1_WIDTH
),
649 DECL(AL_EQUALIZER_MID2_GAIN
),
650 DECL(AL_EQUALIZER_MID2_CENTER
),
651 DECL(AL_EQUALIZER_MID2_WIDTH
),
652 DECL(AL_EQUALIZER_HIGH_GAIN
),
653 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
655 DECL(AL_DEDICATED_GAIN
),
657 DECL(AL_NUM_RESAMPLERS_SOFT
),
658 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
659 DECL(AL_SOURCE_RESAMPLER_SOFT
),
660 DECL(AL_RESAMPLER_NAME_SOFT
),
662 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
665 DECL(AL_MAP_READ_BIT_SOFT
),
666 DECL(AL_MAP_WRITE_BIT_SOFT
),
667 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
668 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
670 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
671 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
672 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
673 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
674 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
675 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
676 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
680 static const ALCchar alcNoError
[] = "No Error";
681 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
682 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
683 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
684 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
685 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
688 /************************************************
690 ************************************************/
692 /* Enumerated device names */
693 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
695 static al_string alcAllDevicesList
;
696 static al_string alcCaptureDeviceList
;
698 /* Default is always the first in the list */
699 static ALCchar
*alcDefaultAllDevicesSpecifier
;
700 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
702 /* Default context extensions */
703 static const ALchar alExtList
[] =
707 "AL_EXT_EXPONENT_DISTANCE "
710 "AL_EXT_LINEAR_DISTANCE "
713 "AL_EXT_MULAW_BFORMAT "
714 "AL_EXT_MULAW_MCFORMATS "
716 "AL_EXT_source_distance_model "
717 "AL_EXT_SOURCE_RADIUS "
718 "AL_EXT_STEREO_ANGLES "
719 "AL_LOKI_quadriphonic "
720 "AL_SOFT_block_alignment "
721 "AL_SOFT_deferred_updates "
722 "AL_SOFT_direct_channels "
724 "AL_SOFT_gain_clamp_ex "
725 "AL_SOFT_loop_points "
726 "AL_SOFTX_map_buffer "
728 "AL_SOFT_source_latency "
729 "AL_SOFT_source_length "
730 "AL_SOFT_source_resampler "
731 "AL_SOFT_source_spatialize";
733 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
735 /* Thread-local current context */
736 static altss_t LocalContext
;
737 /* Process-wide current context */
738 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
740 /* Mixing thread piority level */
745 enum LogLevel LogLevel
= LogWarning
;
747 enum LogLevel LogLevel
= LogError
;
750 /* Flag to trap ALC device errors */
751 static ALCboolean TrapALCError
= ALC_FALSE
;
753 /* One-time configuration init control */
754 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
756 /* Default effect that applies to sources that don't have an effect on send 0 */
757 static ALeffect DefaultEffect
;
759 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
762 static ALCboolean SuspendDefers
= ALC_TRUE
;
765 /************************************************
767 ************************************************/
768 static const ALCchar alcNoDeviceExtList
[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
771 static const ALCchar alcExtensionList
[] =
772 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
773 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
774 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
775 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
776 static const ALCint alcMajorVersion
= 1;
777 static const ALCint alcMinorVersion
= 1;
779 static const ALCint alcEFXMajorVersion
= 1;
780 static const ALCint alcEFXMinorVersion
= 0;
783 /************************************************
785 ************************************************/
786 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
788 static almtx_t ListLock
;
789 static inline void LockLists(void)
791 int ret
= almtx_lock(&ListLock
);
792 assert(ret
== althrd_success
);
794 static inline void UnlockLists(void)
796 int ret
= almtx_unlock(&ListLock
);
797 assert(ret
== althrd_success
);
800 /************************************************
801 * Library initialization
802 ************************************************/
804 static void alc_init(void);
805 static void alc_deinit(void);
806 static void alc_deinit_safe(void);
808 #ifndef AL_LIBTYPE_STATIC
809 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
813 case DLL_PROCESS_ATTACH
:
814 /* Pin the DLL so we won't get unloaded until the process terminates */
815 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
816 (WCHAR
*)hModule
, &hModule
);
820 case DLL_THREAD_DETACH
:
821 althrd_thread_detach();
824 case DLL_PROCESS_DETACH
:
833 #elif defined(_MSC_VER)
834 #pragma section(".CRT$XCU",read)
835 static void alc_constructor(void);
836 static void alc_destructor(void);
837 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
839 static void alc_constructor(void)
841 atexit(alc_destructor
);
845 static void alc_destructor(void)
849 #elif defined(HAVE_GCC_DESTRUCTOR)
850 static void alc_init(void) __attribute__((constructor
));
851 static void alc_deinit(void) __attribute__((destructor
));
853 #error "No static initialization available on this platform!"
856 #elif defined(HAVE_GCC_DESTRUCTOR)
858 static void alc_init(void) __attribute__((constructor
));
859 static void alc_deinit(void) __attribute__((destructor
));
862 #error "No global initialization available on this platform!"
865 static void ReleaseThreadCtx(void *ptr
);
866 static void alc_init(void)
873 AL_STRING_INIT(alcAllDevicesList
);
874 AL_STRING_INIT(alcCaptureDeviceList
);
876 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
877 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
880 str
= getenv("__ALSOFT_REVERSE_Z");
881 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
884 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
885 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
886 OverrideReverbSpeedOfSound
= AL_TRUE
;
888 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
889 assert(ret
== althrd_success
);
891 ret
= almtx_init(&ListLock
, almtx_recursive
);
892 assert(ret
== althrd_success
);
895 static void alc_initconfig(void)
897 const char *devs
, *str
;
902 str
= getenv("ALSOFT_LOGLEVEL");
905 long lvl
= strtol(str
, NULL
, 0);
906 if(lvl
>= NoLog
&& lvl
<= LogRef
)
910 str
= getenv("ALSOFT_LOGFILE");
913 FILE *logfile
= al_fopen(str
, "wt");
914 if(logfile
) LogFile
= logfile
;
915 else ERR("Failed to open log file '%s'\n", str
);
918 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
919 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
924 if(BackendListSize
> 0)
925 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
926 for(i
= 1;i
< BackendListSize
;i
++)
927 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
928 TRACE("Supported backends: %s\n", buf
);
932 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
935 if(strcasecmp(str
, "ignore") == 0)
937 SuspendDefers
= ALC_FALSE
;
938 TRACE("Selected context suspend behavior, \"ignore\"\n");
941 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
945 #if defined(HAVE_SSE4_1)
946 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
947 #elif defined(HAVE_SSE3)
948 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
949 #elif defined(HAVE_SSE2)
950 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
951 #elif defined(HAVE_SSE)
952 capfilter
|= CPU_CAP_SSE
;
955 capfilter
|= CPU_CAP_NEON
;
957 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
959 if(strcasecmp(str
, "all") == 0)
964 const char *next
= str
;
968 while(isspace(str
[0]))
970 next
= strchr(str
, ',');
972 if(!str
[0] || str
[0] == ',')
975 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
976 while(len
> 0 && isspace(str
[len
-1]))
978 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
979 capfilter
&= ~CPU_CAP_SSE
;
980 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
981 capfilter
&= ~CPU_CAP_SSE2
;
982 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
983 capfilter
&= ~CPU_CAP_SSE3
;
984 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
985 capfilter
&= ~CPU_CAP_SSE4_1
;
986 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
987 capfilter
&= ~CPU_CAP_NEON
;
989 WARN("Invalid CPU extension \"%s\"\n", str
);
993 FillCPUCaps(capfilter
);
1000 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1005 str
= getenv("ALSOFT_TRAP_ERROR");
1006 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1008 TrapALError
= AL_TRUE
;
1009 TrapALCError
= AL_TRUE
;
1013 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1014 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1015 TrapALError
= AL_TRUE
;
1016 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1018 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1019 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1020 TrapALCError
= ALC_TRUE
;
1021 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1024 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1025 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1027 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1028 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1032 const char *next
= devs
;
1033 int endlist
, delitem
;
1038 while(isspace(devs
[0]))
1040 next
= strchr(devs
, ',');
1042 delitem
= (devs
[0] == '-');
1043 if(devs
[0] == '-') devs
++;
1045 if(!devs
[0] || devs
[0] == ',')
1052 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1053 while(len
> 0 && isspace(devs
[len
-1]))
1056 /* HACK: For backwards compatibility, convert backend references of
1057 * mmdevapi to wasapi. This should eventually be removed.
1059 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1065 for(n
= i
;n
< BackendListSize
;n
++)
1067 if(len
== strlen(BackendList
[n
].name
) &&
1068 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1072 for(;n
+1 < BackendListSize
;n
++)
1073 BackendList
[n
] = BackendList
[n
+1];
1078 struct BackendInfo Bkp
= BackendList
[n
];
1080 BackendList
[n
] = BackendList
[n
-1];
1081 BackendList
[n
] = Bkp
;
1091 BackendListSize
= i
;
1094 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1096 ALCbackendFactory
*factory
;
1097 BackendList
[n
] = BackendList
[i
];
1099 factory
= BackendList
[n
].getFactory();
1100 if(!V0(factory
,init
)())
1102 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1106 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1107 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1109 PlaybackBackend
= BackendList
[n
];
1110 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1112 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1114 CaptureBackend
= BackendList
[n
];
1115 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1119 BackendListSize
= n
;
1122 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1126 if(!PlaybackBackend
.name
)
1127 WARN("No playback backend available!\n");
1128 if(!CaptureBackend
.name
)
1129 WARN("No capture backend available!\n");
1131 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1134 const char *next
= str
;
1138 next
= strchr(str
, ',');
1140 if(!str
[0] || next
== str
)
1143 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1144 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1146 if(len
== strlen(EffectList
[n
].name
) &&
1147 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1148 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1153 InitEffect(&DefaultEffect
);
1154 str
= getenv("ALSOFT_DEFAULT_REVERB");
1155 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1156 LoadReverbPreset(str
, &DefaultEffect
);
1158 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1163 static JavaVM
*gJavaVM
;
1164 static pthread_key_t gJVMThreadKey
;
1166 static void CleanupJNIEnv(void* UNUSED(ptr
))
1168 JCALL0(gJavaVM
,DetachCurrentThread
)();
1171 void *Android_GetJNIEnv(void)
1175 WARN("gJavaVM is NULL!\n");
1179 /* http://developer.android.com/guide/practices/jni.html
1181 * All threads are Linux threads, scheduled by the kernel. They're usually
1182 * started from managed code (using Thread.start), but they can also be
1183 * created elsewhere and then attached to the JavaVM. For example, a thread
1184 * started with pthread_create can be attached with the JNI
1185 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1186 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1187 * Attaching a natively-created thread causes a java.lang.Thread object to
1188 * be constructed and added to the "main" ThreadGroup, making it visible to
1189 * the debugger. Calling AttachCurrentThread on an already-attached thread
1192 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1195 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1198 ERR("Failed to attach current thread\n");
1201 pthread_setspecific(gJVMThreadKey
, env
);
1206 /* Automatically called by JNI. */
1207 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1213 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1215 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1219 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1220 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1222 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1223 ERR("pthread_key_create failed: %d\n", err
);
1224 pthread_setspecific(gJVMThreadKey
, env
);
1225 return JNI_VERSION_1_4
;
1230 /************************************************
1231 * Library deinitialization
1232 ************************************************/
1233 static void alc_cleanup(void)
1237 AL_STRING_DEINIT(alcAllDevicesList
);
1238 AL_STRING_DEINIT(alcCaptureDeviceList
);
1240 free(alcDefaultAllDevicesSpecifier
);
1241 alcDefaultAllDevicesSpecifier
= NULL
;
1242 free(alcCaptureDefaultDeviceSpecifier
);
1243 alcCaptureDefaultDeviceSpecifier
= NULL
;
1245 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1250 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
1251 } while(dev
!= NULL
);
1252 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1256 static void alc_deinit_safe(void)
1263 almtx_destroy(&ListLock
);
1264 altss_delete(LocalContext
);
1266 if(LogFile
!= stderr
)
1273 static void alc_deinit(void)
1279 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1280 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1282 for(i
= 0;i
< BackendListSize
;i
++)
1284 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1285 V0(factory
,deinit
)();
1288 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1289 V0(factory
,deinit
)();
1296 /************************************************
1297 * Device enumeration
1298 ************************************************/
1299 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1306 if(backendinfo
->getFactory
)
1308 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1309 V(factory
,probe
)(type
);
1314 static void ProbeAllDevicesList(void)
1315 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1316 static void ProbeCaptureDeviceList(void)
1317 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1319 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1321 size_t len
= strlen(name
);
1323 alstr_append_range(devnames
, name
, name
+len
+1);
1325 void AppendAllDevicesList(const ALCchar
*name
)
1326 { AppendDevice(name
, &alcAllDevicesList
); }
1327 void AppendCaptureDeviceList(const ALCchar
*name
)
1328 { AppendDevice(name
, &alcCaptureDeviceList
); }
1331 /************************************************
1332 * Device format information
1333 ************************************************/
1334 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1338 case DevFmtByte
: return "Signed Byte";
1339 case DevFmtUByte
: return "Unsigned Byte";
1340 case DevFmtShort
: return "Signed Short";
1341 case DevFmtUShort
: return "Unsigned Short";
1342 case DevFmtInt
: return "Signed Int";
1343 case DevFmtUInt
: return "Unsigned Int";
1344 case DevFmtFloat
: return "Float";
1346 return "(unknown type)";
1348 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1352 case DevFmtMono
: return "Mono";
1353 case DevFmtStereo
: return "Stereo";
1354 case DevFmtQuad
: return "Quadraphonic";
1355 case DevFmtX51
: return "5.1 Surround";
1356 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1357 case DevFmtX61
: return "6.1 Surround";
1358 case DevFmtX71
: return "7.1 Surround";
1359 case DevFmtAmbi3D
: return "Ambisonic 3D";
1361 return "(unknown channels)";
1364 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1365 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1369 case DevFmtByte
: return sizeof(ALbyte
);
1370 case DevFmtUByte
: return sizeof(ALubyte
);
1371 case DevFmtShort
: return sizeof(ALshort
);
1372 case DevFmtUShort
: return sizeof(ALushort
);
1373 case DevFmtInt
: return sizeof(ALint
);
1374 case DevFmtUInt
: return sizeof(ALuint
);
1375 case DevFmtFloat
: return sizeof(ALfloat
);
1379 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1383 case DevFmtMono
: return 1;
1384 case DevFmtStereo
: return 2;
1385 case DevFmtQuad
: return 4;
1386 case DevFmtX51
: return 6;
1387 case DevFmtX51Rear
: return 6;
1388 case DevFmtX61
: return 7;
1389 case DevFmtX71
: return 8;
1390 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1391 (ambiorder
== 2) ? 9 :
1392 (ambiorder
== 1) ? 4 : 1;
1397 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1398 enum DevFmtType
*type
)
1400 static const struct {
1402 enum DevFmtChannels channels
;
1403 enum DevFmtType type
;
1405 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1406 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1407 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1409 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1410 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1411 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1413 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1414 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1415 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1417 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1418 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1419 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1421 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1422 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1423 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1425 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1426 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1427 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1431 for(i
= 0;i
< COUNTOF(list
);i
++)
1433 if(list
[i
].format
== format
)
1435 *chans
= list
[i
].channels
;
1436 *type
= list
[i
].type
;
1444 static ALCboolean
IsValidALCType(ALCenum type
)
1449 case ALC_UNSIGNED_BYTE_SOFT
:
1450 case ALC_SHORT_SOFT
:
1451 case ALC_UNSIGNED_SHORT_SOFT
:
1453 case ALC_UNSIGNED_INT_SOFT
:
1454 case ALC_FLOAT_SOFT
:
1460 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1465 case ALC_STEREO_SOFT
:
1467 case ALC_5POINT1_SOFT
:
1468 case ALC_6POINT1_SOFT
:
1469 case ALC_7POINT1_SOFT
:
1470 case ALC_BFORMAT3D_SOFT
:
1476 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1487 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1499 /************************************************
1500 * Miscellaneous ALC helpers
1501 ************************************************/
1503 /* SetDefaultWFXChannelOrder
1505 * Sets the default channel order used by WaveFormatEx.
1507 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1511 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1512 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1514 switch(device
->FmtChans
)
1517 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1520 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1521 device
->RealOut
.ChannelName
[1] = FrontRight
;
1524 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1525 device
->RealOut
.ChannelName
[1] = FrontRight
;
1526 device
->RealOut
.ChannelName
[2] = BackLeft
;
1527 device
->RealOut
.ChannelName
[3] = BackRight
;
1530 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1531 device
->RealOut
.ChannelName
[1] = FrontRight
;
1532 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1533 device
->RealOut
.ChannelName
[3] = LFE
;
1534 device
->RealOut
.ChannelName
[4] = SideLeft
;
1535 device
->RealOut
.ChannelName
[5] = SideRight
;
1538 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1539 device
->RealOut
.ChannelName
[1] = FrontRight
;
1540 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1541 device
->RealOut
.ChannelName
[3] = LFE
;
1542 device
->RealOut
.ChannelName
[4] = BackLeft
;
1543 device
->RealOut
.ChannelName
[5] = BackRight
;
1546 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1547 device
->RealOut
.ChannelName
[1] = FrontRight
;
1548 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1549 device
->RealOut
.ChannelName
[3] = LFE
;
1550 device
->RealOut
.ChannelName
[4] = BackCenter
;
1551 device
->RealOut
.ChannelName
[5] = SideLeft
;
1552 device
->RealOut
.ChannelName
[6] = SideRight
;
1555 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1556 device
->RealOut
.ChannelName
[1] = FrontRight
;
1557 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1558 device
->RealOut
.ChannelName
[3] = LFE
;
1559 device
->RealOut
.ChannelName
[4] = BackLeft
;
1560 device
->RealOut
.ChannelName
[5] = BackRight
;
1561 device
->RealOut
.ChannelName
[6] = SideLeft
;
1562 device
->RealOut
.ChannelName
[7] = SideRight
;
1565 device
->RealOut
.ChannelName
[0] = Aux0
;
1566 if(device
->AmbiOrder
> 0)
1568 device
->RealOut
.ChannelName
[1] = Aux1
;
1569 device
->RealOut
.ChannelName
[2] = Aux2
;
1570 device
->RealOut
.ChannelName
[3] = Aux3
;
1572 if(device
->AmbiOrder
> 1)
1574 device
->RealOut
.ChannelName
[4] = Aux4
;
1575 device
->RealOut
.ChannelName
[5] = Aux5
;
1576 device
->RealOut
.ChannelName
[6] = Aux6
;
1577 device
->RealOut
.ChannelName
[7] = Aux7
;
1578 device
->RealOut
.ChannelName
[8] = Aux8
;
1580 if(device
->AmbiOrder
> 2)
1582 device
->RealOut
.ChannelName
[9] = Aux9
;
1583 device
->RealOut
.ChannelName
[10] = Aux10
;
1584 device
->RealOut
.ChannelName
[11] = Aux11
;
1585 device
->RealOut
.ChannelName
[12] = Aux12
;
1586 device
->RealOut
.ChannelName
[13] = Aux13
;
1587 device
->RealOut
.ChannelName
[14] = Aux14
;
1588 device
->RealOut
.ChannelName
[15] = Aux15
;
1594 /* SetDefaultChannelOrder
1596 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1598 void SetDefaultChannelOrder(ALCdevice
*device
)
1602 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1603 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1605 switch(device
->FmtChans
)
1608 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1609 device
->RealOut
.ChannelName
[1] = FrontRight
;
1610 device
->RealOut
.ChannelName
[2] = BackLeft
;
1611 device
->RealOut
.ChannelName
[3] = BackRight
;
1612 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1613 device
->RealOut
.ChannelName
[5] = LFE
;
1616 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1617 device
->RealOut
.ChannelName
[1] = FrontRight
;
1618 device
->RealOut
.ChannelName
[2] = BackLeft
;
1619 device
->RealOut
.ChannelName
[3] = BackRight
;
1620 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1621 device
->RealOut
.ChannelName
[5] = LFE
;
1622 device
->RealOut
.ChannelName
[6] = SideLeft
;
1623 device
->RealOut
.ChannelName
[7] = SideRight
;
1626 /* Same as WFX order */
1633 SetDefaultWFXChannelOrder(device
);
1638 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1639 extern inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
);
1642 /* ALCcontext_DeferUpdates
1644 * Defers/suspends updates for the given context's listener and sources. This
1645 * does *NOT* stop mixing, but rather prevents certain property changes from
1648 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1650 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1653 /* ALCcontext_ProcessUpdates
1655 * Resumes update processing after being deferred.
1657 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1659 almtx_lock(&context
->PropLock
);
1660 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1662 /* Tell the mixer to stop applying updates, then wait for any active
1663 * updating to finish, before providing updates.
1665 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1666 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1669 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1670 UpdateContextProps(context
);
1671 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1672 UpdateListenerProps(context
);
1673 UpdateAllEffectSlotProps(context
);
1674 UpdateAllSourceProps(context
);
1676 /* Now with all updates declared, let the mixer continue applying them
1677 * so they all happen at once.
1679 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1681 almtx_unlock(&context
->PropLock
);
1687 * Stores the latest ALC device error
1689 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1691 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1695 /* DebugBreak() will cause an exception if there is no debugger */
1696 if(IsDebuggerPresent())
1698 #elif defined(SIGTRAP)
1704 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1706 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1710 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1712 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1713 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1718 * Updates the device's base clock time with however many samples have been
1719 * done. This is used so frequency changes on the device don't cause the time
1720 * to jump forward or back. Must not be called while the device is running/
1723 static inline void UpdateClockBase(ALCdevice
*device
)
1725 IncrementRef(&device
->MixCount
);
1726 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1727 device
->SamplesDone
= 0;
1728 IncrementRef(&device
->MixCount
);
1731 /* UpdateDeviceParams
1733 * Updates device parameters according to the attribute list (caller is
1734 * responsible for holding the list lock).
1736 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1738 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1739 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1740 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1741 const ALsizei old_sends
= device
->NumAuxSends
;
1742 ALsizei new_sends
= device
->NumAuxSends
;
1743 enum DevFmtChannels oldChans
;
1744 enum DevFmtType oldType
;
1745 ALboolean update_failed
;
1746 ALCsizei hrtf_id
= -1;
1747 ALCcontext
*context
;
1753 // Check for attributes
1754 if(device
->Type
== Loopback
)
1756 ALCsizei numMono
, numStereo
, numSends
;
1757 ALCenum alayout
= AL_NONE
;
1758 ALCenum ascale
= AL_NONE
;
1759 ALCenum schans
= AL_NONE
;
1760 ALCenum stype
= AL_NONE
;
1761 ALCsizei attrIdx
= 0;
1762 ALCsizei aorder
= 0;
1767 WARN("Missing attributes for loopback device\n");
1768 return ALC_INVALID_VALUE
;
1771 numMono
= device
->NumMonoSources
;
1772 numStereo
= device
->NumStereoSources
;
1773 numSends
= old_sends
;
1775 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1776 while(attrList
[attrIdx
])
1778 switch(attrList
[attrIdx
])
1780 case ALC_FORMAT_CHANNELS_SOFT
:
1781 schans
= attrList
[attrIdx
+ 1];
1782 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1783 if(!IsValidALCChannels(schans
))
1784 return ALC_INVALID_VALUE
;
1787 case ALC_FORMAT_TYPE_SOFT
:
1788 stype
= attrList
[attrIdx
+ 1];
1789 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1790 if(!IsValidALCType(stype
))
1791 return ALC_INVALID_VALUE
;
1795 freq
= attrList
[attrIdx
+ 1];
1796 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1797 if(freq
< MIN_OUTPUT_RATE
)
1798 return ALC_INVALID_VALUE
;
1801 case ALC_AMBISONIC_LAYOUT_SOFT
:
1802 alayout
= attrList
[attrIdx
+ 1];
1803 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1804 if(!IsValidAmbiLayout(alayout
))
1805 return ALC_INVALID_VALUE
;
1808 case ALC_AMBISONIC_SCALING_SOFT
:
1809 ascale
= attrList
[attrIdx
+ 1];
1810 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1811 if(!IsValidAmbiScaling(ascale
))
1812 return ALC_INVALID_VALUE
;
1815 case ALC_AMBISONIC_ORDER_SOFT
:
1816 aorder
= attrList
[attrIdx
+ 1];
1817 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1818 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1819 return ALC_INVALID_VALUE
;
1822 case ALC_MONO_SOURCES
:
1823 numMono
= attrList
[attrIdx
+ 1];
1824 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1825 numMono
= maxi(numMono
, 0);
1828 case ALC_STEREO_SOURCES
:
1829 numStereo
= attrList
[attrIdx
+ 1];
1830 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1831 numStereo
= maxi(numStereo
, 0);
1834 case ALC_MAX_AUXILIARY_SENDS
:
1835 numSends
= attrList
[attrIdx
+ 1];
1836 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1837 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1841 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1842 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1843 hrtf_appreq
= Hrtf_Disable
;
1844 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1845 hrtf_appreq
= Hrtf_Enable
;
1847 hrtf_appreq
= Hrtf_Default
;
1850 case ALC_HRTF_ID_SOFT
:
1851 hrtf_id
= attrList
[attrIdx
+ 1];
1852 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1855 case ALC_OUTPUT_LIMITER_SOFT
:
1856 gainLimiter
= attrList
[attrIdx
+ 1];
1857 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1861 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1862 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1870 if(!schans
|| !stype
|| !freq
)
1872 WARN("Missing format for loopback device\n");
1873 return ALC_INVALID_VALUE
;
1875 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1877 WARN("Missing ambisonic info for loopback device\n");
1878 return ALC_INVALID_VALUE
;
1881 if((device
->Flags
&DEVICE_RUNNING
))
1882 V0(device
->Backend
,stop
)();
1883 device
->Flags
&= ~DEVICE_RUNNING
;
1885 UpdateClockBase(device
);
1887 device
->Frequency
= freq
;
1888 device
->FmtChans
= schans
;
1889 device
->FmtType
= stype
;
1890 if(schans
== ALC_BFORMAT3D_SOFT
)
1892 device
->AmbiOrder
= aorder
;
1893 device
->AmbiLayout
= alayout
;
1894 device
->AmbiScale
= ascale
;
1897 if(numMono
> INT_MAX
-numStereo
)
1898 numMono
= INT_MAX
-numStereo
;
1899 numMono
+= numStereo
;
1900 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1906 numMono
= maxi(numMono
, 256);
1907 numStereo
= mini(numStereo
, numMono
);
1908 numMono
-= numStereo
;
1909 device
->SourcesMax
= numMono
+ numStereo
;
1911 device
->NumMonoSources
= numMono
;
1912 device
->NumStereoSources
= numStereo
;
1914 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1915 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1917 new_sends
= numSends
;
1919 else if(attrList
&& attrList
[0])
1921 ALCsizei numMono
, numStereo
, numSends
;
1922 ALCsizei attrIdx
= 0;
1925 /* If a context is already running on the device, stop playback so the
1926 * device attributes can be updated. */
1927 if((device
->Flags
&DEVICE_RUNNING
))
1928 V0(device
->Backend
,stop
)();
1929 device
->Flags
&= ~DEVICE_RUNNING
;
1931 UpdateClockBase(device
);
1933 freq
= device
->Frequency
;
1934 numMono
= device
->NumMonoSources
;
1935 numStereo
= device
->NumStereoSources
;
1936 numSends
= old_sends
;
1938 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1939 while(attrList
[attrIdx
])
1941 switch(attrList
[attrIdx
])
1944 freq
= attrList
[attrIdx
+ 1];
1945 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1946 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1949 case ALC_MONO_SOURCES
:
1950 numMono
= attrList
[attrIdx
+ 1];
1951 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1952 numMono
= maxi(numMono
, 0);
1955 case ALC_STEREO_SOURCES
:
1956 numStereo
= attrList
[attrIdx
+ 1];
1957 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1958 numStereo
= maxi(numStereo
, 0);
1961 case ALC_MAX_AUXILIARY_SENDS
:
1962 numSends
= attrList
[attrIdx
+ 1];
1963 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1964 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1968 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1969 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1970 hrtf_appreq
= Hrtf_Disable
;
1971 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1972 hrtf_appreq
= Hrtf_Enable
;
1974 hrtf_appreq
= Hrtf_Default
;
1977 case ALC_HRTF_ID_SOFT
:
1978 hrtf_id
= attrList
[attrIdx
+ 1];
1979 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1982 case ALC_OUTPUT_LIMITER_SOFT
:
1983 gainLimiter
= attrList
[attrIdx
+ 1];
1984 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1988 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1989 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1997 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
1998 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2000 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2002 /* SSE and Neon do best with the update size being a multiple of 4 */
2003 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2004 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2006 device
->Frequency
= freq
;
2008 if(numMono
> INT_MAX
-numStereo
)
2009 numMono
= INT_MAX
-numStereo
;
2010 numMono
+= numStereo
;
2011 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2017 numMono
= maxi(numMono
, 256);
2018 numStereo
= mini(numStereo
, numMono
);
2019 numMono
-= numStereo
;
2020 device
->SourcesMax
= numMono
+ numStereo
;
2022 device
->NumMonoSources
= numMono
;
2023 device
->NumStereoSources
= numStereo
;
2025 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2026 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2028 new_sends
= numSends
;
2031 if((device
->Flags
&DEVICE_RUNNING
))
2032 return ALC_NO_ERROR
;
2034 al_free(device
->Uhj_Encoder
);
2035 device
->Uhj_Encoder
= NULL
;
2037 al_free(device
->Bs2b
);
2038 device
->Bs2b
= NULL
;
2040 al_free(device
->ChannelDelay
[0].Buffer
);
2041 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2043 device
->ChannelDelay
[i
].Length
= 0;
2044 device
->ChannelDelay
[i
].Buffer
= NULL
;
2047 al_free(device
->Dry
.Buffer
);
2048 device
->Dry
.Buffer
= NULL
;
2049 device
->Dry
.NumChannels
= 0;
2050 device
->FOAOut
.Buffer
= NULL
;
2051 device
->FOAOut
.NumChannels
= 0;
2052 device
->RealOut
.Buffer
= NULL
;
2053 device
->RealOut
.NumChannels
= 0;
2055 UpdateClockBase(device
);
2057 device
->DitherSeed
= DITHER_RNG_SEED
;
2059 /*************************************************************************
2060 * Update device format request if HRTF is requested
2062 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2063 if(device
->Type
!= Loopback
)
2066 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2068 if(strcasecmp(hrtf
, "true") == 0)
2069 hrtf_userreq
= Hrtf_Enable
;
2070 else if(strcasecmp(hrtf
, "false") == 0)
2071 hrtf_userreq
= Hrtf_Disable
;
2072 else if(strcasecmp(hrtf
, "auto") != 0)
2073 ERR("Unexpected hrtf value: %s\n", hrtf
);
2076 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2078 struct Hrtf
*hrtf
= NULL
;
2079 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2081 VECTOR_DEINIT(device
->HrtfList
);
2082 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2084 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2086 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2087 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2089 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2094 device
->FmtChans
= DevFmtStereo
;
2095 device
->Frequency
= hrtf
->sampleRate
;
2096 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2097 if(device
->HrtfHandle
)
2098 Hrtf_DecRef(device
->HrtfHandle
);
2099 device
->HrtfHandle
= hrtf
;
2103 hrtf_userreq
= Hrtf_Default
;
2104 hrtf_appreq
= Hrtf_Disable
;
2105 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2110 oldFreq
= device
->Frequency
;
2111 oldChans
= device
->FmtChans
;
2112 oldType
= device
->FmtType
;
2114 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2115 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2116 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2117 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2118 device
->UpdateSize
, device
->NumUpdates
2121 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2122 return ALC_INVALID_DEVICE
;
2124 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2126 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2127 DevFmtChannelsString(device
->FmtChans
));
2128 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2130 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2132 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2133 DevFmtTypeString(device
->FmtType
));
2134 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2136 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2138 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2139 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2142 if((device
->UpdateSize
&3) != 0)
2144 if((CPUCapFlags
&CPU_CAP_SSE
))
2145 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2146 if((CPUCapFlags
&CPU_CAP_NEON
))
2147 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2150 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2151 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2152 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2155 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2156 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2157 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2159 /* Allocate extra channels for any post-filter output. */
2160 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2161 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2163 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2164 device
->Dry
.Buffer
= al_calloc(16, size
);
2165 if(!device
->Dry
.Buffer
)
2167 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2168 return ALC_INVALID_DEVICE
;
2171 if(device
->RealOut
.NumChannels
!= 0)
2172 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2173 device
->FOAOut
.NumChannels
;
2176 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2177 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2180 if(device
->FOAOut
.NumChannels
!= 0)
2181 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2184 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2185 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2188 device
->NumAuxSends
= new_sends
;
2189 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2190 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2191 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2193 device
->DitherDepth
= 0.0f
;
2194 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2197 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2200 switch(device
->FmtType
)
2218 device
->DitherDepth
= (depth
> 0) ? powf(2.0f
, (ALfloat
)(depth
-1)) : 0.0f
;
2220 if(!(device
->DitherDepth
> 0.0f
))
2221 TRACE("Dithering disabled\n");
2223 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2224 device
->DitherDepth
);
2226 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2227 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2228 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2229 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2232 if(gainLimiter
!= ALC_FALSE
)
2234 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2236 al_free(device
->Limiter
);
2237 device
->Limiter
= CreateDeviceLimiter(device
);
2242 al_free(device
->Limiter
);
2243 device
->Limiter
= NULL
;
2245 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2247 aluSelectPostProcess(device
);
2249 /* Need to delay returning failure until replacement Send arrays have been
2250 * allocated with the appropriate size.
2252 update_failed
= AL_FALSE
;
2254 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2257 SourceSubList
*sublist
, *subend
;
2258 struct ALvoiceProps
*vprops
;
2261 if(context
->DefaultSlot
)
2263 ALeffectslot
*slot
= context
->DefaultSlot
;
2264 ALeffectState
*state
= slot
->Effect
.State
;
2266 state
->OutBuffer
= device
->Dry
.Buffer
;
2267 state
->OutChannels
= device
->Dry
.NumChannels
;
2268 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2269 update_failed
= AL_TRUE
;
2271 UpdateEffectSlotProps(slot
, context
);
2274 almtx_lock(&context
->PropLock
);
2275 almtx_lock(&context
->EffectSlotLock
);
2276 for(pos
= 0;pos
< (ALsizei
)VECTOR_SIZE(context
->EffectSlotList
);pos
++)
2278 ALeffectslot
*slot
= VECTOR_ELEM(context
->EffectSlotList
, pos
);
2279 ALeffectState
*state
= slot
->Effect
.State
;
2281 state
->OutBuffer
= device
->Dry
.Buffer
;
2282 state
->OutChannels
= device
->Dry
.NumChannels
;
2283 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2284 update_failed
= AL_TRUE
;
2286 UpdateEffectSlotProps(slot
, context
);
2288 almtx_unlock(&context
->EffectSlotLock
);
2290 almtx_lock(&context
->SourceLock
);
2291 sublist
= VECTOR_BEGIN(context
->SourceList
);
2292 subend
= VECTOR_END(context
->SourceList
);
2293 for(;sublist
!= subend
;++sublist
)
2295 ALuint64 usemask
= ~sublist
->FreeMask
;
2298 ALsizei idx
= CTZ64(usemask
);
2299 ALsource
*source
= sublist
->Sources
+ idx
;
2301 usemask
&= ~(U64(1) << idx
);
2303 if(old_sends
!= device
->NumAuxSends
)
2305 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2308 memcpy(sends
, source
->Send
,
2309 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2311 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2313 if(source
->Send
[s
].Slot
)
2314 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2315 source
->Send
[s
].Slot
= NULL
;
2317 al_free(source
->Send
);
2318 source
->Send
= sends
;
2319 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2321 source
->Send
[s
].Slot
= NULL
;
2322 source
->Send
[s
].Gain
= 1.0f
;
2323 source
->Send
[s
].GainHF
= 1.0f
;
2324 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2325 source
->Send
[s
].GainLF
= 1.0f
;
2326 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2330 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2334 /* Clear any pre-existing voice property structs, in case the number of
2335 * auxiliary sends is changing. Active sources will have updates
2336 * respecified in UpdateAllSourceProps.
2338 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2341 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2346 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2347 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2349 ALvoice
*voice
= context
->Voices
[pos
];
2351 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2353 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2356 if(device
->AvgSpeakerDist
> 0.0f
)
2358 /* Reinitialize the NFC filters for new parameters. */
2359 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2360 (device
->AvgSpeakerDist
* device
->Frequency
);
2361 for(i
= 0;i
< voice
->NumChannels
;i
++)
2362 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2365 almtx_unlock(&context
->SourceLock
);
2367 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2368 UpdateContextProps(context
);
2369 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2370 UpdateListenerProps(context
);
2371 UpdateAllSourceProps(context
);
2372 almtx_unlock(&context
->PropLock
);
2374 context
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2378 return ALC_INVALID_DEVICE
;
2380 if(!(device
->Flags
&DEVICE_PAUSED
))
2382 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2383 return ALC_INVALID_DEVICE
;
2384 device
->Flags
|= DEVICE_RUNNING
;
2387 return ALC_NO_ERROR
;
2391 static void InitDevice(ALCdevice
*device
, enum DeviceType type
)
2395 InitRef(&device
->ref
, 1);
2396 ATOMIC_INIT(&device
->Connected
, ALC_TRUE
);
2397 device
->Type
= type
;
2398 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
2401 device
->Render_Mode
= NormalRender
;
2402 device
->AvgSpeakerDist
= 0.0f
;
2404 ATOMIC_INIT(&device
->ContextList
, NULL
);
2406 device
->ClockBase
= 0;
2407 device
->SamplesDone
= 0;
2409 device
->SourcesMax
= 0;
2410 device
->AuxiliaryEffectSlotMax
= 0;
2411 device
->NumAuxSends
= 0;
2413 device
->Dry
.Buffer
= NULL
;
2414 device
->Dry
.NumChannels
= 0;
2415 device
->FOAOut
.Buffer
= NULL
;
2416 device
->FOAOut
.NumChannels
= 0;
2417 device
->RealOut
.Buffer
= NULL
;
2418 device
->RealOut
.NumChannels
= 0;
2420 AL_STRING_INIT(device
->DeviceName
);
2422 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2424 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2425 device
->ChannelDelay
[i
].Length
= 0;
2426 device
->ChannelDelay
[i
].Buffer
= NULL
;
2429 AL_STRING_INIT(device
->HrtfName
);
2430 VECTOR_INIT(device
->HrtfList
);
2431 device
->HrtfHandle
= NULL
;
2432 device
->Hrtf
= NULL
;
2433 device
->Bs2b
= NULL
;
2434 device
->Uhj_Encoder
= NULL
;
2435 device
->AmbiDecoder
= NULL
;
2436 device
->AmbiUp
= NULL
;
2437 device
->Stablizer
= NULL
;
2438 device
->Limiter
= NULL
;
2440 VECTOR_INIT(device
->BufferList
);
2441 almtx_init(&device
->BufferLock
, almtx_plain
);
2443 VECTOR_INIT(device
->EffectList
);
2444 almtx_init(&device
->EffectLock
, almtx_plain
);
2446 VECTOR_INIT(device
->FilterList
);
2447 almtx_init(&device
->FilterLock
, almtx_plain
);
2449 almtx_init(&device
->BackendLock
, almtx_plain
);
2450 device
->Backend
= NULL
;
2452 ATOMIC_INIT(&device
->next
, NULL
);
2457 * Frees the device structure, and destroys any objects the app failed to
2458 * delete. Called once there's no more references on the device.
2460 static ALCvoid
FreeDevice(ALCdevice
*device
)
2464 TRACE("%p\n", device
);
2467 DELETE_OBJ(device
->Backend
);
2468 device
->Backend
= NULL
;
2470 almtx_destroy(&device
->BackendLock
);
2472 ReleaseALBuffers(device
);
2473 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2474 VECTOR_FOR_EACH(BufferSubList
, device
->BufferList
, FREE_BUFFERSUBLIST
);
2475 #undef FREE_BUFFERSUBLIST
2476 VECTOR_DEINIT(device
->BufferList
);
2477 almtx_destroy(&device
->BufferLock
);
2479 ReleaseALEffects(device
);
2480 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2481 VECTOR_FOR_EACH(EffectSubList
, device
->EffectList
, FREE_EFFECTSUBLIST
);
2482 #undef FREE_EFFECTSUBLIST
2483 VECTOR_DEINIT(device
->EffectList
);
2484 almtx_destroy(&device
->EffectLock
);
2486 ReleaseALFilters(device
);
2487 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2488 VECTOR_FOR_EACH(FilterSubList
, device
->FilterList
, FREE_FILTERSUBLIST
);
2489 #undef FREE_FILTERSUBLIST
2490 VECTOR_DEINIT(device
->FilterList
);
2491 almtx_destroy(&device
->FilterLock
);
2493 AL_STRING_DEINIT(device
->HrtfName
);
2494 FreeHrtfList(&device
->HrtfList
);
2495 if(device
->HrtfHandle
)
2496 Hrtf_DecRef(device
->HrtfHandle
);
2497 device
->HrtfHandle
= NULL
;
2498 al_free(device
->Hrtf
);
2499 device
->Hrtf
= NULL
;
2501 al_free(device
->Bs2b
);
2502 device
->Bs2b
= NULL
;
2504 al_free(device
->Uhj_Encoder
);
2505 device
->Uhj_Encoder
= NULL
;
2507 bformatdec_free(&device
->AmbiDecoder
);
2508 ambiup_free(&device
->AmbiUp
);
2510 al_free(device
->Stablizer
);
2511 device
->Stablizer
= NULL
;
2513 al_free(device
->Limiter
);
2514 device
->Limiter
= NULL
;
2516 al_free(device
->ChannelDelay
[0].Buffer
);
2517 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2519 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2520 device
->ChannelDelay
[i
].Length
= 0;
2521 device
->ChannelDelay
[i
].Buffer
= NULL
;
2524 AL_STRING_DEINIT(device
->DeviceName
);
2526 al_free(device
->Dry
.Buffer
);
2527 device
->Dry
.Buffer
= NULL
;
2528 device
->Dry
.NumChannels
= 0;
2529 device
->FOAOut
.Buffer
= NULL
;
2530 device
->FOAOut
.NumChannels
= 0;
2531 device
->RealOut
.Buffer
= NULL
;
2532 device
->RealOut
.NumChannels
= 0;
2538 void ALCdevice_IncRef(ALCdevice
*device
)
2541 ref
= IncrementRef(&device
->ref
);
2542 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2545 void ALCdevice_DecRef(ALCdevice
*device
)
2548 ref
= DecrementRef(&device
->ref
);
2549 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2550 if(ref
== 0) FreeDevice(device
);
2555 * Checks if the device handle is valid, and increments its ref count if so.
2557 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2559 ALCdevice
*tmpDevice
;
2562 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2565 if(tmpDevice
== *device
)
2567 ALCdevice_IncRef(tmpDevice
);
2571 tmpDevice
= ATOMIC_LOAD(&tmpDevice
->next
, almemory_order_relaxed
);
2582 * Initializes context fields
2584 static ALvoid
InitContext(ALCcontext
*Context
)
2586 ALlistener
*listener
= Context
->Listener
;
2587 struct ALeffectslotArray
*auxslots
;
2589 //Initialise listener
2590 listener
->Gain
= 1.0f
;
2591 listener
->Position
[0] = 0.0f
;
2592 listener
->Position
[1] = 0.0f
;
2593 listener
->Position
[2] = 0.0f
;
2594 listener
->Velocity
[0] = 0.0f
;
2595 listener
->Velocity
[1] = 0.0f
;
2596 listener
->Velocity
[2] = 0.0f
;
2597 listener
->Forward
[0] = 0.0f
;
2598 listener
->Forward
[1] = 0.0f
;
2599 listener
->Forward
[2] = -1.0f
;
2600 listener
->Up
[0] = 0.0f
;
2601 listener
->Up
[1] = 1.0f
;
2602 listener
->Up
[2] = 0.0f
;
2603 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2605 ATOMIC_INIT(&listener
->Update
, NULL
);
2608 InitRef(&Context
->UpdateCount
, 0);
2609 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2610 Context
->GainBoost
= 1.0f
;
2611 almtx_init(&Context
->PropLock
, almtx_plain
);
2612 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2613 VECTOR_INIT(Context
->SourceList
);
2614 Context
->NumSources
= 0;
2615 almtx_init(&Context
->SourceLock
, almtx_plain
);
2616 VECTOR_INIT(Context
->EffectSlotList
);
2617 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2619 if(Context
->DefaultSlot
)
2621 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2622 auxslots
->count
= 1;
2623 auxslots
->slot
[0] = Context
->DefaultSlot
;
2627 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2628 auxslots
->count
= 0;
2630 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2633 Context
->DistanceModel
= DefaultDistanceModel
;
2634 Context
->SourceDistanceModel
= AL_FALSE
;
2635 Context
->DopplerFactor
= 1.0f
;
2636 Context
->DopplerVelocity
= 1.0f
;
2637 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2638 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2639 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2640 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2641 almtx_init(&Context
->EventThrdLock
, almtx_plain
);
2642 alsem_init(&Context
->EventSem
, 0);
2643 Context
->AsyncEvents
= NULL
;
2644 ATOMIC_INIT(&Context
->EnabledEvts
, 0);
2645 almtx_init(&Context
->EventCbLock
, almtx_plain
);
2646 Context
->EventCb
= NULL
;
2647 Context
->EventParam
= NULL
;
2649 ATOMIC_INIT(&Context
->Update
, NULL
);
2650 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2651 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2652 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2653 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2655 Context
->ExtensionList
= alExtList
;
2658 listener
->Params
.Matrix
= IdentityMatrixf
;
2659 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2660 listener
->Params
.Gain
= listener
->Gain
;
2661 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2662 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2663 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2664 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2665 listener
->Params
.MetersPerUnit
;
2666 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2667 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2673 * Cleans up the context, and destroys any remaining objects the app failed to
2674 * delete. Called once there's no more references on the context.
2676 static void FreeContext(ALCcontext
*context
)
2678 ALlistener
*listener
= context
->Listener
;
2679 struct ALeffectslotArray
*auxslots
;
2680 struct ALeffectslotProps
*eprops
;
2681 struct ALlistenerProps
*lprops
;
2682 struct ALcontextProps
*cprops
;
2683 struct ALvoiceProps
*vprops
;
2687 TRACE("%p\n", context
);
2689 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2691 TRACE("Freed unapplied context update %p\n", cprops
);
2696 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2699 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2704 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2706 if(context
->DefaultSlot
)
2708 DeinitEffectSlot(context
->DefaultSlot
);
2709 context
->DefaultSlot
= NULL
;
2712 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2715 ReleaseALSources(context
);
2716 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2717 VECTOR_FOR_EACH(SourceSubList
, context
->SourceList
, FREE_SOURCESUBLIST
);
2718 #undef FREE_SOURCESUBLIST
2719 VECTOR_DEINIT(context
->SourceList
);
2720 context
->NumSources
= 0;
2721 almtx_destroy(&context
->SourceLock
);
2724 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2727 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2728 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2733 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2735 ReleaseALAuxiliaryEffectSlots(context
);
2736 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2737 VECTOR_FOR_EACH(ALeffectslotPtr
, context
->EffectSlotList
, FREE_EFFECTSLOTPTR
);
2738 #undef FREE_EFFECTSLOTPTR
2739 VECTOR_DEINIT(context
->EffectSlotList
);
2740 almtx_destroy(&context
->EffectSlotLock
);
2743 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2746 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2751 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2753 for(i
= 0;i
< context
->VoiceCount
;i
++)
2754 DeinitVoice(context
->Voices
[i
]);
2755 al_free(context
->Voices
);
2756 context
->Voices
= NULL
;
2757 context
->VoiceCount
= 0;
2758 context
->MaxVoices
= 0;
2760 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2762 TRACE("Freed unapplied listener update %p\n", lprops
);
2766 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2769 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2774 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2776 if(ATOMIC_EXCHANGE(&context
->EnabledEvts
, 0, almemory_order_acq_rel
))
2778 static const AsyncEvent kill_evt
= { 0 };
2779 while(ll_ringbuffer_write(context
->AsyncEvents
, (const char*)&kill_evt
, 1) == 0)
2781 alsem_post(&context
->EventSem
);
2782 althrd_join(context
->EventThread
, NULL
);
2785 almtx_destroy(&context
->EventCbLock
);
2786 almtx_destroy(&context
->EventThrdLock
);
2787 alsem_destroy(&context
->EventSem
);
2789 ll_ringbuffer_free(context
->AsyncEvents
);
2790 context
->AsyncEvents
= NULL
;
2792 almtx_destroy(&context
->PropLock
);
2794 ALCdevice_DecRef(context
->Device
);
2795 context
->Device
= NULL
;
2797 //Invalidate context
2798 memset(context
, 0, sizeof(ALCcontext
));
2804 * Removes the context reference from the given device and removes it from
2805 * being current on the running thread or globally. Returns true if other
2806 * contexts still exist on the device.
2808 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2810 ALCcontext
*origctx
, *newhead
;
2813 if(altss_get(LocalContext
) == context
)
2815 WARN("%p released while current on thread\n", context
);
2816 altss_set(LocalContext
, NULL
);
2817 ALCcontext_DecRef(context
);
2821 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2822 ALCcontext_DecRef(context
);
2824 V0(device
->Backend
,lock
)();
2826 newhead
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2827 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2831 /* origctx is what the desired context failed to match. Try
2832 * swapping out the next one in the list.
2836 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origctx
, newhead
));
2840 V0(device
->Backend
,unlock
)();
2842 ALCcontext_DecRef(context
);
2846 static void ALCcontext_IncRef(ALCcontext
*context
)
2848 uint ref
= IncrementRef(&context
->ref
);
2849 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2852 void ALCcontext_DecRef(ALCcontext
*context
)
2854 uint ref
= DecrementRef(&context
->ref
);
2855 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2856 if(ref
== 0) FreeContext(context
);
2859 static void ReleaseThreadCtx(void *ptr
)
2861 ALCcontext
*context
= ptr
;
2862 uint ref
= DecrementRef(&context
->ref
);
2863 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2864 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2869 * Checks that the given context is valid, and increments its reference count.
2871 static ALCboolean
VerifyContext(ALCcontext
**context
)
2876 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2879 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2884 ALCcontext_IncRef(ctx
);
2888 ctx
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
2890 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
2901 * Returns the currently active context for this thread, and adds a reference
2902 * without locking it.
2904 ALCcontext
*GetContextRef(void)
2906 ALCcontext
*context
;
2908 context
= altss_get(LocalContext
);
2910 ALCcontext_IncRef(context
);
2914 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2916 ALCcontext_IncRef(context
);
2924 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2926 ALCdevice
*device
= context
->Device
;
2927 ALsizei num_sends
= device
->NumAuxSends
;
2928 struct ALvoiceProps
*props
;
2929 size_t sizeof_props
;
2930 size_t sizeof_voice
;
2936 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2939 /* Allocate the voice pointers, voices, and the voices' stored source
2940 * property set (including the dynamically-sized Send[] array) in one
2943 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2944 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2945 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2947 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2948 /* The voice and property objects are stored interleaved since they're
2951 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2952 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2956 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2957 const ALsizei s_count
= mini(old_sends
, num_sends
);
2959 for(;v
< v_count
;v
++)
2961 ALvoice
*old_voice
= context
->Voices
[v
];
2964 /* Copy the old voice data and source property set to the new
2967 *voice
= *old_voice
;
2968 for(i
= 0;i
< s_count
;i
++)
2969 voice
->Send
[i
] = old_voice
->Send
[i
];
2970 *props
= *(old_voice
->Props
);
2971 for(i
= 0;i
< s_count
;i
++)
2972 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2974 /* Set this voice's property set pointer and voice reference. */
2975 voice
->Props
= props
;
2978 /* Increment pointers to the next storage space. */
2979 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2980 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2982 /* Deinit any left over voices that weren't copied over to the new
2983 * array. NOTE: If this does anything, v equals num_voices and
2984 * num_voices is less than VoiceCount, so the following loop won't do
2987 for(;v
< context
->VoiceCount
;v
++)
2988 DeinitVoice(context
->Voices
[v
]);
2990 /* Finish setting the voices' property set pointers and references. */
2991 for(;v
< num_voices
;v
++)
2993 ATOMIC_INIT(&voice
->Update
, NULL
);
2995 voice
->Props
= props
;
2998 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2999 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
3002 al_free(context
->Voices
);
3003 context
->Voices
= voices
;
3004 context
->MaxVoices
= num_voices
;
3005 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
3009 /************************************************
3010 * Standard ALC functions
3011 ************************************************/
3015 * Return last ALC generated error code for the given device
3017 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
3021 if(VerifyDevice(&device
))
3023 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3024 ALCdevice_DecRef(device
);
3027 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
3033 /* alcSuspendContext
3035 * Suspends updates for the given context
3037 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
3042 if(!VerifyContext(&context
))
3043 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3046 ALCcontext_DeferUpdates(context
);
3047 ALCcontext_DecRef(context
);
3051 /* alcProcessContext
3053 * Resumes processing updates for the given context
3055 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
3060 if(!VerifyContext(&context
))
3061 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3064 ALCcontext_ProcessUpdates(context
);
3065 ALCcontext_DecRef(context
);
3072 * Returns information about the device, and error strings
3074 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
3076 const ALCchar
*value
= NULL
;
3084 case ALC_INVALID_ENUM
:
3085 value
= alcErrInvalidEnum
;
3088 case ALC_INVALID_VALUE
:
3089 value
= alcErrInvalidValue
;
3092 case ALC_INVALID_DEVICE
:
3093 value
= alcErrInvalidDevice
;
3096 case ALC_INVALID_CONTEXT
:
3097 value
= alcErrInvalidContext
;
3100 case ALC_OUT_OF_MEMORY
:
3101 value
= alcErrOutOfMemory
;
3104 case ALC_DEVICE_SPECIFIER
:
3105 value
= alcDefaultName
;
3108 case ALC_ALL_DEVICES_SPECIFIER
:
3109 if(VerifyDevice(&Device
))
3111 value
= alstr_get_cstr(Device
->DeviceName
);
3112 ALCdevice_DecRef(Device
);
3116 ProbeAllDevicesList();
3117 value
= alstr_get_cstr(alcAllDevicesList
);
3121 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3122 if(VerifyDevice(&Device
))
3124 value
= alstr_get_cstr(Device
->DeviceName
);
3125 ALCdevice_DecRef(Device
);
3129 ProbeCaptureDeviceList();
3130 value
= alstr_get_cstr(alcCaptureDeviceList
);
3134 /* Default devices are always first in the list */
3135 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3136 value
= alcDefaultName
;
3139 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3140 if(alstr_empty(alcAllDevicesList
))
3141 ProbeAllDevicesList();
3143 VerifyDevice(&Device
);
3145 free(alcDefaultAllDevicesSpecifier
);
3146 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3147 if(!alcDefaultAllDevicesSpecifier
)
3148 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3150 value
= alcDefaultAllDevicesSpecifier
;
3151 if(Device
) ALCdevice_DecRef(Device
);
3154 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3155 if(alstr_empty(alcCaptureDeviceList
))
3156 ProbeCaptureDeviceList();
3158 VerifyDevice(&Device
);
3160 free(alcCaptureDefaultDeviceSpecifier
);
3161 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3162 if(!alcCaptureDefaultDeviceSpecifier
)
3163 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3165 value
= alcCaptureDefaultDeviceSpecifier
;
3166 if(Device
) ALCdevice_DecRef(Device
);
3169 case ALC_EXTENSIONS
:
3170 if(!VerifyDevice(&Device
))
3171 value
= alcNoDeviceExtList
;
3174 value
= alcExtensionList
;
3175 ALCdevice_DecRef(Device
);
3179 case ALC_HRTF_SPECIFIER_SOFT
:
3180 if(!VerifyDevice(&Device
))
3181 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3184 almtx_lock(&Device
->BackendLock
);
3185 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3186 almtx_unlock(&Device
->BackendLock
);
3187 ALCdevice_DecRef(Device
);
3192 VerifyDevice(&Device
);
3193 alcSetError(Device
, ALC_INVALID_ENUM
);
3194 if(Device
) ALCdevice_DecRef(Device
);
3202 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3204 if(device
->Type
== Capture
) return 9;
3205 if(device
->Type
!= Loopback
) return 29;
3206 if(device
->FmtChans
== DevFmtAmbi3D
)
3211 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3215 if(size
<= 0 || values
== NULL
)
3217 alcSetError(device
, ALC_INVALID_VALUE
);
3225 case ALC_MAJOR_VERSION
:
3226 values
[0] = alcMajorVersion
;
3228 case ALC_MINOR_VERSION
:
3229 values
[0] = alcMinorVersion
;
3232 case ALC_ATTRIBUTES_SIZE
:
3233 case ALC_ALL_ATTRIBUTES
:
3237 case ALC_MONO_SOURCES
:
3238 case ALC_STEREO_SOURCES
:
3239 case ALC_CAPTURE_SAMPLES
:
3240 case ALC_FORMAT_CHANNELS_SOFT
:
3241 case ALC_FORMAT_TYPE_SOFT
:
3242 case ALC_AMBISONIC_LAYOUT_SOFT
:
3243 case ALC_AMBISONIC_SCALING_SOFT
:
3244 case ALC_AMBISONIC_ORDER_SOFT
:
3245 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3246 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3250 alcSetError(NULL
, ALC_INVALID_ENUM
);
3256 if(device
->Type
== Capture
)
3260 case ALC_ATTRIBUTES_SIZE
:
3261 values
[0] = NumAttrsForDevice(device
);
3264 case ALC_ALL_ATTRIBUTES
:
3265 if(size
< NumAttrsForDevice(device
))
3267 alcSetError(device
, ALC_INVALID_VALUE
);
3272 almtx_lock(&device
->BackendLock
);
3273 values
[i
++] = ALC_MAJOR_VERSION
;
3274 values
[i
++] = alcMajorVersion
;
3275 values
[i
++] = ALC_MINOR_VERSION
;
3276 values
[i
++] = alcMinorVersion
;
3277 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3278 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3279 values
[i
++] = ALC_CONNECTED
;
3280 values
[i
++] = ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
);
3281 almtx_unlock(&device
->BackendLock
);
3286 case ALC_MAJOR_VERSION
:
3287 values
[0] = alcMajorVersion
;
3289 case ALC_MINOR_VERSION
:
3290 values
[0] = alcMinorVersion
;
3293 case ALC_CAPTURE_SAMPLES
:
3294 almtx_lock(&device
->BackendLock
);
3295 values
[0] = V0(device
->Backend
,availableSamples
)();
3296 almtx_unlock(&device
->BackendLock
);
3300 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3304 alcSetError(device
, ALC_INVALID_ENUM
);
3313 case ALC_ATTRIBUTES_SIZE
:
3314 values
[0] = NumAttrsForDevice(device
);
3317 case ALC_ALL_ATTRIBUTES
:
3318 if(size
< NumAttrsForDevice(device
))
3320 alcSetError(device
, ALC_INVALID_VALUE
);
3325 almtx_lock(&device
->BackendLock
);
3326 values
[i
++] = ALC_MAJOR_VERSION
;
3327 values
[i
++] = alcMajorVersion
;
3328 values
[i
++] = ALC_MINOR_VERSION
;
3329 values
[i
++] = alcMinorVersion
;
3330 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3331 values
[i
++] = alcEFXMajorVersion
;
3332 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3333 values
[i
++] = alcEFXMinorVersion
;
3335 values
[i
++] = ALC_FREQUENCY
;
3336 values
[i
++] = device
->Frequency
;
3337 if(device
->Type
!= Loopback
)
3339 values
[i
++] = ALC_REFRESH
;
3340 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3342 values
[i
++] = ALC_SYNC
;
3343 values
[i
++] = ALC_FALSE
;
3347 if(device
->FmtChans
== DevFmtAmbi3D
)
3349 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3350 values
[i
++] = device
->AmbiLayout
;
3352 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3353 values
[i
++] = device
->AmbiScale
;
3355 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3356 values
[i
++] = device
->AmbiOrder
;
3359 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3360 values
[i
++] = device
->FmtChans
;
3362 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3363 values
[i
++] = device
->FmtType
;
3366 values
[i
++] = ALC_MONO_SOURCES
;
3367 values
[i
++] = device
->NumMonoSources
;
3369 values
[i
++] = ALC_STEREO_SOURCES
;
3370 values
[i
++] = device
->NumStereoSources
;
3372 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3373 values
[i
++] = device
->NumAuxSends
;
3375 values
[i
++] = ALC_HRTF_SOFT
;
3376 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3378 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3379 values
[i
++] = device
->HrtfStatus
;
3381 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3382 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3384 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3385 values
[i
++] = MAX_AMBI_ORDER
;
3386 almtx_unlock(&device
->BackendLock
);
3391 case ALC_MAJOR_VERSION
:
3392 values
[0] = alcMajorVersion
;
3395 case ALC_MINOR_VERSION
:
3396 values
[0] = alcMinorVersion
;
3399 case ALC_EFX_MAJOR_VERSION
:
3400 values
[0] = alcEFXMajorVersion
;
3403 case ALC_EFX_MINOR_VERSION
:
3404 values
[0] = alcEFXMinorVersion
;
3408 values
[0] = device
->Frequency
;
3412 if(device
->Type
== Loopback
)
3414 alcSetError(device
, ALC_INVALID_DEVICE
);
3417 almtx_lock(&device
->BackendLock
);
3418 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3419 almtx_unlock(&device
->BackendLock
);
3423 if(device
->Type
== Loopback
)
3425 alcSetError(device
, ALC_INVALID_DEVICE
);
3428 values
[0] = ALC_FALSE
;
3431 case ALC_FORMAT_CHANNELS_SOFT
:
3432 if(device
->Type
!= Loopback
)
3434 alcSetError(device
, ALC_INVALID_DEVICE
);
3437 values
[0] = device
->FmtChans
;
3440 case ALC_FORMAT_TYPE_SOFT
:
3441 if(device
->Type
!= Loopback
)
3443 alcSetError(device
, ALC_INVALID_DEVICE
);
3446 values
[0] = device
->FmtType
;
3449 case ALC_AMBISONIC_LAYOUT_SOFT
:
3450 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3452 alcSetError(device
, ALC_INVALID_DEVICE
);
3455 values
[0] = device
->AmbiLayout
;
3458 case ALC_AMBISONIC_SCALING_SOFT
:
3459 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3461 alcSetError(device
, ALC_INVALID_DEVICE
);
3464 values
[0] = device
->AmbiScale
;
3467 case ALC_AMBISONIC_ORDER_SOFT
:
3468 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3470 alcSetError(device
, ALC_INVALID_DEVICE
);
3473 values
[0] = device
->AmbiOrder
;
3476 case ALC_MONO_SOURCES
:
3477 values
[0] = device
->NumMonoSources
;
3480 case ALC_STEREO_SOURCES
:
3481 values
[0] = device
->NumStereoSources
;
3484 case ALC_MAX_AUXILIARY_SENDS
:
3485 values
[0] = device
->NumAuxSends
;
3489 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3493 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3496 case ALC_HRTF_STATUS_SOFT
:
3497 values
[0] = device
->HrtfStatus
;
3500 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3501 almtx_lock(&device
->BackendLock
);
3502 FreeHrtfList(&device
->HrtfList
);
3503 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3504 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3505 almtx_unlock(&device
->BackendLock
);
3508 case ALC_OUTPUT_LIMITER_SOFT
:
3509 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3512 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3513 values
[0] = MAX_AMBI_ORDER
;
3517 alcSetError(device
, ALC_INVALID_ENUM
);
3525 * Returns information about the device and the version of OpenAL
3527 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3529 VerifyDevice(&device
);
3530 if(size
<= 0 || values
== NULL
)
3531 alcSetError(device
, ALC_INVALID_VALUE
);
3533 GetIntegerv(device
, param
, size
, values
);
3534 if(device
) ALCdevice_DecRef(device
);
3537 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3542 VerifyDevice(&device
);
3543 if(size
<= 0 || values
== NULL
)
3544 alcSetError(device
, ALC_INVALID_VALUE
);
3545 else if(!device
|| device
->Type
== Capture
)
3547 ivals
= malloc(size
* sizeof(ALCint
));
3548 size
= GetIntegerv(device
, pname
, size
, ivals
);
3549 for(i
= 0;i
< size
;i
++)
3550 values
[i
] = ivals
[i
];
3553 else /* render device */
3562 case ALC_ATTRIBUTES_SIZE
:
3563 *values
= NumAttrsForDevice(device
)+4;
3566 case ALC_ALL_ATTRIBUTES
:
3567 if(size
< NumAttrsForDevice(device
)+4)
3568 alcSetError(device
, ALC_INVALID_VALUE
);
3572 almtx_lock(&device
->BackendLock
);
3573 values
[i
++] = ALC_FREQUENCY
;
3574 values
[i
++] = device
->Frequency
;
3576 if(device
->Type
!= Loopback
)
3578 values
[i
++] = ALC_REFRESH
;
3579 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3581 values
[i
++] = ALC_SYNC
;
3582 values
[i
++] = ALC_FALSE
;
3586 if(device
->FmtChans
== DevFmtAmbi3D
)
3588 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3589 values
[i
++] = device
->AmbiLayout
;
3591 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3592 values
[i
++] = device
->AmbiScale
;
3594 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3595 values
[i
++] = device
->AmbiOrder
;
3598 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3599 values
[i
++] = device
->FmtChans
;
3601 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3602 values
[i
++] = device
->FmtType
;
3605 values
[i
++] = ALC_MONO_SOURCES
;
3606 values
[i
++] = device
->NumMonoSources
;
3608 values
[i
++] = ALC_STEREO_SOURCES
;
3609 values
[i
++] = device
->NumStereoSources
;
3611 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3612 values
[i
++] = device
->NumAuxSends
;
3614 values
[i
++] = ALC_HRTF_SOFT
;
3615 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3617 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3618 values
[i
++] = device
->HrtfStatus
;
3620 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3621 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3623 clock
= V0(device
->Backend
,getClockLatency
)();
3624 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3625 values
[i
++] = clock
.ClockTime
;
3627 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3628 values
[i
++] = clock
.Latency
;
3629 almtx_unlock(&device
->BackendLock
);
3635 case ALC_DEVICE_CLOCK_SOFT
:
3636 almtx_lock(&device
->BackendLock
);
3638 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3640 basecount
= device
->ClockBase
;
3641 samplecount
= device
->SamplesDone
;
3642 } while(refcount
!= ReadRef(&device
->MixCount
));
3643 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3644 almtx_unlock(&device
->BackendLock
);
3647 case ALC_DEVICE_LATENCY_SOFT
:
3648 almtx_lock(&device
->BackendLock
);
3649 clock
= V0(device
->Backend
,getClockLatency
)();
3650 almtx_unlock(&device
->BackendLock
);
3651 *values
= clock
.Latency
;
3654 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3656 alcSetError(device
, ALC_INVALID_VALUE
);
3659 almtx_lock(&device
->BackendLock
);
3660 clock
= V0(device
->Backend
,getClockLatency
)();
3661 almtx_unlock(&device
->BackendLock
);
3662 values
[0] = clock
.ClockTime
;
3663 values
[1] = clock
.Latency
;
3668 ivals
= malloc(size
* sizeof(ALCint
));
3669 size
= GetIntegerv(device
, pname
, size
, ivals
);
3670 for(i
= 0;i
< size
;i
++)
3671 values
[i
] = ivals
[i
];
3677 ALCdevice_DecRef(device
);
3681 /* alcIsExtensionPresent
3683 * Determines if there is support for a particular extension
3685 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3687 ALCboolean bResult
= ALC_FALSE
;
3689 VerifyDevice(&device
);
3692 alcSetError(device
, ALC_INVALID_VALUE
);
3695 size_t len
= strlen(extName
);
3696 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3699 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3700 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3705 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3709 } while(isspace(*ptr
));
3714 ALCdevice_DecRef(device
);
3719 /* alcGetProcAddress
3721 * Retrieves the function address for a particular extension function
3723 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3725 ALCvoid
*ptr
= NULL
;
3729 VerifyDevice(&device
);
3730 alcSetError(device
, ALC_INVALID_VALUE
);
3731 if(device
) ALCdevice_DecRef(device
);
3736 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3738 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3740 ptr
= alcFunctions
[i
].address
;
3752 * Get the value for a particular ALC enumeration name
3754 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3760 VerifyDevice(&device
);
3761 alcSetError(device
, ALC_INVALID_VALUE
);
3762 if(device
) ALCdevice_DecRef(device
);
3767 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3769 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3771 val
= alcEnumerations
[i
].value
;
3783 * Create and attach a context to the given device.
3785 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3787 ALCcontext
*ALContext
;
3791 /* Explicitly hold the list lock while taking the BackendLock in case the
3792 * device is asynchronously destropyed, to ensure this new context is
3793 * properly cleaned up after being made.
3796 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3797 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
3800 alcSetError(device
, ALC_INVALID_DEVICE
);
3801 if(device
) ALCdevice_DecRef(device
);
3804 almtx_lock(&device
->BackendLock
);
3807 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3809 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3810 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3812 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3815 almtx_unlock(&device
->BackendLock
);
3817 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3818 ALCdevice_DecRef(device
);
3822 InitRef(&ALContext
->ref
, 1);
3823 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3824 ALContext
->DefaultSlot
= NULL
;
3826 ALContext
->Voices
= NULL
;
3827 ALContext
->VoiceCount
= 0;
3828 ALContext
->MaxVoices
= 0;
3829 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3830 ALContext
->Device
= device
;
3831 ATOMIC_INIT(&ALContext
->next
, NULL
);
3833 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3835 almtx_unlock(&device
->BackendLock
);
3840 alcSetError(device
, err
);
3841 if(err
== ALC_INVALID_DEVICE
)
3843 V0(device
->Backend
,lock
)();
3844 aluHandleDisconnect(device
, "Device update failure");
3845 V0(device
->Backend
,unlock
)();
3847 ALCdevice_DecRef(device
);
3850 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3852 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3854 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3855 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3856 aluInitEffectPanning(ALContext
->DefaultSlot
);
3859 ALContext
->DefaultSlot
= NULL
;
3860 ERR("Failed to initialize the default effect slot\n");
3864 ALCdevice_IncRef(ALContext
->Device
);
3865 InitContext(ALContext
);
3867 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3870 ERR("volume-adjust must be finite: %f\n", valf
);
3873 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3875 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3876 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3877 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3880 UpdateListenerProps(ALContext
);
3883 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3885 ATOMIC_STORE(&ALContext
->next
, head
, almemory_order_relaxed
);
3886 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3889 almtx_unlock(&device
->BackendLock
);
3891 if(ALContext
->DefaultSlot
)
3893 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3894 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3896 ERR("Failed to initialize the default effect\n");
3899 ALCdevice_DecRef(device
);
3901 TRACE("Created context %p\n", ALContext
);
3905 /* alcDestroyContext
3907 * Remove a context from its device
3909 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3914 if(!VerifyContext(&context
))
3917 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3921 Device
= context
->Device
;
3924 almtx_lock(&Device
->BackendLock
);
3925 if(!ReleaseContext(context
, Device
))
3927 V0(Device
->Backend
,stop
)();
3928 Device
->Flags
&= ~DEVICE_RUNNING
;
3930 almtx_unlock(&Device
->BackendLock
);
3934 ALCcontext_DecRef(context
);
3938 /* alcGetCurrentContext
3940 * Returns the currently active context on the calling thread
3942 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3944 ALCcontext
*Context
= altss_get(LocalContext
);
3945 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3949 /* alcGetThreadContext
3951 * Returns the currently active thread-local context
3953 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3955 return altss_get(LocalContext
);
3959 /* alcMakeContextCurrent
3961 * Makes the given context the active process-wide context, and removes the
3962 * thread-local context for the calling thread.
3964 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3966 /* context must be valid or NULL */
3967 if(context
&& !VerifyContext(&context
))
3969 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3972 /* context's reference count is already incremented */
3973 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3974 if(context
) ALCcontext_DecRef(context
);
3976 if((context
=altss_get(LocalContext
)) != NULL
)
3978 altss_set(LocalContext
, NULL
);
3979 ALCcontext_DecRef(context
);
3985 /* alcSetThreadContext
3987 * Makes the given context the active context for the current thread
3989 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3993 /* context must be valid or NULL */
3994 if(context
&& !VerifyContext(&context
))
3996 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3999 /* context's reference count is already incremented */
4000 old
= altss_get(LocalContext
);
4001 altss_set(LocalContext
, context
);
4002 if(old
) ALCcontext_DecRef(old
);
4008 /* alcGetContextsDevice
4010 * Returns the device that a particular context is attached to
4012 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
4016 if(!VerifyContext(&Context
))
4018 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
4021 Device
= Context
->Device
;
4022 ALCcontext_DecRef(Context
);
4030 * Opens the named device.
4032 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
4034 ALCbackendFactory
*factory
;
4041 if(!PlaybackBackend
.name
)
4043 alcSetError(NULL
, ALC_INVALID_VALUE
);
4047 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
4049 /* Some old Windows apps hardcode these expecting OpenAL to use a
4050 * specific audio API, even when they're not enumerated. Creative's
4051 * router effectively ignores them too.
4053 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
4054 || strcasecmp(deviceName
, "MMSYSTEM") == 0
4059 device
= al_calloc(16, sizeof(ALCdevice
));
4062 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4067 InitDevice(device
, Playback
);
4070 device
->FmtChans
= DevFmtChannelsDefault
;
4071 device
->FmtType
= DevFmtTypeDefault
;
4072 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4073 device
->IsHeadphones
= AL_FALSE
;
4074 device
->AmbiLayout
= AmbiLayout_Default
;
4075 device
->AmbiScale
= AmbiNorm_Default
;
4076 device
->NumUpdates
= 3;
4077 device
->UpdateSize
= 1024;
4079 device
->SourcesMax
= 256;
4080 device
->AuxiliaryEffectSlotMax
= 64;
4081 device
->NumAuxSends
= DEFAULT_SENDS
;
4083 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
4085 static const struct {
4086 const char name
[16];
4087 enum DevFmtChannels chans
;
4090 { "mono", DevFmtMono
, 0 },
4091 { "stereo", DevFmtStereo
, 0 },
4092 { "quad", DevFmtQuad
, 0 },
4093 { "surround51", DevFmtX51
, 0 },
4094 { "surround61", DevFmtX61
, 0 },
4095 { "surround71", DevFmtX71
, 0 },
4096 { "surround51rear", DevFmtX51Rear
, 0 },
4097 { "ambi1", DevFmtAmbi3D
, 1 },
4098 { "ambi2", DevFmtAmbi3D
, 2 },
4099 { "ambi3", DevFmtAmbi3D
, 3 },
4103 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4105 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4107 device
->FmtChans
= chanlist
[i
].chans
;
4108 device
->AmbiOrder
= chanlist
[i
].order
;
4109 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4113 if(i
== COUNTOF(chanlist
))
4114 ERR("Unsupported channels: %s\n", fmt
);
4116 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4118 static const struct {
4119 const char name
[16];
4120 enum DevFmtType type
;
4122 { "int8", DevFmtByte
},
4123 { "uint8", DevFmtUByte
},
4124 { "int16", DevFmtShort
},
4125 { "uint16", DevFmtUShort
},
4126 { "int32", DevFmtInt
},
4127 { "uint32", DevFmtUInt
},
4128 { "float32", DevFmtFloat
},
4132 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4134 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4136 device
->FmtType
= typelist
[i
].type
;
4137 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4141 if(i
== COUNTOF(typelist
))
4142 ERR("Unsupported sample-type: %s\n", fmt
);
4145 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4147 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4148 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4149 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4150 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4153 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4154 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4156 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4157 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4158 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4159 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4161 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4162 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4164 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4165 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4166 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4168 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4169 device
->NumAuxSends
= clampi(
4170 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4173 device
->NumStereoSources
= 1;
4174 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4176 factory
= PlaybackBackend
.getFactory();
4177 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
4178 if(!device
->Backend
)
4181 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4185 // Find a playback device to open
4186 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4189 alcSetError(NULL
, err
);
4193 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4195 if(strcasecmp(fmt
, "fuma") == 0)
4197 device
->AmbiLayout
= AmbiLayout_FuMa
;
4198 device
->AmbiScale
= AmbiNorm_FuMa
;
4200 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4202 device
->AmbiLayout
= AmbiLayout_ACN
;
4203 device
->AmbiScale
= AmbiNorm_SN3D
;
4205 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4207 device
->AmbiLayout
= AmbiLayout_ACN
;
4208 device
->AmbiScale
= AmbiNorm_N3D
;
4211 ERR("Unsupported ambi-format: %s\n", fmt
);
4214 device
->Limiter
= CreateDeviceLimiter(device
);
4217 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4219 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4220 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4223 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4229 * Closes the given device.
4231 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4233 ALCdevice
*iter
, *origdev
, *nextdev
;
4237 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4241 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4242 } while(iter
!= NULL
);
4243 if(!iter
|| iter
->Type
== Capture
)
4245 alcSetError(iter
, ALC_INVALID_DEVICE
);
4249 almtx_lock(&device
->BackendLock
);
4252 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4253 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4259 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4263 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4266 ALCcontext
*next
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
4267 WARN("Releasing context %p\n", ctx
);
4268 ReleaseContext(ctx
, device
);
4271 if((device
->Flags
&DEVICE_RUNNING
))
4272 V0(device
->Backend
,stop
)();
4273 device
->Flags
&= ~DEVICE_RUNNING
;
4274 almtx_unlock(&device
->BackendLock
);
4276 ALCdevice_DecRef(device
);
4282 /************************************************
4283 * ALC capture functions
4284 ************************************************/
4285 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4287 ALCbackendFactory
*factory
;
4288 ALCdevice
*device
= NULL
;
4293 if(!CaptureBackend
.name
)
4295 alcSetError(NULL
, ALC_INVALID_VALUE
);
4301 alcSetError(NULL
, ALC_INVALID_VALUE
);
4305 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4308 device
= al_calloc(16, sizeof(ALCdevice
));
4311 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4316 InitDevice(device
, Capture
);
4318 device
->Frequency
= frequency
;
4319 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4321 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4324 alcSetError(NULL
, ALC_INVALID_ENUM
);
4327 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4328 device
->IsHeadphones
= AL_FALSE
;
4329 device
->AmbiOrder
= 0;
4330 device
->AmbiLayout
= AmbiLayout_Default
;
4331 device
->AmbiScale
= AmbiNorm_Default
;
4333 device
->UpdateSize
= samples
;
4334 device
->NumUpdates
= 1;
4336 factory
= CaptureBackend
.getFactory();
4337 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4338 if(!device
->Backend
)
4341 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4345 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4346 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4347 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4349 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4352 alcSetError(NULL
, err
);
4357 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4359 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4360 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4363 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4367 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4369 ALCdevice
*iter
, *origdev
, *nextdev
;
4372 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4376 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4377 } while(iter
!= NULL
);
4378 if(!iter
|| iter
->Type
!= Capture
)
4380 alcSetError(iter
, ALC_INVALID_DEVICE
);
4386 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4387 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4393 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4397 ALCdevice_DecRef(device
);
4402 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4404 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4405 alcSetError(device
, ALC_INVALID_DEVICE
);
4408 almtx_lock(&device
->BackendLock
);
4409 if(!ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
))
4410 alcSetError(device
, ALC_INVALID_DEVICE
);
4411 else if(!(device
->Flags
&DEVICE_RUNNING
))
4413 if(V0(device
->Backend
,start
)())
4414 device
->Flags
|= DEVICE_RUNNING
;
4417 aluHandleDisconnect(device
, "Device start failure");
4418 alcSetError(device
, ALC_INVALID_DEVICE
);
4421 almtx_unlock(&device
->BackendLock
);
4424 if(device
) ALCdevice_DecRef(device
);
4427 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4429 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4430 alcSetError(device
, ALC_INVALID_DEVICE
);
4433 almtx_lock(&device
->BackendLock
);
4434 if((device
->Flags
&DEVICE_RUNNING
))
4435 V0(device
->Backend
,stop
)();
4436 device
->Flags
&= ~DEVICE_RUNNING
;
4437 almtx_unlock(&device
->BackendLock
);
4440 if(device
) ALCdevice_DecRef(device
);
4443 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4445 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4446 alcSetError(device
, ALC_INVALID_DEVICE
);
4449 ALCenum err
= ALC_INVALID_VALUE
;
4451 almtx_lock(&device
->BackendLock
);
4452 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4453 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4454 almtx_unlock(&device
->BackendLock
);
4456 if(err
!= ALC_NO_ERROR
)
4457 alcSetError(device
, err
);
4459 if(device
) ALCdevice_DecRef(device
);
4463 /************************************************
4464 * ALC loopback functions
4465 ************************************************/
4467 /* alcLoopbackOpenDeviceSOFT
4469 * Open a loopback device, for manual rendering.
4471 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4473 ALCbackendFactory
*factory
;
4478 /* Make sure the device name, if specified, is us. */
4479 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4481 alcSetError(NULL
, ALC_INVALID_VALUE
);
4485 device
= al_calloc(16, sizeof(ALCdevice
));
4488 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4493 InitDevice(device
, Loopback
);
4495 device
->SourcesMax
= 256;
4496 device
->AuxiliaryEffectSlotMax
= 64;
4497 device
->NumAuxSends
= DEFAULT_SENDS
;
4500 device
->NumUpdates
= 0;
4501 device
->UpdateSize
= 0;
4503 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4504 device
->FmtChans
= DevFmtChannelsDefault
;
4505 device
->FmtType
= DevFmtTypeDefault
;
4506 device
->IsHeadphones
= AL_FALSE
;
4507 device
->AmbiLayout
= AmbiLayout_Default
;
4508 device
->AmbiScale
= AmbiNorm_Default
;
4510 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4511 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4513 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4514 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4515 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4517 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4518 device
->NumAuxSends
= clampi(
4519 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4522 device
->NumStereoSources
= 1;
4523 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4525 factory
= ALCloopbackFactory_getFactory();
4526 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4527 if(!device
->Backend
)
4530 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4534 // Open the "backend"
4535 V(device
->Backend
,open
)("Loopback");
4537 device
->Limiter
= CreateDeviceLimiter(device
);
4540 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4542 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4543 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4546 TRACE("Created device %p\n", device
);
4550 /* alcIsRenderFormatSupportedSOFT
4552 * Determines if the loopback device supports the given format for rendering.
4554 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4556 ALCboolean ret
= ALC_FALSE
;
4558 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4559 alcSetError(device
, ALC_INVALID_DEVICE
);
4561 alcSetError(device
, ALC_INVALID_VALUE
);
4564 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4567 if(device
) ALCdevice_DecRef(device
);
4572 /* alcRenderSamplesSOFT
4574 * Renders some samples into a buffer, using the format last set by the
4575 * attributes given to alcCreateContext.
4577 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4579 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4580 alcSetError(device
, ALC_INVALID_DEVICE
);
4581 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4582 alcSetError(device
, ALC_INVALID_VALUE
);
4585 V0(device
->Backend
,lock
)();
4586 aluMixData(device
, buffer
, samples
);
4587 V0(device
->Backend
,unlock
)();
4589 if(device
) ALCdevice_DecRef(device
);
4593 /************************************************
4594 * ALC DSP pause/resume functions
4595 ************************************************/
4597 /* alcDevicePauseSOFT
4599 * Pause the DSP to stop audio processing.
4601 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4603 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4604 alcSetError(device
, ALC_INVALID_DEVICE
);
4607 almtx_lock(&device
->BackendLock
);
4608 if((device
->Flags
&DEVICE_RUNNING
))
4609 V0(device
->Backend
,stop
)();
4610 device
->Flags
&= ~DEVICE_RUNNING
;
4611 device
->Flags
|= DEVICE_PAUSED
;
4612 almtx_unlock(&device
->BackendLock
);
4614 if(device
) ALCdevice_DecRef(device
);
4617 /* alcDeviceResumeSOFT
4619 * Resume the DSP to restart audio processing.
4621 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4623 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4624 alcSetError(device
, ALC_INVALID_DEVICE
);
4627 almtx_lock(&device
->BackendLock
);
4628 if((device
->Flags
&DEVICE_PAUSED
))
4630 device
->Flags
&= ~DEVICE_PAUSED
;
4631 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4633 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4634 device
->Flags
|= DEVICE_RUNNING
;
4637 V0(device
->Backend
,lock
)();
4638 aluHandleDisconnect(device
, "Device start failure");
4639 V0(device
->Backend
,unlock
)();
4640 alcSetError(device
, ALC_INVALID_DEVICE
);
4644 almtx_unlock(&device
->BackendLock
);
4646 if(device
) ALCdevice_DecRef(device
);
4650 /************************************************
4651 * ALC HRTF functions
4652 ************************************************/
4654 /* alcGetStringiSOFT
4656 * Gets a string parameter at the given index.
4658 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4660 const ALCchar
*str
= NULL
;
4662 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4663 alcSetError(device
, ALC_INVALID_DEVICE
);
4664 else switch(paramName
)
4666 case ALC_HRTF_SPECIFIER_SOFT
:
4667 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4668 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4670 alcSetError(device
, ALC_INVALID_VALUE
);
4674 alcSetError(device
, ALC_INVALID_ENUM
);
4677 if(device
) ALCdevice_DecRef(device
);
4682 /* alcResetDeviceSOFT
4684 * Resets the given device output, using the specified attribute list.
4686 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4691 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4692 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
4695 alcSetError(device
, ALC_INVALID_DEVICE
);
4696 if(device
) ALCdevice_DecRef(device
);
4699 almtx_lock(&device
->BackendLock
);
4702 err
= UpdateDeviceParams(device
, attribs
);
4703 almtx_unlock(&device
->BackendLock
);
4705 if(err
!= ALC_NO_ERROR
)
4707 alcSetError(device
, err
);
4708 if(err
== ALC_INVALID_DEVICE
)
4710 V0(device
->Backend
,lock
)();
4711 aluHandleDisconnect(device
, "Device start failure");
4712 V0(device
->Backend
,unlock
)();
4714 ALCdevice_DecRef(device
);
4717 ALCdevice_DecRef(device
);