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
),
553 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_FREQUENCY_SHIFTER_FREQUENCY
),
636 DECL(AL_FREQUENCY_SHIFTER_LEFT_DIRECTION
),
637 DECL(AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION
),
639 DECL(AL_RING_MODULATOR_FREQUENCY
),
640 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
641 DECL(AL_RING_MODULATOR_WAVEFORM
),
643 DECL(AL_PITCH_SHIFTER_COARSE_TUNE
),
644 DECL(AL_PITCH_SHIFTER_FINE_TUNE
),
646 DECL(AL_COMPRESSOR_ONOFF
),
648 DECL(AL_EQUALIZER_LOW_GAIN
),
649 DECL(AL_EQUALIZER_LOW_CUTOFF
),
650 DECL(AL_EQUALIZER_MID1_GAIN
),
651 DECL(AL_EQUALIZER_MID1_CENTER
),
652 DECL(AL_EQUALIZER_MID1_WIDTH
),
653 DECL(AL_EQUALIZER_MID2_GAIN
),
654 DECL(AL_EQUALIZER_MID2_CENTER
),
655 DECL(AL_EQUALIZER_MID2_WIDTH
),
656 DECL(AL_EQUALIZER_HIGH_GAIN
),
657 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
659 DECL(AL_DEDICATED_GAIN
),
661 DECL(AL_NUM_RESAMPLERS_SOFT
),
662 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
663 DECL(AL_SOURCE_RESAMPLER_SOFT
),
664 DECL(AL_RESAMPLER_NAME_SOFT
),
666 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
669 DECL(AL_MAP_READ_BIT_SOFT
),
670 DECL(AL_MAP_WRITE_BIT_SOFT
),
671 DECL(AL_MAP_PERSISTENT_BIT_SOFT
),
672 DECL(AL_PRESERVE_DATA_BIT_SOFT
),
674 DECL(AL_EVENT_CALLBACK_FUNCTION_SOFT
),
675 DECL(AL_EVENT_CALLBACK_USER_PARAM_SOFT
),
676 DECL(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT
),
677 DECL(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT
),
678 DECL(AL_EVENT_TYPE_ERROR_SOFT
),
679 DECL(AL_EVENT_TYPE_PERFORMANCE_SOFT
),
680 DECL(AL_EVENT_TYPE_DEPRECATED_SOFT
),
684 static const ALCchar alcNoError
[] = "No Error";
685 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
686 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
687 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
688 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
689 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
692 /************************************************
694 ************************************************/
696 /* Enumerated device names */
697 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
699 static al_string alcAllDevicesList
;
700 static al_string alcCaptureDeviceList
;
702 /* Default is always the first in the list */
703 static ALCchar
*alcDefaultAllDevicesSpecifier
;
704 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
706 /* Default context extensions */
707 static const ALchar alExtList
[] =
711 "AL_EXT_EXPONENT_DISTANCE "
714 "AL_EXT_LINEAR_DISTANCE "
717 "AL_EXT_MULAW_BFORMAT "
718 "AL_EXT_MULAW_MCFORMATS "
720 "AL_EXT_source_distance_model "
721 "AL_EXT_SOURCE_RADIUS "
722 "AL_EXT_STEREO_ANGLES "
723 "AL_LOKI_quadriphonic "
724 "AL_SOFT_block_alignment "
725 "AL_SOFT_deferred_updates "
726 "AL_SOFT_direct_channels "
728 "AL_SOFT_gain_clamp_ex "
729 "AL_SOFT_loop_points "
730 "AL_SOFTX_map_buffer "
732 "AL_SOFT_source_latency "
733 "AL_SOFT_source_length "
734 "AL_SOFT_source_resampler "
735 "AL_SOFT_source_spatialize";
737 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
739 /* Thread-local current context */
740 static altss_t LocalContext
;
741 /* Process-wide current context */
742 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
744 /* Mixing thread piority level */
749 enum LogLevel LogLevel
= LogWarning
;
751 enum LogLevel LogLevel
= LogError
;
754 /* Flag to trap ALC device errors */
755 static ALCboolean TrapALCError
= ALC_FALSE
;
757 /* One-time configuration init control */
758 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
760 /* Default effect that applies to sources that don't have an effect on send 0 */
761 static ALeffect DefaultEffect
;
763 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
766 static ALCboolean SuspendDefers
= ALC_TRUE
;
769 /************************************************
771 ************************************************/
772 static const ALCchar alcNoDeviceExtList
[] =
773 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
774 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
775 static const ALCchar alcExtensionList
[] =
776 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
777 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
778 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
779 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
780 static const ALCint alcMajorVersion
= 1;
781 static const ALCint alcMinorVersion
= 1;
783 static const ALCint alcEFXMajorVersion
= 1;
784 static const ALCint alcEFXMinorVersion
= 0;
787 /************************************************
789 ************************************************/
790 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
792 static almtx_t ListLock
;
793 static inline void LockLists(void)
795 int ret
= almtx_lock(&ListLock
);
796 assert(ret
== althrd_success
);
798 static inline void UnlockLists(void)
800 int ret
= almtx_unlock(&ListLock
);
801 assert(ret
== althrd_success
);
804 /************************************************
805 * Library initialization
806 ************************************************/
808 static void alc_init(void);
809 static void alc_deinit(void);
810 static void alc_deinit_safe(void);
812 #ifndef AL_LIBTYPE_STATIC
813 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
817 case DLL_PROCESS_ATTACH
:
818 /* Pin the DLL so we won't get unloaded until the process terminates */
819 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
820 (WCHAR
*)hModule
, &hModule
);
824 case DLL_THREAD_DETACH
:
825 althrd_thread_detach();
828 case DLL_PROCESS_DETACH
:
837 #elif defined(_MSC_VER)
838 #pragma section(".CRT$XCU",read)
839 static void alc_constructor(void);
840 static void alc_destructor(void);
841 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
843 static void alc_constructor(void)
845 atexit(alc_destructor
);
849 static void alc_destructor(void)
853 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor
));
855 static void alc_deinit(void) __attribute__((destructor
));
857 #error "No static initialization available on this platform!"
860 #elif defined(HAVE_GCC_DESTRUCTOR)
862 static void alc_init(void) __attribute__((constructor
));
863 static void alc_deinit(void) __attribute__((destructor
));
866 #error "No global initialization available on this platform!"
869 static void ReleaseThreadCtx(void *ptr
);
870 static void alc_init(void)
877 AL_STRING_INIT(alcAllDevicesList
);
878 AL_STRING_INIT(alcCaptureDeviceList
);
880 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
881 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
884 str
= getenv("__ALSOFT_REVERSE_Z");
885 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
888 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
889 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
890 OverrideReverbSpeedOfSound
= AL_TRUE
;
892 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
893 assert(ret
== althrd_success
);
895 ret
= almtx_init(&ListLock
, almtx_recursive
);
896 assert(ret
== althrd_success
);
899 static void alc_initconfig(void)
901 const char *devs
, *str
;
906 str
= getenv("ALSOFT_LOGLEVEL");
909 long lvl
= strtol(str
, NULL
, 0);
910 if(lvl
>= NoLog
&& lvl
<= LogRef
)
914 str
= getenv("ALSOFT_LOGFILE");
917 FILE *logfile
= al_fopen(str
, "wt");
918 if(logfile
) LogFile
= logfile
;
919 else ERR("Failed to open log file '%s'\n", str
);
922 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
923 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
928 if(BackendListSize
> 0)
929 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
930 for(i
= 1;i
< BackendListSize
;i
++)
931 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
932 TRACE("Supported backends: %s\n", buf
);
936 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
939 if(strcasecmp(str
, "ignore") == 0)
941 SuspendDefers
= ALC_FALSE
;
942 TRACE("Selected context suspend behavior, \"ignore\"\n");
945 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
949 #if defined(HAVE_SSE4_1)
950 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
951 #elif defined(HAVE_SSE3)
952 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
953 #elif defined(HAVE_SSE2)
954 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
955 #elif defined(HAVE_SSE)
956 capfilter
|= CPU_CAP_SSE
;
959 capfilter
|= CPU_CAP_NEON
;
961 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
963 if(strcasecmp(str
, "all") == 0)
968 const char *next
= str
;
972 while(isspace(str
[0]))
974 next
= strchr(str
, ',');
976 if(!str
[0] || str
[0] == ',')
979 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
980 while(len
> 0 && isspace(str
[len
-1]))
982 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
983 capfilter
&= ~CPU_CAP_SSE
;
984 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
985 capfilter
&= ~CPU_CAP_SSE2
;
986 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
987 capfilter
&= ~CPU_CAP_SSE3
;
988 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
989 capfilter
&= ~CPU_CAP_SSE4_1
;
990 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
991 capfilter
&= ~CPU_CAP_NEON
;
993 WARN("Invalid CPU extension \"%s\"\n", str
);
997 FillCPUCaps(capfilter
);
1004 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1009 str
= getenv("ALSOFT_TRAP_ERROR");
1010 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1012 TrapALError
= AL_TRUE
;
1013 TrapALCError
= AL_TRUE
;
1017 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1018 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1019 TrapALError
= AL_TRUE
;
1020 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1022 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1023 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1024 TrapALCError
= ALC_TRUE
;
1025 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1028 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1029 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1031 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1032 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1036 const char *next
= devs
;
1037 int endlist
, delitem
;
1042 while(isspace(devs
[0]))
1044 next
= strchr(devs
, ',');
1046 delitem
= (devs
[0] == '-');
1047 if(devs
[0] == '-') devs
++;
1049 if(!devs
[0] || devs
[0] == ',')
1056 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1057 while(len
> 0 && isspace(devs
[len
-1]))
1060 /* HACK: For backwards compatibility, convert backend references of
1061 * mmdevapi to wasapi. This should eventually be removed.
1063 if(len
== 8 && strncmp(devs
, "mmdevapi", len
) == 0)
1069 for(n
= i
;n
< BackendListSize
;n
++)
1071 if(len
== strlen(BackendList
[n
].name
) &&
1072 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1076 for(;n
+1 < BackendListSize
;n
++)
1077 BackendList
[n
] = BackendList
[n
+1];
1082 struct BackendInfo Bkp
= BackendList
[n
];
1084 BackendList
[n
] = BackendList
[n
-1];
1085 BackendList
[n
] = Bkp
;
1095 BackendListSize
= i
;
1098 for(n
= i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1100 ALCbackendFactory
*factory
;
1101 BackendList
[n
] = BackendList
[i
];
1103 factory
= BackendList
[n
].getFactory();
1104 if(!V0(factory
,init
)())
1106 WARN("Failed to initialize backend \"%s\"\n", BackendList
[n
].name
);
1110 TRACE("Initialized backend \"%s\"\n", BackendList
[n
].name
);
1111 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1113 PlaybackBackend
= BackendList
[n
];
1114 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1116 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1118 CaptureBackend
= BackendList
[n
];
1119 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1123 BackendListSize
= n
;
1126 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1130 if(!PlaybackBackend
.name
)
1131 WARN("No playback backend available!\n");
1132 if(!CaptureBackend
.name
)
1133 WARN("No capture backend available!\n");
1135 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1138 const char *next
= str
;
1142 next
= strchr(str
, ',');
1144 if(!str
[0] || next
== str
)
1147 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1148 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1150 if(len
== strlen(EffectList
[n
].name
) &&
1151 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1152 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1157 InitEffect(&DefaultEffect
);
1158 str
= getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1160 LoadReverbPreset(str
, &DefaultEffect
);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1167 static JavaVM
*gJavaVM
;
1168 static pthread_key_t gJVMThreadKey
;
1170 static void CleanupJNIEnv(void* UNUSED(ptr
))
1172 JCALL0(gJavaVM
,DetachCurrentThread
)();
1175 void *Android_GetJNIEnv(void)
1179 WARN("gJavaVM is NULL!\n");
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1196 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1199 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1202 ERR("Failed to attach current thread\n");
1205 pthread_setspecific(gJVMThreadKey
, env
);
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1217 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err
);
1228 pthread_setspecific(gJVMThreadKey
, env
);
1229 return JNI_VERSION_1_4
;
1234 /************************************************
1235 * Library deinitialization
1236 ************************************************/
1237 static void alc_cleanup(void)
1241 AL_STRING_DEINIT(alcAllDevicesList
);
1242 AL_STRING_DEINIT(alcCaptureDeviceList
);
1244 free(alcDefaultAllDevicesSpecifier
);
1245 alcDefaultAllDevicesSpecifier
= NULL
;
1246 free(alcCaptureDefaultDeviceSpecifier
);
1247 alcCaptureDefaultDeviceSpecifier
= NULL
;
1249 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1254 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
1255 } while(dev
!= NULL
);
1256 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1260 static void alc_deinit_safe(void)
1267 almtx_destroy(&ListLock
);
1268 altss_delete(LocalContext
);
1270 if(LogFile
!= stderr
)
1277 static void alc_deinit(void)
1283 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1284 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1286 for(i
= 0;i
< BackendListSize
;i
++)
1288 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1289 V0(factory
,deinit
)();
1292 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1293 V0(factory
,deinit
)();
1300 /************************************************
1301 * Device enumeration
1302 ************************************************/
1303 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1310 if(backendinfo
->getFactory
)
1312 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1313 V(factory
,probe
)(type
);
1318 static void ProbeAllDevicesList(void)
1319 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1320 static void ProbeCaptureDeviceList(void)
1321 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1323 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1325 size_t len
= strlen(name
);
1327 alstr_append_range(devnames
, name
, name
+len
+1);
1329 void AppendAllDevicesList(const ALCchar
*name
)
1330 { AppendDevice(name
, &alcAllDevicesList
); }
1331 void AppendCaptureDeviceList(const ALCchar
*name
)
1332 { AppendDevice(name
, &alcCaptureDeviceList
); }
1335 /************************************************
1336 * Device format information
1337 ************************************************/
1338 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1342 case DevFmtByte
: return "Signed Byte";
1343 case DevFmtUByte
: return "Unsigned Byte";
1344 case DevFmtShort
: return "Signed Short";
1345 case DevFmtUShort
: return "Unsigned Short";
1346 case DevFmtInt
: return "Signed Int";
1347 case DevFmtUInt
: return "Unsigned Int";
1348 case DevFmtFloat
: return "Float";
1350 return "(unknown type)";
1352 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1356 case DevFmtMono
: return "Mono";
1357 case DevFmtStereo
: return "Stereo";
1358 case DevFmtQuad
: return "Quadraphonic";
1359 case DevFmtX51
: return "5.1 Surround";
1360 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1361 case DevFmtX61
: return "6.1 Surround";
1362 case DevFmtX71
: return "7.1 Surround";
1363 case DevFmtAmbi3D
: return "Ambisonic 3D";
1365 return "(unknown channels)";
1368 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1369 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1373 case DevFmtByte
: return sizeof(ALbyte
);
1374 case DevFmtUByte
: return sizeof(ALubyte
);
1375 case DevFmtShort
: return sizeof(ALshort
);
1376 case DevFmtUShort
: return sizeof(ALushort
);
1377 case DevFmtInt
: return sizeof(ALint
);
1378 case DevFmtUInt
: return sizeof(ALuint
);
1379 case DevFmtFloat
: return sizeof(ALfloat
);
1383 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1387 case DevFmtMono
: return 1;
1388 case DevFmtStereo
: return 2;
1389 case DevFmtQuad
: return 4;
1390 case DevFmtX51
: return 6;
1391 case DevFmtX51Rear
: return 6;
1392 case DevFmtX61
: return 7;
1393 case DevFmtX71
: return 8;
1394 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1395 (ambiorder
== 2) ? 9 :
1396 (ambiorder
== 1) ? 4 : 1;
1401 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1402 enum DevFmtType
*type
)
1404 static const struct {
1406 enum DevFmtChannels channels
;
1407 enum DevFmtType type
;
1409 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1410 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1411 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1413 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1414 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1415 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1417 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1418 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1419 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1421 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1422 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1423 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1425 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1426 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1427 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1429 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1430 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1431 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1435 for(i
= 0;i
< COUNTOF(list
);i
++)
1437 if(list
[i
].format
== format
)
1439 *chans
= list
[i
].channels
;
1440 *type
= list
[i
].type
;
1448 static ALCboolean
IsValidALCType(ALCenum type
)
1453 case ALC_UNSIGNED_BYTE_SOFT
:
1454 case ALC_SHORT_SOFT
:
1455 case ALC_UNSIGNED_SHORT_SOFT
:
1457 case ALC_UNSIGNED_INT_SOFT
:
1458 case ALC_FLOAT_SOFT
:
1464 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1469 case ALC_STEREO_SOFT
:
1471 case ALC_5POINT1_SOFT
:
1472 case ALC_6POINT1_SOFT
:
1473 case ALC_7POINT1_SOFT
:
1474 case ALC_BFORMAT3D_SOFT
:
1480 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1491 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1503 /************************************************
1504 * Miscellaneous ALC helpers
1505 ************************************************/
1507 /* SetDefaultWFXChannelOrder
1509 * Sets the default channel order used by WaveFormatEx.
1511 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1515 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1516 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1518 switch(device
->FmtChans
)
1521 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1524 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1525 device
->RealOut
.ChannelName
[1] = FrontRight
;
1528 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1529 device
->RealOut
.ChannelName
[1] = FrontRight
;
1530 device
->RealOut
.ChannelName
[2] = BackLeft
;
1531 device
->RealOut
.ChannelName
[3] = BackRight
;
1534 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1535 device
->RealOut
.ChannelName
[1] = FrontRight
;
1536 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1537 device
->RealOut
.ChannelName
[3] = LFE
;
1538 device
->RealOut
.ChannelName
[4] = SideLeft
;
1539 device
->RealOut
.ChannelName
[5] = SideRight
;
1542 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1543 device
->RealOut
.ChannelName
[1] = FrontRight
;
1544 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1545 device
->RealOut
.ChannelName
[3] = LFE
;
1546 device
->RealOut
.ChannelName
[4] = BackLeft
;
1547 device
->RealOut
.ChannelName
[5] = BackRight
;
1550 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1551 device
->RealOut
.ChannelName
[1] = FrontRight
;
1552 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1553 device
->RealOut
.ChannelName
[3] = LFE
;
1554 device
->RealOut
.ChannelName
[4] = BackCenter
;
1555 device
->RealOut
.ChannelName
[5] = SideLeft
;
1556 device
->RealOut
.ChannelName
[6] = SideRight
;
1559 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1560 device
->RealOut
.ChannelName
[1] = FrontRight
;
1561 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1562 device
->RealOut
.ChannelName
[3] = LFE
;
1563 device
->RealOut
.ChannelName
[4] = BackLeft
;
1564 device
->RealOut
.ChannelName
[5] = BackRight
;
1565 device
->RealOut
.ChannelName
[6] = SideLeft
;
1566 device
->RealOut
.ChannelName
[7] = SideRight
;
1569 device
->RealOut
.ChannelName
[0] = Aux0
;
1570 if(device
->AmbiOrder
> 0)
1572 device
->RealOut
.ChannelName
[1] = Aux1
;
1573 device
->RealOut
.ChannelName
[2] = Aux2
;
1574 device
->RealOut
.ChannelName
[3] = Aux3
;
1576 if(device
->AmbiOrder
> 1)
1578 device
->RealOut
.ChannelName
[4] = Aux4
;
1579 device
->RealOut
.ChannelName
[5] = Aux5
;
1580 device
->RealOut
.ChannelName
[6] = Aux6
;
1581 device
->RealOut
.ChannelName
[7] = Aux7
;
1582 device
->RealOut
.ChannelName
[8] = Aux8
;
1584 if(device
->AmbiOrder
> 2)
1586 device
->RealOut
.ChannelName
[9] = Aux9
;
1587 device
->RealOut
.ChannelName
[10] = Aux10
;
1588 device
->RealOut
.ChannelName
[11] = Aux11
;
1589 device
->RealOut
.ChannelName
[12] = Aux12
;
1590 device
->RealOut
.ChannelName
[13] = Aux13
;
1591 device
->RealOut
.ChannelName
[14] = Aux14
;
1592 device
->RealOut
.ChannelName
[15] = Aux15
;
1598 /* SetDefaultChannelOrder
1600 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1602 void SetDefaultChannelOrder(ALCdevice
*device
)
1606 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1607 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1609 switch(device
->FmtChans
)
1612 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1613 device
->RealOut
.ChannelName
[1] = FrontRight
;
1614 device
->RealOut
.ChannelName
[2] = BackLeft
;
1615 device
->RealOut
.ChannelName
[3] = BackRight
;
1616 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1617 device
->RealOut
.ChannelName
[5] = LFE
;
1620 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1621 device
->RealOut
.ChannelName
[1] = FrontRight
;
1622 device
->RealOut
.ChannelName
[2] = BackLeft
;
1623 device
->RealOut
.ChannelName
[3] = BackRight
;
1624 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1625 device
->RealOut
.ChannelName
[5] = LFE
;
1626 device
->RealOut
.ChannelName
[6] = SideLeft
;
1627 device
->RealOut
.ChannelName
[7] = SideRight
;
1630 /* Same as WFX order */
1637 SetDefaultWFXChannelOrder(device
);
1642 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1643 extern inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
);
1646 /* ALCcontext_DeferUpdates
1648 * Defers/suspends updates for the given context's listener and sources. This
1649 * does *NOT* stop mixing, but rather prevents certain property changes from
1652 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1654 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1657 /* ALCcontext_ProcessUpdates
1659 * Resumes update processing after being deferred.
1661 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1663 almtx_lock(&context
->PropLock
);
1664 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1666 /* Tell the mixer to stop applying updates, then wait for any active
1667 * updating to finish, before providing updates.
1669 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1670 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1673 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1674 UpdateContextProps(context
);
1675 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1676 UpdateListenerProps(context
);
1677 UpdateAllEffectSlotProps(context
);
1678 UpdateAllSourceProps(context
);
1680 /* Now with all updates declared, let the mixer continue applying them
1681 * so they all happen at once.
1683 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1685 almtx_unlock(&context
->PropLock
);
1691 * Stores the latest ALC device error
1693 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1695 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1699 /* DebugBreak() will cause an exception if there is no debugger */
1700 if(IsDebuggerPresent())
1702 #elif defined(SIGTRAP)
1708 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1710 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1714 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1716 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1717 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1722 * Updates the device's base clock time with however many samples have been
1723 * done. This is used so frequency changes on the device don't cause the time
1724 * to jump forward or back. Must not be called while the device is running/
1727 static inline void UpdateClockBase(ALCdevice
*device
)
1729 IncrementRef(&device
->MixCount
);
1730 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1731 device
->SamplesDone
= 0;
1732 IncrementRef(&device
->MixCount
);
1735 /* UpdateDeviceParams
1737 * Updates device parameters according to the attribute list (caller is
1738 * responsible for holding the list lock).
1740 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1742 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1743 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1744 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1745 const ALsizei old_sends
= device
->NumAuxSends
;
1746 ALsizei new_sends
= device
->NumAuxSends
;
1747 enum DevFmtChannels oldChans
;
1748 enum DevFmtType oldType
;
1749 ALboolean update_failed
;
1750 ALCsizei hrtf_id
= -1;
1751 ALCcontext
*context
;
1757 // Check for attributes
1758 if(device
->Type
== Loopback
)
1760 ALCsizei numMono
, numStereo
, numSends
;
1761 ALCenum alayout
= AL_NONE
;
1762 ALCenum ascale
= AL_NONE
;
1763 ALCenum schans
= AL_NONE
;
1764 ALCenum stype
= AL_NONE
;
1765 ALCsizei attrIdx
= 0;
1766 ALCsizei aorder
= 0;
1771 WARN("Missing attributes for loopback device\n");
1772 return ALC_INVALID_VALUE
;
1775 numMono
= device
->NumMonoSources
;
1776 numStereo
= device
->NumStereoSources
;
1777 numSends
= old_sends
;
1779 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1780 while(attrList
[attrIdx
])
1782 switch(attrList
[attrIdx
])
1784 case ALC_FORMAT_CHANNELS_SOFT
:
1785 schans
= attrList
[attrIdx
+ 1];
1786 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1787 if(!IsValidALCChannels(schans
))
1788 return ALC_INVALID_VALUE
;
1791 case ALC_FORMAT_TYPE_SOFT
:
1792 stype
= attrList
[attrIdx
+ 1];
1793 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1794 if(!IsValidALCType(stype
))
1795 return ALC_INVALID_VALUE
;
1799 freq
= attrList
[attrIdx
+ 1];
1800 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1801 if(freq
< MIN_OUTPUT_RATE
)
1802 return ALC_INVALID_VALUE
;
1805 case ALC_AMBISONIC_LAYOUT_SOFT
:
1806 alayout
= attrList
[attrIdx
+ 1];
1807 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1808 if(!IsValidAmbiLayout(alayout
))
1809 return ALC_INVALID_VALUE
;
1812 case ALC_AMBISONIC_SCALING_SOFT
:
1813 ascale
= attrList
[attrIdx
+ 1];
1814 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1815 if(!IsValidAmbiScaling(ascale
))
1816 return ALC_INVALID_VALUE
;
1819 case ALC_AMBISONIC_ORDER_SOFT
:
1820 aorder
= attrList
[attrIdx
+ 1];
1821 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1822 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1823 return ALC_INVALID_VALUE
;
1826 case ALC_MONO_SOURCES
:
1827 numMono
= attrList
[attrIdx
+ 1];
1828 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1829 numMono
= maxi(numMono
, 0);
1832 case ALC_STEREO_SOURCES
:
1833 numStereo
= attrList
[attrIdx
+ 1];
1834 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1835 numStereo
= maxi(numStereo
, 0);
1838 case ALC_MAX_AUXILIARY_SENDS
:
1839 numSends
= attrList
[attrIdx
+ 1];
1840 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1841 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1845 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1846 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1847 hrtf_appreq
= Hrtf_Disable
;
1848 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1849 hrtf_appreq
= Hrtf_Enable
;
1851 hrtf_appreq
= Hrtf_Default
;
1854 case ALC_HRTF_ID_SOFT
:
1855 hrtf_id
= attrList
[attrIdx
+ 1];
1856 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1859 case ALC_OUTPUT_LIMITER_SOFT
:
1860 gainLimiter
= attrList
[attrIdx
+ 1];
1861 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1865 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1866 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1874 if(!schans
|| !stype
|| !freq
)
1876 WARN("Missing format for loopback device\n");
1877 return ALC_INVALID_VALUE
;
1879 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1881 WARN("Missing ambisonic info for loopback device\n");
1882 return ALC_INVALID_VALUE
;
1885 if((device
->Flags
&DEVICE_RUNNING
))
1886 V0(device
->Backend
,stop
)();
1887 device
->Flags
&= ~DEVICE_RUNNING
;
1889 UpdateClockBase(device
);
1891 device
->Frequency
= freq
;
1892 device
->FmtChans
= schans
;
1893 device
->FmtType
= stype
;
1894 if(schans
== ALC_BFORMAT3D_SOFT
)
1896 device
->AmbiOrder
= aorder
;
1897 device
->AmbiLayout
= alayout
;
1898 device
->AmbiScale
= ascale
;
1901 if(numMono
> INT_MAX
-numStereo
)
1902 numMono
= INT_MAX
-numStereo
;
1903 numMono
+= numStereo
;
1904 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1910 numMono
= maxi(numMono
, 256);
1911 numStereo
= mini(numStereo
, numMono
);
1912 numMono
-= numStereo
;
1913 device
->SourcesMax
= numMono
+ numStereo
;
1915 device
->NumMonoSources
= numMono
;
1916 device
->NumStereoSources
= numStereo
;
1918 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1919 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1921 new_sends
= numSends
;
1923 else if(attrList
&& attrList
[0])
1925 ALCsizei numMono
, numStereo
, numSends
;
1926 ALCsizei attrIdx
= 0;
1929 /* If a context is already running on the device, stop playback so the
1930 * device attributes can be updated. */
1931 if((device
->Flags
&DEVICE_RUNNING
))
1932 V0(device
->Backend
,stop
)();
1933 device
->Flags
&= ~DEVICE_RUNNING
;
1935 UpdateClockBase(device
);
1937 freq
= device
->Frequency
;
1938 numMono
= device
->NumMonoSources
;
1939 numStereo
= device
->NumStereoSources
;
1940 numSends
= old_sends
;
1942 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1943 while(attrList
[attrIdx
])
1945 switch(attrList
[attrIdx
])
1948 freq
= attrList
[attrIdx
+ 1];
1949 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1950 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1953 case ALC_MONO_SOURCES
:
1954 numMono
= attrList
[attrIdx
+ 1];
1955 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1956 numMono
= maxi(numMono
, 0);
1959 case ALC_STEREO_SOURCES
:
1960 numStereo
= attrList
[attrIdx
+ 1];
1961 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1962 numStereo
= maxi(numStereo
, 0);
1965 case ALC_MAX_AUXILIARY_SENDS
:
1966 numSends
= attrList
[attrIdx
+ 1];
1967 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1968 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1972 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1973 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1974 hrtf_appreq
= Hrtf_Disable
;
1975 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1976 hrtf_appreq
= Hrtf_Enable
;
1978 hrtf_appreq
= Hrtf_Default
;
1981 case ALC_HRTF_ID_SOFT
:
1982 hrtf_id
= attrList
[attrIdx
+ 1];
1983 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1986 case ALC_OUTPUT_LIMITER_SOFT
:
1987 gainLimiter
= attrList
[attrIdx
+ 1];
1988 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1992 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1993 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
2001 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2002 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2004 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2006 /* SSE and Neon do best with the update size being a multiple of 4 */
2007 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2008 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2010 device
->Frequency
= freq
;
2012 if(numMono
> INT_MAX
-numStereo
)
2013 numMono
= INT_MAX
-numStereo
;
2014 numMono
+= numStereo
;
2015 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2021 numMono
= maxi(numMono
, 256);
2022 numStereo
= mini(numStereo
, numMono
);
2023 numMono
-= numStereo
;
2024 device
->SourcesMax
= numMono
+ numStereo
;
2026 device
->NumMonoSources
= numMono
;
2027 device
->NumStereoSources
= numStereo
;
2029 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2030 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2032 new_sends
= numSends
;
2035 if((device
->Flags
&DEVICE_RUNNING
))
2036 return ALC_NO_ERROR
;
2038 al_free(device
->Uhj_Encoder
);
2039 device
->Uhj_Encoder
= NULL
;
2041 al_free(device
->Bs2b
);
2042 device
->Bs2b
= NULL
;
2044 al_free(device
->ChannelDelay
[0].Buffer
);
2045 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2047 device
->ChannelDelay
[i
].Length
= 0;
2048 device
->ChannelDelay
[i
].Buffer
= NULL
;
2051 al_free(device
->Dry
.Buffer
);
2052 device
->Dry
.Buffer
= NULL
;
2053 device
->Dry
.NumChannels
= 0;
2054 device
->FOAOut
.Buffer
= NULL
;
2055 device
->FOAOut
.NumChannels
= 0;
2056 device
->RealOut
.Buffer
= NULL
;
2057 device
->RealOut
.NumChannels
= 0;
2059 UpdateClockBase(device
);
2061 device
->DitherSeed
= DITHER_RNG_SEED
;
2063 /*************************************************************************
2064 * Update device format request if HRTF is requested
2066 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2067 if(device
->Type
!= Loopback
)
2070 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2072 if(strcasecmp(hrtf
, "true") == 0)
2073 hrtf_userreq
= Hrtf_Enable
;
2074 else if(strcasecmp(hrtf
, "false") == 0)
2075 hrtf_userreq
= Hrtf_Disable
;
2076 else if(strcasecmp(hrtf
, "auto") != 0)
2077 ERR("Unexpected hrtf value: %s\n", hrtf
);
2080 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2082 struct Hrtf
*hrtf
= NULL
;
2083 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2085 VECTOR_DEINIT(device
->HrtfList
);
2086 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2088 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2090 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2091 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2093 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2098 device
->FmtChans
= DevFmtStereo
;
2099 device
->Frequency
= hrtf
->sampleRate
;
2100 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2101 if(device
->HrtfHandle
)
2102 Hrtf_DecRef(device
->HrtfHandle
);
2103 device
->HrtfHandle
= hrtf
;
2107 hrtf_userreq
= Hrtf_Default
;
2108 hrtf_appreq
= Hrtf_Disable
;
2109 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2114 oldFreq
= device
->Frequency
;
2115 oldChans
= device
->FmtChans
;
2116 oldType
= device
->FmtType
;
2118 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2119 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2120 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2121 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2122 device
->UpdateSize
, device
->NumUpdates
2125 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2126 return ALC_INVALID_DEVICE
;
2128 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2130 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2131 DevFmtChannelsString(device
->FmtChans
));
2132 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2134 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2136 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2137 DevFmtTypeString(device
->FmtType
));
2138 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2140 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2142 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2143 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2146 if((device
->UpdateSize
&3) != 0)
2148 if((CPUCapFlags
&CPU_CAP_SSE
))
2149 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2150 if((CPUCapFlags
&CPU_CAP_NEON
))
2151 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2154 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2155 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2156 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2159 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2160 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2161 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2163 /* Allocate extra channels for any post-filter output. */
2164 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2165 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2167 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2168 device
->Dry
.Buffer
= al_calloc(16, size
);
2169 if(!device
->Dry
.Buffer
)
2171 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2172 return ALC_INVALID_DEVICE
;
2175 if(device
->RealOut
.NumChannels
!= 0)
2176 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2177 device
->FOAOut
.NumChannels
;
2180 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2181 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2184 if(device
->FOAOut
.NumChannels
!= 0)
2185 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2188 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2189 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2192 device
->NumAuxSends
= new_sends
;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2195 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2197 device
->DitherDepth
= 0.0f
;
2198 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2201 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2204 switch(device
->FmtType
)
2223 depth
= clampi(depth
, 2, 20);
2224 device
->DitherDepth
= powf(2.0f
, (ALfloat
)(depth
-1));
2227 if(!(device
->DitherDepth
> 0.0f
))
2228 TRACE("Dithering disabled\n");
2230 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2231 device
->DitherDepth
);
2233 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2234 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2235 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2236 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2239 if(gainLimiter
!= ALC_FALSE
)
2241 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2243 al_free(device
->Limiter
);
2244 device
->Limiter
= CreateDeviceLimiter(device
);
2249 al_free(device
->Limiter
);
2250 device
->Limiter
= NULL
;
2252 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2254 aluSelectPostProcess(device
);
2256 /* Need to delay returning failure until replacement Send arrays have been
2257 * allocated with the appropriate size.
2259 update_failed
= AL_FALSE
;
2261 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2264 SourceSubList
*sublist
, *subend
;
2265 struct ALvoiceProps
*vprops
;
2268 if(context
->DefaultSlot
)
2270 ALeffectslot
*slot
= context
->DefaultSlot
;
2271 ALeffectState
*state
= slot
->Effect
.State
;
2273 state
->OutBuffer
= device
->Dry
.Buffer
;
2274 state
->OutChannels
= device
->Dry
.NumChannels
;
2275 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2276 update_failed
= AL_TRUE
;
2278 UpdateEffectSlotProps(slot
, context
);
2281 almtx_lock(&context
->PropLock
);
2282 almtx_lock(&context
->EffectSlotLock
);
2283 for(pos
= 0;pos
< (ALsizei
)VECTOR_SIZE(context
->EffectSlotList
);pos
++)
2285 ALeffectslot
*slot
= VECTOR_ELEM(context
->EffectSlotList
, pos
);
2286 ALeffectState
*state
= slot
->Effect
.State
;
2288 state
->OutBuffer
= device
->Dry
.Buffer
;
2289 state
->OutChannels
= device
->Dry
.NumChannels
;
2290 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2291 update_failed
= AL_TRUE
;
2293 UpdateEffectSlotProps(slot
, context
);
2295 almtx_unlock(&context
->EffectSlotLock
);
2297 almtx_lock(&context
->SourceLock
);
2298 sublist
= VECTOR_BEGIN(context
->SourceList
);
2299 subend
= VECTOR_END(context
->SourceList
);
2300 for(;sublist
!= subend
;++sublist
)
2302 ALuint64 usemask
= ~sublist
->FreeMask
;
2305 ALsizei idx
= CTZ64(usemask
);
2306 ALsource
*source
= sublist
->Sources
+ idx
;
2308 usemask
&= ~(U64(1) << idx
);
2310 if(old_sends
!= device
->NumAuxSends
)
2312 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2315 memcpy(sends
, source
->Send
,
2316 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2318 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2320 if(source
->Send
[s
].Slot
)
2321 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2322 source
->Send
[s
].Slot
= NULL
;
2324 al_free(source
->Send
);
2325 source
->Send
= sends
;
2326 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2328 source
->Send
[s
].Slot
= NULL
;
2329 source
->Send
[s
].Gain
= 1.0f
;
2330 source
->Send
[s
].GainHF
= 1.0f
;
2331 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2332 source
->Send
[s
].GainLF
= 1.0f
;
2333 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2337 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2341 /* Clear any pre-existing voice property structs, in case the number of
2342 * auxiliary sends is changing. Active sources will have updates
2343 * respecified in UpdateAllSourceProps.
2345 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2348 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2353 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2354 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2356 ALvoice
*voice
= context
->Voices
[pos
];
2358 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2360 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2363 if(device
->AvgSpeakerDist
> 0.0f
)
2365 /* Reinitialize the NFC filters for new parameters. */
2366 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2367 (device
->AvgSpeakerDist
* device
->Frequency
);
2368 for(i
= 0;i
< voice
->NumChannels
;i
++)
2369 NfcFilterCreate(&voice
->Direct
.Params
[i
].NFCtrlFilter
, 0.0f
, w1
);
2372 almtx_unlock(&context
->SourceLock
);
2374 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2375 UpdateContextProps(context
);
2376 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2377 UpdateListenerProps(context
);
2378 UpdateAllSourceProps(context
);
2379 almtx_unlock(&context
->PropLock
);
2381 context
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2385 return ALC_INVALID_DEVICE
;
2387 if(!(device
->Flags
&DEVICE_PAUSED
))
2389 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2390 return ALC_INVALID_DEVICE
;
2391 device
->Flags
|= DEVICE_RUNNING
;
2394 return ALC_NO_ERROR
;
2398 static void InitDevice(ALCdevice
*device
, enum DeviceType type
)
2402 InitRef(&device
->ref
, 1);
2403 ATOMIC_INIT(&device
->Connected
, ALC_TRUE
);
2404 device
->Type
= type
;
2405 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
2408 device
->Render_Mode
= NormalRender
;
2409 device
->AvgSpeakerDist
= 0.0f
;
2411 ATOMIC_INIT(&device
->ContextList
, NULL
);
2413 device
->ClockBase
= 0;
2414 device
->SamplesDone
= 0;
2416 device
->SourcesMax
= 0;
2417 device
->AuxiliaryEffectSlotMax
= 0;
2418 device
->NumAuxSends
= 0;
2420 device
->Dry
.Buffer
= NULL
;
2421 device
->Dry
.NumChannels
= 0;
2422 device
->FOAOut
.Buffer
= NULL
;
2423 device
->FOAOut
.NumChannels
= 0;
2424 device
->RealOut
.Buffer
= NULL
;
2425 device
->RealOut
.NumChannels
= 0;
2427 AL_STRING_INIT(device
->DeviceName
);
2429 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2431 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2432 device
->ChannelDelay
[i
].Length
= 0;
2433 device
->ChannelDelay
[i
].Buffer
= NULL
;
2436 AL_STRING_INIT(device
->HrtfName
);
2437 VECTOR_INIT(device
->HrtfList
);
2438 device
->HrtfHandle
= NULL
;
2439 device
->Hrtf
= NULL
;
2440 device
->Bs2b
= NULL
;
2441 device
->Uhj_Encoder
= NULL
;
2442 device
->AmbiDecoder
= NULL
;
2443 device
->AmbiUp
= NULL
;
2444 device
->Stablizer
= NULL
;
2445 device
->Limiter
= NULL
;
2447 VECTOR_INIT(device
->BufferList
);
2448 almtx_init(&device
->BufferLock
, almtx_plain
);
2450 VECTOR_INIT(device
->EffectList
);
2451 almtx_init(&device
->EffectLock
, almtx_plain
);
2453 VECTOR_INIT(device
->FilterList
);
2454 almtx_init(&device
->FilterLock
, almtx_plain
);
2456 almtx_init(&device
->BackendLock
, almtx_plain
);
2457 device
->Backend
= NULL
;
2459 ATOMIC_INIT(&device
->next
, NULL
);
2464 * Frees the device structure, and destroys any objects the app failed to
2465 * delete. Called once there's no more references on the device.
2467 static ALCvoid
FreeDevice(ALCdevice
*device
)
2471 TRACE("%p\n", device
);
2474 DELETE_OBJ(device
->Backend
);
2475 device
->Backend
= NULL
;
2477 almtx_destroy(&device
->BackendLock
);
2479 ReleaseALBuffers(device
);
2480 #define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
2481 VECTOR_FOR_EACH(BufferSubList
, device
->BufferList
, FREE_BUFFERSUBLIST
);
2482 #undef FREE_BUFFERSUBLIST
2483 VECTOR_DEINIT(device
->BufferList
);
2484 almtx_destroy(&device
->BufferLock
);
2486 ReleaseALEffects(device
);
2487 #define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
2488 VECTOR_FOR_EACH(EffectSubList
, device
->EffectList
, FREE_EFFECTSUBLIST
);
2489 #undef FREE_EFFECTSUBLIST
2490 VECTOR_DEINIT(device
->EffectList
);
2491 almtx_destroy(&device
->EffectLock
);
2493 ReleaseALFilters(device
);
2494 #define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
2495 VECTOR_FOR_EACH(FilterSubList
, device
->FilterList
, FREE_FILTERSUBLIST
);
2496 #undef FREE_FILTERSUBLIST
2497 VECTOR_DEINIT(device
->FilterList
);
2498 almtx_destroy(&device
->FilterLock
);
2500 AL_STRING_DEINIT(device
->HrtfName
);
2501 FreeHrtfList(&device
->HrtfList
);
2502 if(device
->HrtfHandle
)
2503 Hrtf_DecRef(device
->HrtfHandle
);
2504 device
->HrtfHandle
= NULL
;
2505 al_free(device
->Hrtf
);
2506 device
->Hrtf
= NULL
;
2508 al_free(device
->Bs2b
);
2509 device
->Bs2b
= NULL
;
2511 al_free(device
->Uhj_Encoder
);
2512 device
->Uhj_Encoder
= NULL
;
2514 bformatdec_free(&device
->AmbiDecoder
);
2515 ambiup_free(&device
->AmbiUp
);
2517 al_free(device
->Stablizer
);
2518 device
->Stablizer
= NULL
;
2520 al_free(device
->Limiter
);
2521 device
->Limiter
= NULL
;
2523 al_free(device
->ChannelDelay
[0].Buffer
);
2524 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2526 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2527 device
->ChannelDelay
[i
].Length
= 0;
2528 device
->ChannelDelay
[i
].Buffer
= NULL
;
2531 AL_STRING_DEINIT(device
->DeviceName
);
2533 al_free(device
->Dry
.Buffer
);
2534 device
->Dry
.Buffer
= NULL
;
2535 device
->Dry
.NumChannels
= 0;
2536 device
->FOAOut
.Buffer
= NULL
;
2537 device
->FOAOut
.NumChannels
= 0;
2538 device
->RealOut
.Buffer
= NULL
;
2539 device
->RealOut
.NumChannels
= 0;
2545 void ALCdevice_IncRef(ALCdevice
*device
)
2548 ref
= IncrementRef(&device
->ref
);
2549 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2552 void ALCdevice_DecRef(ALCdevice
*device
)
2555 ref
= DecrementRef(&device
->ref
);
2556 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2557 if(ref
== 0) FreeDevice(device
);
2562 * Checks if the device handle is valid, and increments its ref count if so.
2564 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2566 ALCdevice
*tmpDevice
;
2569 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2572 if(tmpDevice
== *device
)
2574 ALCdevice_IncRef(tmpDevice
);
2578 tmpDevice
= ATOMIC_LOAD(&tmpDevice
->next
, almemory_order_relaxed
);
2589 * Initializes context fields
2591 static ALvoid
InitContext(ALCcontext
*Context
)
2593 ALlistener
*listener
= Context
->Listener
;
2594 struct ALeffectslotArray
*auxslots
;
2596 //Initialise listener
2597 listener
->Gain
= 1.0f
;
2598 listener
->Position
[0] = 0.0f
;
2599 listener
->Position
[1] = 0.0f
;
2600 listener
->Position
[2] = 0.0f
;
2601 listener
->Velocity
[0] = 0.0f
;
2602 listener
->Velocity
[1] = 0.0f
;
2603 listener
->Velocity
[2] = 0.0f
;
2604 listener
->Forward
[0] = 0.0f
;
2605 listener
->Forward
[1] = 0.0f
;
2606 listener
->Forward
[2] = -1.0f
;
2607 listener
->Up
[0] = 0.0f
;
2608 listener
->Up
[1] = 1.0f
;
2609 listener
->Up
[2] = 0.0f
;
2610 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2612 ATOMIC_INIT(&listener
->Update
, NULL
);
2615 InitRef(&Context
->UpdateCount
, 0);
2616 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2617 Context
->GainBoost
= 1.0f
;
2618 almtx_init(&Context
->PropLock
, almtx_plain
);
2619 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2620 VECTOR_INIT(Context
->SourceList
);
2621 Context
->NumSources
= 0;
2622 almtx_init(&Context
->SourceLock
, almtx_plain
);
2623 VECTOR_INIT(Context
->EffectSlotList
);
2624 almtx_init(&Context
->EffectSlotLock
, almtx_plain
);
2626 if(Context
->DefaultSlot
)
2628 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2629 auxslots
->count
= 1;
2630 auxslots
->slot
[0] = Context
->DefaultSlot
;
2634 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2635 auxslots
->count
= 0;
2637 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2640 Context
->DistanceModel
= DefaultDistanceModel
;
2641 Context
->SourceDistanceModel
= AL_FALSE
;
2642 Context
->DopplerFactor
= 1.0f
;
2643 Context
->DopplerVelocity
= 1.0f
;
2644 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2645 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2646 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2647 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2648 almtx_init(&Context
->EventThrdLock
, almtx_plain
);
2649 alsem_init(&Context
->EventSem
, 0);
2650 Context
->AsyncEvents
= NULL
;
2651 ATOMIC_INIT(&Context
->EnabledEvts
, 0);
2652 almtx_init(&Context
->EventCbLock
, almtx_plain
);
2653 Context
->EventCb
= NULL
;
2654 Context
->EventParam
= NULL
;
2656 ATOMIC_INIT(&Context
->Update
, NULL
);
2657 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2658 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2659 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2660 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2662 Context
->ExtensionList
= alExtList
;
2665 listener
->Params
.Matrix
= IdentityMatrixf
;
2666 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2667 listener
->Params
.Gain
= listener
->Gain
;
2668 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2669 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2670 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2671 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2672 listener
->Params
.MetersPerUnit
;
2673 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2674 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2680 * Cleans up the context, and destroys any remaining objects the app failed to
2681 * delete. Called once there's no more references on the context.
2683 static void FreeContext(ALCcontext
*context
)
2685 ALlistener
*listener
= context
->Listener
;
2686 struct ALeffectslotArray
*auxslots
;
2687 struct ALeffectslotProps
*eprops
;
2688 struct ALlistenerProps
*lprops
;
2689 struct ALcontextProps
*cprops
;
2690 struct ALvoiceProps
*vprops
;
2694 TRACE("%p\n", context
);
2696 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2698 TRACE("Freed unapplied context update %p\n", cprops
);
2703 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2706 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2711 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2713 if(context
->DefaultSlot
)
2715 DeinitEffectSlot(context
->DefaultSlot
);
2716 context
->DefaultSlot
= NULL
;
2719 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2722 ReleaseALSources(context
);
2723 #define FREE_SOURCESUBLIST(x) al_free((x)->Sources)
2724 VECTOR_FOR_EACH(SourceSubList
, context
->SourceList
, FREE_SOURCESUBLIST
);
2725 #undef FREE_SOURCESUBLIST
2726 VECTOR_DEINIT(context
->SourceList
);
2727 context
->NumSources
= 0;
2728 almtx_destroy(&context
->SourceLock
);
2731 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2734 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2735 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2740 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2742 ReleaseALAuxiliaryEffectSlots(context
);
2743 #define FREE_EFFECTSLOTPTR(x) al_free(*(x))
2744 VECTOR_FOR_EACH(ALeffectslotPtr
, context
->EffectSlotList
, FREE_EFFECTSLOTPTR
);
2745 #undef FREE_EFFECTSLOTPTR
2746 VECTOR_DEINIT(context
->EffectSlotList
);
2747 almtx_destroy(&context
->EffectSlotLock
);
2750 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2753 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2758 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2760 for(i
= 0;i
< context
->VoiceCount
;i
++)
2761 DeinitVoice(context
->Voices
[i
]);
2762 al_free(context
->Voices
);
2763 context
->Voices
= NULL
;
2764 context
->VoiceCount
= 0;
2765 context
->MaxVoices
= 0;
2767 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2769 TRACE("Freed unapplied listener update %p\n", lprops
);
2773 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2776 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2781 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2783 if(ATOMIC_EXCHANGE(&context
->EnabledEvts
, 0, almemory_order_acq_rel
))
2785 static const AsyncEvent kill_evt
= { 0 };
2786 while(ll_ringbuffer_write(context
->AsyncEvents
, (const char*)&kill_evt
, 1) == 0)
2788 alsem_post(&context
->EventSem
);
2789 althrd_join(context
->EventThread
, NULL
);
2792 almtx_destroy(&context
->EventCbLock
);
2793 almtx_destroy(&context
->EventThrdLock
);
2794 alsem_destroy(&context
->EventSem
);
2796 ll_ringbuffer_free(context
->AsyncEvents
);
2797 context
->AsyncEvents
= NULL
;
2799 almtx_destroy(&context
->PropLock
);
2801 ALCdevice_DecRef(context
->Device
);
2802 context
->Device
= NULL
;
2804 //Invalidate context
2805 memset(context
, 0, sizeof(ALCcontext
));
2811 * Removes the context reference from the given device and removes it from
2812 * being current on the running thread or globally. Returns true if other
2813 * contexts still exist on the device.
2815 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2817 ALCcontext
*origctx
, *newhead
;
2820 if(altss_get(LocalContext
) == context
)
2822 WARN("%p released while current on thread\n", context
);
2823 altss_set(LocalContext
, NULL
);
2824 ALCcontext_DecRef(context
);
2828 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2829 ALCcontext_DecRef(context
);
2831 V0(device
->Backend
,lock
)();
2833 newhead
= ATOMIC_LOAD(&context
->next
, almemory_order_relaxed
);
2834 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2838 /* origctx is what the desired context failed to match. Try
2839 * swapping out the next one in the list.
2843 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origctx
, newhead
));
2847 V0(device
->Backend
,unlock
)();
2849 ALCcontext_DecRef(context
);
2853 static void ALCcontext_IncRef(ALCcontext
*context
)
2855 uint ref
= IncrementRef(&context
->ref
);
2856 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2859 void ALCcontext_DecRef(ALCcontext
*context
)
2861 uint ref
= DecrementRef(&context
->ref
);
2862 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2863 if(ref
== 0) FreeContext(context
);
2866 static void ReleaseThreadCtx(void *ptr
)
2868 ALCcontext
*context
= ptr
;
2869 uint ref
= DecrementRef(&context
->ref
);
2870 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2871 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2876 * Checks that the given context is valid, and increments its reference count.
2878 static ALCboolean
VerifyContext(ALCcontext
**context
)
2883 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2886 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2891 ALCcontext_IncRef(ctx
);
2895 ctx
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
2897 dev
= ATOMIC_LOAD(&dev
->next
, almemory_order_relaxed
);
2908 * Returns the currently active context for this thread, and adds a reference
2909 * without locking it.
2911 ALCcontext
*GetContextRef(void)
2913 ALCcontext
*context
;
2915 context
= altss_get(LocalContext
);
2917 ALCcontext_IncRef(context
);
2921 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2923 ALCcontext_IncRef(context
);
2931 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2933 ALCdevice
*device
= context
->Device
;
2934 ALsizei num_sends
= device
->NumAuxSends
;
2935 struct ALvoiceProps
*props
;
2936 size_t sizeof_props
;
2937 size_t sizeof_voice
;
2943 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2946 /* Allocate the voice pointers, voices, and the voices' stored source
2947 * property set (including the dynamically-sized Send[] array) in one
2950 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2951 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2952 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2954 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2955 /* The voice and property objects are stored interleaved since they're
2958 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2959 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2963 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2964 const ALsizei s_count
= mini(old_sends
, num_sends
);
2966 for(;v
< v_count
;v
++)
2968 ALvoice
*old_voice
= context
->Voices
[v
];
2971 /* Copy the old voice data and source property set to the new
2974 *voice
= *old_voice
;
2975 for(i
= 0;i
< s_count
;i
++)
2976 voice
->Send
[i
] = old_voice
->Send
[i
];
2977 *props
= *(old_voice
->Props
);
2978 for(i
= 0;i
< s_count
;i
++)
2979 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2981 /* Set this voice's property set pointer and voice reference. */
2982 voice
->Props
= props
;
2985 /* Increment pointers to the next storage space. */
2986 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2987 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2989 /* Deinit any left over voices that weren't copied over to the new
2990 * array. NOTE: If this does anything, v equals num_voices and
2991 * num_voices is less than VoiceCount, so the following loop won't do
2994 for(;v
< context
->VoiceCount
;v
++)
2995 DeinitVoice(context
->Voices
[v
]);
2997 /* Finish setting the voices' property set pointers and references. */
2998 for(;v
< num_voices
;v
++)
3000 ATOMIC_INIT(&voice
->Update
, NULL
);
3002 voice
->Props
= props
;
3005 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
3006 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
3009 al_free(context
->Voices
);
3010 context
->Voices
= voices
;
3011 context
->MaxVoices
= num_voices
;
3012 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
3016 /************************************************
3017 * Standard ALC functions
3018 ************************************************/
3022 * Return last ALC generated error code for the given device
3024 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
3028 if(VerifyDevice(&device
))
3030 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3031 ALCdevice_DecRef(device
);
3034 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
3040 /* alcSuspendContext
3042 * Suspends updates for the given context
3044 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
3049 if(!VerifyContext(&context
))
3050 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3053 ALCcontext_DeferUpdates(context
);
3054 ALCcontext_DecRef(context
);
3058 /* alcProcessContext
3060 * Resumes processing updates for the given context
3062 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
3067 if(!VerifyContext(&context
))
3068 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3071 ALCcontext_ProcessUpdates(context
);
3072 ALCcontext_DecRef(context
);
3079 * Returns information about the device, and error strings
3081 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
3083 const ALCchar
*value
= NULL
;
3091 case ALC_INVALID_ENUM
:
3092 value
= alcErrInvalidEnum
;
3095 case ALC_INVALID_VALUE
:
3096 value
= alcErrInvalidValue
;
3099 case ALC_INVALID_DEVICE
:
3100 value
= alcErrInvalidDevice
;
3103 case ALC_INVALID_CONTEXT
:
3104 value
= alcErrInvalidContext
;
3107 case ALC_OUT_OF_MEMORY
:
3108 value
= alcErrOutOfMemory
;
3111 case ALC_DEVICE_SPECIFIER
:
3112 value
= alcDefaultName
;
3115 case ALC_ALL_DEVICES_SPECIFIER
:
3116 if(VerifyDevice(&Device
))
3118 value
= alstr_get_cstr(Device
->DeviceName
);
3119 ALCdevice_DecRef(Device
);
3123 ProbeAllDevicesList();
3124 value
= alstr_get_cstr(alcAllDevicesList
);
3128 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3129 if(VerifyDevice(&Device
))
3131 value
= alstr_get_cstr(Device
->DeviceName
);
3132 ALCdevice_DecRef(Device
);
3136 ProbeCaptureDeviceList();
3137 value
= alstr_get_cstr(alcCaptureDeviceList
);
3141 /* Default devices are always first in the list */
3142 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3143 value
= alcDefaultName
;
3146 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3147 if(alstr_empty(alcAllDevicesList
))
3148 ProbeAllDevicesList();
3150 VerifyDevice(&Device
);
3152 free(alcDefaultAllDevicesSpecifier
);
3153 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3154 if(!alcDefaultAllDevicesSpecifier
)
3155 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3157 value
= alcDefaultAllDevicesSpecifier
;
3158 if(Device
) ALCdevice_DecRef(Device
);
3161 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3162 if(alstr_empty(alcCaptureDeviceList
))
3163 ProbeCaptureDeviceList();
3165 VerifyDevice(&Device
);
3167 free(alcCaptureDefaultDeviceSpecifier
);
3168 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3169 if(!alcCaptureDefaultDeviceSpecifier
)
3170 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3172 value
= alcCaptureDefaultDeviceSpecifier
;
3173 if(Device
) ALCdevice_DecRef(Device
);
3176 case ALC_EXTENSIONS
:
3177 if(!VerifyDevice(&Device
))
3178 value
= alcNoDeviceExtList
;
3181 value
= alcExtensionList
;
3182 ALCdevice_DecRef(Device
);
3186 case ALC_HRTF_SPECIFIER_SOFT
:
3187 if(!VerifyDevice(&Device
))
3188 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3191 almtx_lock(&Device
->BackendLock
);
3192 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3193 almtx_unlock(&Device
->BackendLock
);
3194 ALCdevice_DecRef(Device
);
3199 VerifyDevice(&Device
);
3200 alcSetError(Device
, ALC_INVALID_ENUM
);
3201 if(Device
) ALCdevice_DecRef(Device
);
3209 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3211 if(device
->Type
== Capture
) return 9;
3212 if(device
->Type
!= Loopback
) return 29;
3213 if(device
->FmtChans
== DevFmtAmbi3D
)
3218 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3222 if(size
<= 0 || values
== NULL
)
3224 alcSetError(device
, ALC_INVALID_VALUE
);
3232 case ALC_MAJOR_VERSION
:
3233 values
[0] = alcMajorVersion
;
3235 case ALC_MINOR_VERSION
:
3236 values
[0] = alcMinorVersion
;
3239 case ALC_ATTRIBUTES_SIZE
:
3240 case ALC_ALL_ATTRIBUTES
:
3244 case ALC_MONO_SOURCES
:
3245 case ALC_STEREO_SOURCES
:
3246 case ALC_CAPTURE_SAMPLES
:
3247 case ALC_FORMAT_CHANNELS_SOFT
:
3248 case ALC_FORMAT_TYPE_SOFT
:
3249 case ALC_AMBISONIC_LAYOUT_SOFT
:
3250 case ALC_AMBISONIC_SCALING_SOFT
:
3251 case ALC_AMBISONIC_ORDER_SOFT
:
3252 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3253 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3257 alcSetError(NULL
, ALC_INVALID_ENUM
);
3263 if(device
->Type
== Capture
)
3267 case ALC_ATTRIBUTES_SIZE
:
3268 values
[0] = NumAttrsForDevice(device
);
3271 case ALC_ALL_ATTRIBUTES
:
3272 if(size
< NumAttrsForDevice(device
))
3274 alcSetError(device
, ALC_INVALID_VALUE
);
3279 almtx_lock(&device
->BackendLock
);
3280 values
[i
++] = ALC_MAJOR_VERSION
;
3281 values
[i
++] = alcMajorVersion
;
3282 values
[i
++] = ALC_MINOR_VERSION
;
3283 values
[i
++] = alcMinorVersion
;
3284 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3285 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3286 values
[i
++] = ALC_CONNECTED
;
3287 values
[i
++] = ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
);
3288 almtx_unlock(&device
->BackendLock
);
3293 case ALC_MAJOR_VERSION
:
3294 values
[0] = alcMajorVersion
;
3296 case ALC_MINOR_VERSION
:
3297 values
[0] = alcMinorVersion
;
3300 case ALC_CAPTURE_SAMPLES
:
3301 almtx_lock(&device
->BackendLock
);
3302 values
[0] = V0(device
->Backend
,availableSamples
)();
3303 almtx_unlock(&device
->BackendLock
);
3307 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3311 alcSetError(device
, ALC_INVALID_ENUM
);
3320 case ALC_ATTRIBUTES_SIZE
:
3321 values
[0] = NumAttrsForDevice(device
);
3324 case ALC_ALL_ATTRIBUTES
:
3325 if(size
< NumAttrsForDevice(device
))
3327 alcSetError(device
, ALC_INVALID_VALUE
);
3332 almtx_lock(&device
->BackendLock
);
3333 values
[i
++] = ALC_MAJOR_VERSION
;
3334 values
[i
++] = alcMajorVersion
;
3335 values
[i
++] = ALC_MINOR_VERSION
;
3336 values
[i
++] = alcMinorVersion
;
3337 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3338 values
[i
++] = alcEFXMajorVersion
;
3339 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3340 values
[i
++] = alcEFXMinorVersion
;
3342 values
[i
++] = ALC_FREQUENCY
;
3343 values
[i
++] = device
->Frequency
;
3344 if(device
->Type
!= Loopback
)
3346 values
[i
++] = ALC_REFRESH
;
3347 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3349 values
[i
++] = ALC_SYNC
;
3350 values
[i
++] = ALC_FALSE
;
3354 if(device
->FmtChans
== DevFmtAmbi3D
)
3356 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3357 values
[i
++] = device
->AmbiLayout
;
3359 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3360 values
[i
++] = device
->AmbiScale
;
3362 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3363 values
[i
++] = device
->AmbiOrder
;
3366 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3367 values
[i
++] = device
->FmtChans
;
3369 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3370 values
[i
++] = device
->FmtType
;
3373 values
[i
++] = ALC_MONO_SOURCES
;
3374 values
[i
++] = device
->NumMonoSources
;
3376 values
[i
++] = ALC_STEREO_SOURCES
;
3377 values
[i
++] = device
->NumStereoSources
;
3379 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3380 values
[i
++] = device
->NumAuxSends
;
3382 values
[i
++] = ALC_HRTF_SOFT
;
3383 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3385 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3386 values
[i
++] = device
->HrtfStatus
;
3388 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3389 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3391 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3392 values
[i
++] = MAX_AMBI_ORDER
;
3393 almtx_unlock(&device
->BackendLock
);
3398 case ALC_MAJOR_VERSION
:
3399 values
[0] = alcMajorVersion
;
3402 case ALC_MINOR_VERSION
:
3403 values
[0] = alcMinorVersion
;
3406 case ALC_EFX_MAJOR_VERSION
:
3407 values
[0] = alcEFXMajorVersion
;
3410 case ALC_EFX_MINOR_VERSION
:
3411 values
[0] = alcEFXMinorVersion
;
3415 values
[0] = device
->Frequency
;
3419 if(device
->Type
== Loopback
)
3421 alcSetError(device
, ALC_INVALID_DEVICE
);
3424 almtx_lock(&device
->BackendLock
);
3425 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3426 almtx_unlock(&device
->BackendLock
);
3430 if(device
->Type
== Loopback
)
3432 alcSetError(device
, ALC_INVALID_DEVICE
);
3435 values
[0] = ALC_FALSE
;
3438 case ALC_FORMAT_CHANNELS_SOFT
:
3439 if(device
->Type
!= Loopback
)
3441 alcSetError(device
, ALC_INVALID_DEVICE
);
3444 values
[0] = device
->FmtChans
;
3447 case ALC_FORMAT_TYPE_SOFT
:
3448 if(device
->Type
!= Loopback
)
3450 alcSetError(device
, ALC_INVALID_DEVICE
);
3453 values
[0] = device
->FmtType
;
3456 case ALC_AMBISONIC_LAYOUT_SOFT
:
3457 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3459 alcSetError(device
, ALC_INVALID_DEVICE
);
3462 values
[0] = device
->AmbiLayout
;
3465 case ALC_AMBISONIC_SCALING_SOFT
:
3466 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3468 alcSetError(device
, ALC_INVALID_DEVICE
);
3471 values
[0] = device
->AmbiScale
;
3474 case ALC_AMBISONIC_ORDER_SOFT
:
3475 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3477 alcSetError(device
, ALC_INVALID_DEVICE
);
3480 values
[0] = device
->AmbiOrder
;
3483 case ALC_MONO_SOURCES
:
3484 values
[0] = device
->NumMonoSources
;
3487 case ALC_STEREO_SOURCES
:
3488 values
[0] = device
->NumStereoSources
;
3491 case ALC_MAX_AUXILIARY_SENDS
:
3492 values
[0] = device
->NumAuxSends
;
3496 values
[0] = ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
);
3500 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3503 case ALC_HRTF_STATUS_SOFT
:
3504 values
[0] = device
->HrtfStatus
;
3507 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3508 almtx_lock(&device
->BackendLock
);
3509 FreeHrtfList(&device
->HrtfList
);
3510 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3511 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3512 almtx_unlock(&device
->BackendLock
);
3515 case ALC_OUTPUT_LIMITER_SOFT
:
3516 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3519 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3520 values
[0] = MAX_AMBI_ORDER
;
3524 alcSetError(device
, ALC_INVALID_ENUM
);
3532 * Returns information about the device and the version of OpenAL
3534 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3536 VerifyDevice(&device
);
3537 if(size
<= 0 || values
== NULL
)
3538 alcSetError(device
, ALC_INVALID_VALUE
);
3540 GetIntegerv(device
, param
, size
, values
);
3541 if(device
) ALCdevice_DecRef(device
);
3544 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3549 VerifyDevice(&device
);
3550 if(size
<= 0 || values
== NULL
)
3551 alcSetError(device
, ALC_INVALID_VALUE
);
3552 else if(!device
|| device
->Type
== Capture
)
3554 ivals
= malloc(size
* sizeof(ALCint
));
3555 size
= GetIntegerv(device
, pname
, size
, ivals
);
3556 for(i
= 0;i
< size
;i
++)
3557 values
[i
] = ivals
[i
];
3560 else /* render device */
3569 case ALC_ATTRIBUTES_SIZE
:
3570 *values
= NumAttrsForDevice(device
)+4;
3573 case ALC_ALL_ATTRIBUTES
:
3574 if(size
< NumAttrsForDevice(device
)+4)
3575 alcSetError(device
, ALC_INVALID_VALUE
);
3579 almtx_lock(&device
->BackendLock
);
3580 values
[i
++] = ALC_FREQUENCY
;
3581 values
[i
++] = device
->Frequency
;
3583 if(device
->Type
!= Loopback
)
3585 values
[i
++] = ALC_REFRESH
;
3586 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3588 values
[i
++] = ALC_SYNC
;
3589 values
[i
++] = ALC_FALSE
;
3593 if(device
->FmtChans
== DevFmtAmbi3D
)
3595 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3596 values
[i
++] = device
->AmbiLayout
;
3598 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3599 values
[i
++] = device
->AmbiScale
;
3601 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3602 values
[i
++] = device
->AmbiOrder
;
3605 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3606 values
[i
++] = device
->FmtChans
;
3608 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3609 values
[i
++] = device
->FmtType
;
3612 values
[i
++] = ALC_MONO_SOURCES
;
3613 values
[i
++] = device
->NumMonoSources
;
3615 values
[i
++] = ALC_STEREO_SOURCES
;
3616 values
[i
++] = device
->NumStereoSources
;
3618 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3619 values
[i
++] = device
->NumAuxSends
;
3621 values
[i
++] = ALC_HRTF_SOFT
;
3622 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3624 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3625 values
[i
++] = device
->HrtfStatus
;
3627 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3628 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3630 clock
= V0(device
->Backend
,getClockLatency
)();
3631 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3632 values
[i
++] = clock
.ClockTime
;
3634 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3635 values
[i
++] = clock
.Latency
;
3636 almtx_unlock(&device
->BackendLock
);
3642 case ALC_DEVICE_CLOCK_SOFT
:
3643 almtx_lock(&device
->BackendLock
);
3645 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3647 basecount
= device
->ClockBase
;
3648 samplecount
= device
->SamplesDone
;
3649 } while(refcount
!= ReadRef(&device
->MixCount
));
3650 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3651 almtx_unlock(&device
->BackendLock
);
3654 case ALC_DEVICE_LATENCY_SOFT
:
3655 almtx_lock(&device
->BackendLock
);
3656 clock
= V0(device
->Backend
,getClockLatency
)();
3657 almtx_unlock(&device
->BackendLock
);
3658 *values
= clock
.Latency
;
3661 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3663 alcSetError(device
, ALC_INVALID_VALUE
);
3666 almtx_lock(&device
->BackendLock
);
3667 clock
= V0(device
->Backend
,getClockLatency
)();
3668 almtx_unlock(&device
->BackendLock
);
3669 values
[0] = clock
.ClockTime
;
3670 values
[1] = clock
.Latency
;
3675 ivals
= malloc(size
* sizeof(ALCint
));
3676 size
= GetIntegerv(device
, pname
, size
, ivals
);
3677 for(i
= 0;i
< size
;i
++)
3678 values
[i
] = ivals
[i
];
3684 ALCdevice_DecRef(device
);
3688 /* alcIsExtensionPresent
3690 * Determines if there is support for a particular extension
3692 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3694 ALCboolean bResult
= ALC_FALSE
;
3696 VerifyDevice(&device
);
3699 alcSetError(device
, ALC_INVALID_VALUE
);
3702 size_t len
= strlen(extName
);
3703 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3706 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3707 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3712 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3716 } while(isspace(*ptr
));
3721 ALCdevice_DecRef(device
);
3726 /* alcGetProcAddress
3728 * Retrieves the function address for a particular extension function
3730 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3732 ALCvoid
*ptr
= NULL
;
3736 VerifyDevice(&device
);
3737 alcSetError(device
, ALC_INVALID_VALUE
);
3738 if(device
) ALCdevice_DecRef(device
);
3743 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3745 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3747 ptr
= alcFunctions
[i
].address
;
3759 * Get the value for a particular ALC enumeration name
3761 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3767 VerifyDevice(&device
);
3768 alcSetError(device
, ALC_INVALID_VALUE
);
3769 if(device
) ALCdevice_DecRef(device
);
3774 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3776 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3778 val
= alcEnumerations
[i
].value
;
3790 * Create and attach a context to the given device.
3792 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3794 ALCcontext
*ALContext
;
3798 /* Explicitly hold the list lock while taking the BackendLock in case the
3799 * device is asynchronously destropyed, to ensure this new context is
3800 * properly cleaned up after being made.
3803 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
3804 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
3807 alcSetError(device
, ALC_INVALID_DEVICE
);
3808 if(device
) ALCdevice_DecRef(device
);
3811 almtx_lock(&device
->BackendLock
);
3814 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3816 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3817 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3819 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3822 almtx_unlock(&device
->BackendLock
);
3824 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3825 ALCdevice_DecRef(device
);
3829 InitRef(&ALContext
->ref
, 1);
3830 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3831 ALContext
->DefaultSlot
= NULL
;
3833 ALContext
->Voices
= NULL
;
3834 ALContext
->VoiceCount
= 0;
3835 ALContext
->MaxVoices
= 0;
3836 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3837 ALContext
->Device
= device
;
3838 ATOMIC_INIT(&ALContext
->next
, NULL
);
3840 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3842 almtx_unlock(&device
->BackendLock
);
3847 alcSetError(device
, err
);
3848 if(err
== ALC_INVALID_DEVICE
)
3850 V0(device
->Backend
,lock
)();
3851 aluHandleDisconnect(device
, "Device update failure");
3852 V0(device
->Backend
,unlock
)();
3854 ALCdevice_DecRef(device
);
3857 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3859 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3861 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3862 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3863 aluInitEffectPanning(ALContext
->DefaultSlot
);
3866 ALContext
->DefaultSlot
= NULL
;
3867 ERR("Failed to initialize the default effect slot\n");
3871 ALCdevice_IncRef(ALContext
->Device
);
3872 InitContext(ALContext
);
3874 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3877 ERR("volume-adjust must be finite: %f\n", valf
);
3880 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3882 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3883 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3884 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3887 UpdateListenerProps(ALContext
);
3890 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3892 ATOMIC_STORE(&ALContext
->next
, head
, almemory_order_relaxed
);
3893 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3896 almtx_unlock(&device
->BackendLock
);
3898 if(ALContext
->DefaultSlot
)
3900 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3901 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3903 ERR("Failed to initialize the default effect\n");
3906 ALCdevice_DecRef(device
);
3908 TRACE("Created context %p\n", ALContext
);
3912 /* alcDestroyContext
3914 * Remove a context from its device
3916 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3921 if(!VerifyContext(&context
))
3924 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3928 Device
= context
->Device
;
3931 almtx_lock(&Device
->BackendLock
);
3932 if(!ReleaseContext(context
, Device
))
3934 V0(Device
->Backend
,stop
)();
3935 Device
->Flags
&= ~DEVICE_RUNNING
;
3937 almtx_unlock(&Device
->BackendLock
);
3941 ALCcontext_DecRef(context
);
3945 /* alcGetCurrentContext
3947 * Returns the currently active context on the calling thread
3949 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3951 ALCcontext
*Context
= altss_get(LocalContext
);
3952 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3956 /* alcGetThreadContext
3958 * Returns the currently active thread-local context
3960 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3962 return altss_get(LocalContext
);
3966 /* alcMakeContextCurrent
3968 * Makes the given context the active process-wide context, and removes the
3969 * thread-local context for the calling thread.
3971 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3973 /* context must be valid or NULL */
3974 if(context
&& !VerifyContext(&context
))
3976 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3979 /* context's reference count is already incremented */
3980 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3981 if(context
) ALCcontext_DecRef(context
);
3983 if((context
=altss_get(LocalContext
)) != NULL
)
3985 altss_set(LocalContext
, NULL
);
3986 ALCcontext_DecRef(context
);
3992 /* alcSetThreadContext
3994 * Makes the given context the active context for the current thread
3996 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
4000 /* context must be valid or NULL */
4001 if(context
&& !VerifyContext(&context
))
4003 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
4006 /* context's reference count is already incremented */
4007 old
= altss_get(LocalContext
);
4008 altss_set(LocalContext
, context
);
4009 if(old
) ALCcontext_DecRef(old
);
4015 /* alcGetContextsDevice
4017 * Returns the device that a particular context is attached to
4019 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
4023 if(!VerifyContext(&Context
))
4025 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
4028 Device
= Context
->Device
;
4029 ALCcontext_DecRef(Context
);
4037 * Opens the named device.
4039 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
4041 ALCbackendFactory
*factory
;
4048 if(!PlaybackBackend
.name
)
4050 alcSetError(NULL
, ALC_INVALID_VALUE
);
4054 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
4056 /* Some old Windows apps hardcode these expecting OpenAL to use a
4057 * specific audio API, even when they're not enumerated. Creative's
4058 * router effectively ignores them too.
4060 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
4061 || strcasecmp(deviceName
, "MMSYSTEM") == 0
4066 device
= al_calloc(16, sizeof(ALCdevice
));
4069 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4074 InitDevice(device
, Playback
);
4077 device
->FmtChans
= DevFmtChannelsDefault
;
4078 device
->FmtType
= DevFmtTypeDefault
;
4079 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4080 device
->IsHeadphones
= AL_FALSE
;
4081 device
->AmbiLayout
= AmbiLayout_Default
;
4082 device
->AmbiScale
= AmbiNorm_Default
;
4083 device
->NumUpdates
= 3;
4084 device
->UpdateSize
= 1024;
4086 device
->SourcesMax
= 256;
4087 device
->AuxiliaryEffectSlotMax
= 64;
4088 device
->NumAuxSends
= DEFAULT_SENDS
;
4090 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
4092 static const struct {
4093 const char name
[16];
4094 enum DevFmtChannels chans
;
4097 { "mono", DevFmtMono
, 0 },
4098 { "stereo", DevFmtStereo
, 0 },
4099 { "quad", DevFmtQuad
, 0 },
4100 { "surround51", DevFmtX51
, 0 },
4101 { "surround61", DevFmtX61
, 0 },
4102 { "surround71", DevFmtX71
, 0 },
4103 { "surround51rear", DevFmtX51Rear
, 0 },
4104 { "ambi1", DevFmtAmbi3D
, 1 },
4105 { "ambi2", DevFmtAmbi3D
, 2 },
4106 { "ambi3", DevFmtAmbi3D
, 3 },
4110 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4112 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4114 device
->FmtChans
= chanlist
[i
].chans
;
4115 device
->AmbiOrder
= chanlist
[i
].order
;
4116 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4120 if(i
== COUNTOF(chanlist
))
4121 ERR("Unsupported channels: %s\n", fmt
);
4123 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4125 static const struct {
4126 const char name
[16];
4127 enum DevFmtType type
;
4129 { "int8", DevFmtByte
},
4130 { "uint8", DevFmtUByte
},
4131 { "int16", DevFmtShort
},
4132 { "uint16", DevFmtUShort
},
4133 { "int32", DevFmtInt
},
4134 { "uint32", DevFmtUInt
},
4135 { "float32", DevFmtFloat
},
4139 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4141 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4143 device
->FmtType
= typelist
[i
].type
;
4144 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4148 if(i
== COUNTOF(typelist
))
4149 ERR("Unsupported sample-type: %s\n", fmt
);
4152 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4154 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4155 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4156 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4157 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4160 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4161 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4163 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4164 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4165 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4166 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4168 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4169 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4171 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4172 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4173 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4175 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4176 device
->NumAuxSends
= clampi(
4177 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4180 device
->NumStereoSources
= 1;
4181 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4183 factory
= PlaybackBackend
.getFactory();
4184 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
4185 if(!device
->Backend
)
4188 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4192 // Find a playback device to open
4193 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4196 alcSetError(NULL
, err
);
4200 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4202 if(strcasecmp(fmt
, "fuma") == 0)
4204 device
->AmbiLayout
= AmbiLayout_FuMa
;
4205 device
->AmbiScale
= AmbiNorm_FuMa
;
4207 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4209 device
->AmbiLayout
= AmbiLayout_ACN
;
4210 device
->AmbiScale
= AmbiNorm_SN3D
;
4212 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4214 device
->AmbiLayout
= AmbiLayout_ACN
;
4215 device
->AmbiScale
= AmbiNorm_N3D
;
4218 ERR("Unsupported ambi-format: %s\n", fmt
);
4221 device
->Limiter
= CreateDeviceLimiter(device
);
4224 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4226 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4227 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4230 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4236 * Closes the given device.
4238 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4240 ALCdevice
*iter
, *origdev
, *nextdev
;
4244 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4248 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4249 } while(iter
!= NULL
);
4250 if(!iter
|| iter
->Type
== Capture
)
4252 alcSetError(iter
, ALC_INVALID_DEVICE
);
4256 almtx_lock(&device
->BackendLock
);
4259 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4260 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4266 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4270 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4273 ALCcontext
*next
= ATOMIC_LOAD(&ctx
->next
, almemory_order_relaxed
);
4274 WARN("Releasing context %p\n", ctx
);
4275 ReleaseContext(ctx
, device
);
4278 if((device
->Flags
&DEVICE_RUNNING
))
4279 V0(device
->Backend
,stop
)();
4280 device
->Flags
&= ~DEVICE_RUNNING
;
4281 almtx_unlock(&device
->BackendLock
);
4283 ALCdevice_DecRef(device
);
4289 /************************************************
4290 * ALC capture functions
4291 ************************************************/
4292 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4294 ALCbackendFactory
*factory
;
4295 ALCdevice
*device
= NULL
;
4300 if(!CaptureBackend
.name
)
4302 alcSetError(NULL
, ALC_INVALID_VALUE
);
4308 alcSetError(NULL
, ALC_INVALID_VALUE
);
4312 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4315 device
= al_calloc(16, sizeof(ALCdevice
));
4318 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4323 InitDevice(device
, Capture
);
4325 device
->Frequency
= frequency
;
4326 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4328 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4331 alcSetError(NULL
, ALC_INVALID_ENUM
);
4334 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4335 device
->IsHeadphones
= AL_FALSE
;
4336 device
->AmbiOrder
= 0;
4337 device
->AmbiLayout
= AmbiLayout_Default
;
4338 device
->AmbiScale
= AmbiNorm_Default
;
4340 device
->UpdateSize
= samples
;
4341 device
->NumUpdates
= 1;
4343 factory
= CaptureBackend
.getFactory();
4344 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4345 if(!device
->Backend
)
4348 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4352 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4353 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4354 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4356 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4359 alcSetError(NULL
, err
);
4364 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4366 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4367 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4370 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4374 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4376 ALCdevice
*iter
, *origdev
, *nextdev
;
4379 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4383 iter
= ATOMIC_LOAD(&iter
->next
, almemory_order_relaxed
);
4384 } while(iter
!= NULL
);
4385 if(!iter
|| iter
->Type
!= Capture
)
4387 alcSetError(iter
, ALC_INVALID_DEVICE
);
4393 nextdev
= ATOMIC_LOAD(&device
->next
, almemory_order_relaxed
);
4394 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, nextdev
))
4400 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&list
->next
, &origdev
, nextdev
));
4404 almtx_lock(&device
->BackendLock
);
4405 if((device
->Flags
&DEVICE_RUNNING
))
4406 V0(device
->Backend
,stop
)();
4407 device
->Flags
&= ~DEVICE_RUNNING
;
4408 almtx_unlock(&device
->BackendLock
);
4410 ALCdevice_DecRef(device
);
4415 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4417 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4418 alcSetError(device
, ALC_INVALID_DEVICE
);
4421 almtx_lock(&device
->BackendLock
);
4422 if(!ATOMIC_LOAD(&device
->Connected
, almemory_order_acquire
))
4423 alcSetError(device
, ALC_INVALID_DEVICE
);
4424 else if(!(device
->Flags
&DEVICE_RUNNING
))
4426 if(V0(device
->Backend
,start
)())
4427 device
->Flags
|= DEVICE_RUNNING
;
4430 aluHandleDisconnect(device
, "Device start failure");
4431 alcSetError(device
, ALC_INVALID_DEVICE
);
4434 almtx_unlock(&device
->BackendLock
);
4437 if(device
) ALCdevice_DecRef(device
);
4440 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4442 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4443 alcSetError(device
, ALC_INVALID_DEVICE
);
4446 almtx_lock(&device
->BackendLock
);
4447 if((device
->Flags
&DEVICE_RUNNING
))
4448 V0(device
->Backend
,stop
)();
4449 device
->Flags
&= ~DEVICE_RUNNING
;
4450 almtx_unlock(&device
->BackendLock
);
4453 if(device
) ALCdevice_DecRef(device
);
4456 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4458 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4459 alcSetError(device
, ALC_INVALID_DEVICE
);
4462 ALCenum err
= ALC_INVALID_VALUE
;
4464 almtx_lock(&device
->BackendLock
);
4465 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4466 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4467 almtx_unlock(&device
->BackendLock
);
4469 if(err
!= ALC_NO_ERROR
)
4470 alcSetError(device
, err
);
4472 if(device
) ALCdevice_DecRef(device
);
4476 /************************************************
4477 * ALC loopback functions
4478 ************************************************/
4480 /* alcLoopbackOpenDeviceSOFT
4482 * Open a loopback device, for manual rendering.
4484 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4486 ALCbackendFactory
*factory
;
4491 /* Make sure the device name, if specified, is us. */
4492 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4494 alcSetError(NULL
, ALC_INVALID_VALUE
);
4498 device
= al_calloc(16, sizeof(ALCdevice
));
4501 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4506 InitDevice(device
, Loopback
);
4508 device
->SourcesMax
= 256;
4509 device
->AuxiliaryEffectSlotMax
= 64;
4510 device
->NumAuxSends
= DEFAULT_SENDS
;
4513 device
->NumUpdates
= 0;
4514 device
->UpdateSize
= 0;
4516 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4517 device
->FmtChans
= DevFmtChannelsDefault
;
4518 device
->FmtType
= DevFmtTypeDefault
;
4519 device
->IsHeadphones
= AL_FALSE
;
4520 device
->AmbiLayout
= AmbiLayout_Default
;
4521 device
->AmbiScale
= AmbiNorm_Default
;
4523 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4524 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4526 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4527 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4528 else device
->AuxiliaryEffectSlotMax
= minu(device
->AuxiliaryEffectSlotMax
, INT_MAX
);
4530 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4531 device
->NumAuxSends
= clampi(
4532 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4535 device
->NumStereoSources
= 1;
4536 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4538 factory
= ALCloopbackFactory_getFactory();
4539 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4540 if(!device
->Backend
)
4543 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4547 // Open the "backend"
4548 V(device
->Backend
,open
)("Loopback");
4550 device
->Limiter
= CreateDeviceLimiter(device
);
4553 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4555 ATOMIC_STORE(&device
->next
, head
, almemory_order_relaxed
);
4556 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4559 TRACE("Created device %p\n", device
);
4563 /* alcIsRenderFormatSupportedSOFT
4565 * Determines if the loopback device supports the given format for rendering.
4567 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4569 ALCboolean ret
= ALC_FALSE
;
4571 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4572 alcSetError(device
, ALC_INVALID_DEVICE
);
4574 alcSetError(device
, ALC_INVALID_VALUE
);
4577 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4580 if(device
) ALCdevice_DecRef(device
);
4585 /* alcRenderSamplesSOFT
4587 * Renders some samples into a buffer, using the format last set by the
4588 * attributes given to alcCreateContext.
4590 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4592 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4593 alcSetError(device
, ALC_INVALID_DEVICE
);
4594 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4595 alcSetError(device
, ALC_INVALID_VALUE
);
4598 V0(device
->Backend
,lock
)();
4599 aluMixData(device
, buffer
, samples
);
4600 V0(device
->Backend
,unlock
)();
4602 if(device
) ALCdevice_DecRef(device
);
4606 /************************************************
4607 * ALC DSP pause/resume functions
4608 ************************************************/
4610 /* alcDevicePauseSOFT
4612 * Pause the DSP to stop audio processing.
4614 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4616 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4617 alcSetError(device
, ALC_INVALID_DEVICE
);
4620 almtx_lock(&device
->BackendLock
);
4621 if((device
->Flags
&DEVICE_RUNNING
))
4622 V0(device
->Backend
,stop
)();
4623 device
->Flags
&= ~DEVICE_RUNNING
;
4624 device
->Flags
|= DEVICE_PAUSED
;
4625 almtx_unlock(&device
->BackendLock
);
4627 if(device
) ALCdevice_DecRef(device
);
4630 /* alcDeviceResumeSOFT
4632 * Resume the DSP to restart audio processing.
4634 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4636 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4637 alcSetError(device
, ALC_INVALID_DEVICE
);
4640 almtx_lock(&device
->BackendLock
);
4641 if((device
->Flags
&DEVICE_PAUSED
))
4643 device
->Flags
&= ~DEVICE_PAUSED
;
4644 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4646 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4647 device
->Flags
|= DEVICE_RUNNING
;
4650 V0(device
->Backend
,lock
)();
4651 aluHandleDisconnect(device
, "Device start failure");
4652 V0(device
->Backend
,unlock
)();
4653 alcSetError(device
, ALC_INVALID_DEVICE
);
4657 almtx_unlock(&device
->BackendLock
);
4659 if(device
) ALCdevice_DecRef(device
);
4663 /************************************************
4664 * ALC HRTF functions
4665 ************************************************/
4667 /* alcGetStringiSOFT
4669 * Gets a string parameter at the given index.
4671 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4673 const ALCchar
*str
= NULL
;
4675 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4676 alcSetError(device
, ALC_INVALID_DEVICE
);
4677 else switch(paramName
)
4679 case ALC_HRTF_SPECIFIER_SOFT
:
4680 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4681 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4683 alcSetError(device
, ALC_INVALID_VALUE
);
4687 alcSetError(device
, ALC_INVALID_ENUM
);
4690 if(device
) ALCdevice_DecRef(device
);
4695 /* alcResetDeviceSOFT
4697 * Resets the given device output, using the specified attribute list.
4699 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4704 if(!VerifyDevice(&device
) || device
->Type
== Capture
||
4705 !ATOMIC_LOAD(&device
->Connected
, almemory_order_relaxed
))
4708 alcSetError(device
, ALC_INVALID_DEVICE
);
4709 if(device
) ALCdevice_DecRef(device
);
4712 almtx_lock(&device
->BackendLock
);
4715 err
= UpdateDeviceParams(device
, attribs
);
4716 almtx_unlock(&device
->BackendLock
);
4718 if(err
!= ALC_NO_ERROR
)
4720 alcSetError(device
, err
);
4721 if(err
== ALC_INVALID_DEVICE
)
4723 V0(device
->Backend
,lock
)();
4724 aluHandleDisconnect(device
, "Device start failure");
4725 V0(device
->Backend
,unlock
)();
4727 ALCdevice_DecRef(device
);
4730 ALCdevice_DecRef(device
);