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"
38 #include "alAuxEffectSlot.h"
40 #include "bformatdec.h"
48 #include "backends/base.h"
51 /************************************************
53 ************************************************/
56 ALCbackendFactory
* (*getFactory
)(void);
59 static struct BackendInfo BackendList
[] = {
61 { "jack", ALCjackBackendFactory_getFactory
},
63 #ifdef HAVE_PULSEAUDIO
64 { "pulse", ALCpulseBackendFactory_getFactory
},
67 { "alsa", ALCalsaBackendFactory_getFactory
},
70 { "core", ALCcoreAudioBackendFactory_getFactory
},
73 { "oss", ALCossBackendFactory_getFactory
},
76 { "solaris", ALCsolarisBackendFactory_getFactory
},
79 { "sndio", ALCsndioBackendFactory_getFactory
},
82 { "qsa", ALCqsaBackendFactory_getFactory
},
85 { "mmdevapi", ALCmmdevBackendFactory_getFactory
},
88 { "dsound", ALCdsoundBackendFactory_getFactory
},
91 { "winmm", ALCwinmmBackendFactory_getFactory
},
94 { "port", ALCportBackendFactory_getFactory
},
97 { "opensl", ALCopenslBackendFactory_getFactory
},
100 { "null", ALCnullBackendFactory_getFactory
},
102 { "wave", ALCwaveBackendFactory_getFactory
},
105 static ALsizei BackendListSize
= COUNTOF(BackendList
);
108 static struct BackendInfo PlaybackBackend
;
109 static struct BackendInfo CaptureBackend
;
112 /************************************************
113 * Functions, enums, and errors
114 ************************************************/
115 #define DECL(x) { #x, (ALCvoid*)(x) }
116 static const struct {
117 const ALCchar
*funcName
;
120 DECL(alcCreateContext
),
121 DECL(alcMakeContextCurrent
),
122 DECL(alcProcessContext
),
123 DECL(alcSuspendContext
),
124 DECL(alcDestroyContext
),
125 DECL(alcGetCurrentContext
),
126 DECL(alcGetContextsDevice
),
128 DECL(alcCloseDevice
),
130 DECL(alcIsExtensionPresent
),
131 DECL(alcGetProcAddress
),
132 DECL(alcGetEnumValue
),
134 DECL(alcGetIntegerv
),
135 DECL(alcCaptureOpenDevice
),
136 DECL(alcCaptureCloseDevice
),
137 DECL(alcCaptureStart
),
138 DECL(alcCaptureStop
),
139 DECL(alcCaptureSamples
),
141 DECL(alcSetThreadContext
),
142 DECL(alcGetThreadContext
),
144 DECL(alcLoopbackOpenDeviceSOFT
),
145 DECL(alcIsRenderFormatSupportedSOFT
),
146 DECL(alcRenderSamplesSOFT
),
148 DECL(alcDevicePauseSOFT
),
149 DECL(alcDeviceResumeSOFT
),
151 DECL(alcGetStringiSOFT
),
152 DECL(alcResetDeviceSOFT
),
154 DECL(alcGetInteger64vSOFT
),
169 DECL(alIsExtensionPresent
),
170 DECL(alGetProcAddress
),
171 DECL(alGetEnumValue
),
178 DECL(alGetListenerf
),
179 DECL(alGetListener3f
),
180 DECL(alGetListenerfv
),
181 DECL(alGetListeneri
),
182 DECL(alGetListener3i
),
183 DECL(alGetListeneriv
),
185 DECL(alDeleteSources
),
201 DECL(alSourceRewindv
),
202 DECL(alSourcePausev
),
205 DECL(alSourceRewind
),
207 DECL(alSourceQueueBuffers
),
208 DECL(alSourceUnqueueBuffers
),
210 DECL(alDeleteBuffers
),
225 DECL(alDopplerFactor
),
226 DECL(alDopplerVelocity
),
227 DECL(alSpeedOfSound
),
228 DECL(alDistanceModel
),
231 DECL(alDeleteFilters
),
242 DECL(alDeleteEffects
),
252 DECL(alGenAuxiliaryEffectSlots
),
253 DECL(alDeleteAuxiliaryEffectSlots
),
254 DECL(alIsAuxiliaryEffectSlot
),
255 DECL(alAuxiliaryEffectSloti
),
256 DECL(alAuxiliaryEffectSlotiv
),
257 DECL(alAuxiliaryEffectSlotf
),
258 DECL(alAuxiliaryEffectSlotfv
),
259 DECL(alGetAuxiliaryEffectSloti
),
260 DECL(alGetAuxiliaryEffectSlotiv
),
261 DECL(alGetAuxiliaryEffectSlotf
),
262 DECL(alGetAuxiliaryEffectSlotfv
),
264 DECL(alDeferUpdatesSOFT
),
265 DECL(alProcessUpdatesSOFT
),
268 DECL(alSource3dSOFT
),
269 DECL(alSourcedvSOFT
),
270 DECL(alGetSourcedSOFT
),
271 DECL(alGetSource3dSOFT
),
272 DECL(alGetSourcedvSOFT
),
273 DECL(alSourcei64SOFT
),
274 DECL(alSource3i64SOFT
),
275 DECL(alSourcei64vSOFT
),
276 DECL(alGetSourcei64SOFT
),
277 DECL(alGetSource3i64SOFT
),
278 DECL(alGetSourcei64vSOFT
),
280 DECL(alBufferSamplesSOFT
),
281 DECL(alGetBufferSamplesSOFT
),
282 DECL(alIsBufferFormatSupportedSOFT
),
284 DECL(alGetStringiSOFT
),
288 #define DECL(x) { #x, (x) }
289 static const struct {
290 const ALCchar
*enumName
;
292 } alcEnumerations
[] = {
297 DECL(ALC_MAJOR_VERSION
),
298 DECL(ALC_MINOR_VERSION
),
299 DECL(ALC_ATTRIBUTES_SIZE
),
300 DECL(ALC_ALL_ATTRIBUTES
),
301 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
302 DECL(ALC_DEVICE_SPECIFIER
),
303 DECL(ALC_ALL_DEVICES_SPECIFIER
),
304 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
305 DECL(ALC_EXTENSIONS
),
309 DECL(ALC_MONO_SOURCES
),
310 DECL(ALC_STEREO_SOURCES
),
311 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
312 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
313 DECL(ALC_CAPTURE_SAMPLES
),
316 DECL(ALC_EFX_MAJOR_VERSION
),
317 DECL(ALC_EFX_MINOR_VERSION
),
318 DECL(ALC_MAX_AUXILIARY_SENDS
),
320 DECL(ALC_FORMAT_CHANNELS_SOFT
),
321 DECL(ALC_FORMAT_TYPE_SOFT
),
324 DECL(ALC_STEREO_SOFT
),
326 DECL(ALC_5POINT1_SOFT
),
327 DECL(ALC_6POINT1_SOFT
),
328 DECL(ALC_7POINT1_SOFT
),
329 DECL(ALC_BFORMAT3D_SOFT
),
332 DECL(ALC_UNSIGNED_BYTE_SOFT
),
333 DECL(ALC_SHORT_SOFT
),
334 DECL(ALC_UNSIGNED_SHORT_SOFT
),
336 DECL(ALC_UNSIGNED_INT_SOFT
),
337 DECL(ALC_FLOAT_SOFT
),
340 DECL(ALC_DONT_CARE_SOFT
),
341 DECL(ALC_HRTF_STATUS_SOFT
),
342 DECL(ALC_HRTF_DISABLED_SOFT
),
343 DECL(ALC_HRTF_ENABLED_SOFT
),
344 DECL(ALC_HRTF_DENIED_SOFT
),
345 DECL(ALC_HRTF_REQUIRED_SOFT
),
346 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
347 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
348 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
349 DECL(ALC_HRTF_SPECIFIER_SOFT
),
350 DECL(ALC_HRTF_ID_SOFT
),
352 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
353 DECL(ALC_AMBISONIC_SCALING_SOFT
),
354 DECL(ALC_AMBISONIC_ORDER_SOFT
),
360 DECL(ALC_OUTPUT_LIMITER_SOFT
),
363 DECL(ALC_INVALID_DEVICE
),
364 DECL(ALC_INVALID_CONTEXT
),
365 DECL(ALC_INVALID_ENUM
),
366 DECL(ALC_INVALID_VALUE
),
367 DECL(ALC_OUT_OF_MEMORY
),
375 DECL(AL_SOURCE_RELATIVE
),
376 DECL(AL_CONE_INNER_ANGLE
),
377 DECL(AL_CONE_OUTER_ANGLE
),
387 DECL(AL_ORIENTATION
),
388 DECL(AL_REFERENCE_DISTANCE
),
389 DECL(AL_ROLLOFF_FACTOR
),
390 DECL(AL_CONE_OUTER_GAIN
),
391 DECL(AL_MAX_DISTANCE
),
393 DECL(AL_SAMPLE_OFFSET
),
394 DECL(AL_BYTE_OFFSET
),
395 DECL(AL_SOURCE_TYPE
),
398 DECL(AL_UNDETERMINED
),
399 DECL(AL_METERS_PER_UNIT
),
400 DECL(AL_LOOP_POINTS_SOFT
),
401 DECL(AL_DIRECT_CHANNELS_SOFT
),
403 DECL(AL_DIRECT_FILTER
),
404 DECL(AL_AUXILIARY_SEND_FILTER
),
405 DECL(AL_AIR_ABSORPTION_FACTOR
),
406 DECL(AL_ROOM_ROLLOFF_FACTOR
),
407 DECL(AL_CONE_OUTER_GAINHF
),
408 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
409 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
410 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
412 DECL(AL_SOURCE_STATE
),
418 DECL(AL_BUFFERS_QUEUED
),
419 DECL(AL_BUFFERS_PROCESSED
),
421 DECL(AL_FORMAT_MONO8
),
422 DECL(AL_FORMAT_MONO16
),
423 DECL(AL_FORMAT_MONO_FLOAT32
),
424 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
425 DECL(AL_FORMAT_STEREO8
),
426 DECL(AL_FORMAT_STEREO16
),
427 DECL(AL_FORMAT_STEREO_FLOAT32
),
428 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
429 DECL(AL_FORMAT_MONO_IMA4
),
430 DECL(AL_FORMAT_STEREO_IMA4
),
431 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
432 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
433 DECL(AL_FORMAT_QUAD8_LOKI
),
434 DECL(AL_FORMAT_QUAD16_LOKI
),
435 DECL(AL_FORMAT_QUAD8
),
436 DECL(AL_FORMAT_QUAD16
),
437 DECL(AL_FORMAT_QUAD32
),
438 DECL(AL_FORMAT_51CHN8
),
439 DECL(AL_FORMAT_51CHN16
),
440 DECL(AL_FORMAT_51CHN32
),
441 DECL(AL_FORMAT_61CHN8
),
442 DECL(AL_FORMAT_61CHN16
),
443 DECL(AL_FORMAT_61CHN32
),
444 DECL(AL_FORMAT_71CHN8
),
445 DECL(AL_FORMAT_71CHN16
),
446 DECL(AL_FORMAT_71CHN32
),
447 DECL(AL_FORMAT_REAR8
),
448 DECL(AL_FORMAT_REAR16
),
449 DECL(AL_FORMAT_REAR32
),
450 DECL(AL_FORMAT_MONO_MULAW
),
451 DECL(AL_FORMAT_MONO_MULAW_EXT
),
452 DECL(AL_FORMAT_STEREO_MULAW
),
453 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
454 DECL(AL_FORMAT_QUAD_MULAW
),
455 DECL(AL_FORMAT_51CHN_MULAW
),
456 DECL(AL_FORMAT_61CHN_MULAW
),
457 DECL(AL_FORMAT_71CHN_MULAW
),
458 DECL(AL_FORMAT_REAR_MULAW
),
459 DECL(AL_FORMAT_MONO_ALAW_EXT
),
460 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
462 DECL(AL_FORMAT_BFORMAT2D_8
),
463 DECL(AL_FORMAT_BFORMAT2D_16
),
464 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
465 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
466 DECL(AL_FORMAT_BFORMAT3D_8
),
467 DECL(AL_FORMAT_BFORMAT3D_16
),
468 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
469 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
472 DECL(AL_MONO16_SOFT
),
473 DECL(AL_MONO32F_SOFT
),
474 DECL(AL_STEREO8_SOFT
),
475 DECL(AL_STEREO16_SOFT
),
476 DECL(AL_STEREO32F_SOFT
),
478 DECL(AL_QUAD16_SOFT
),
479 DECL(AL_QUAD32F_SOFT
),
481 DECL(AL_REAR16_SOFT
),
482 DECL(AL_REAR32F_SOFT
),
483 DECL(AL_5POINT1_8_SOFT
),
484 DECL(AL_5POINT1_16_SOFT
),
485 DECL(AL_5POINT1_32F_SOFT
),
486 DECL(AL_6POINT1_8_SOFT
),
487 DECL(AL_6POINT1_16_SOFT
),
488 DECL(AL_6POINT1_32F_SOFT
),
489 DECL(AL_7POINT1_8_SOFT
),
490 DECL(AL_7POINT1_16_SOFT
),
491 DECL(AL_7POINT1_32F_SOFT
),
492 DECL(AL_BFORMAT2D_8_SOFT
),
493 DECL(AL_BFORMAT2D_16_SOFT
),
494 DECL(AL_BFORMAT2D_32F_SOFT
),
495 DECL(AL_BFORMAT3D_8_SOFT
),
496 DECL(AL_BFORMAT3D_16_SOFT
),
497 DECL(AL_BFORMAT3D_32F_SOFT
),
500 DECL(AL_STEREO_SOFT
),
503 DECL(AL_5POINT1_SOFT
),
504 DECL(AL_6POINT1_SOFT
),
505 DECL(AL_7POINT1_SOFT
),
506 DECL(AL_BFORMAT2D_SOFT
),
507 DECL(AL_BFORMAT3D_SOFT
),
510 DECL(AL_UNSIGNED_BYTE_SOFT
),
512 DECL(AL_UNSIGNED_SHORT_SOFT
),
514 DECL(AL_UNSIGNED_INT_SOFT
),
516 DECL(AL_DOUBLE_SOFT
),
518 DECL(AL_UNSIGNED_BYTE3_SOFT
),
525 DECL(AL_INTERNAL_FORMAT_SOFT
),
526 DECL(AL_BYTE_LENGTH_SOFT
),
527 DECL(AL_SAMPLE_LENGTH_SOFT
),
528 DECL(AL_SEC_LENGTH_SOFT
),
529 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
530 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
532 DECL(AL_SOURCE_RADIUS
),
534 DECL(AL_STEREO_ANGLES
),
541 DECL(AL_INVALID_NAME
),
542 DECL(AL_INVALID_ENUM
),
543 DECL(AL_INVALID_VALUE
),
544 DECL(AL_INVALID_OPERATION
),
545 DECL(AL_OUT_OF_MEMORY
),
552 DECL(AL_DOPPLER_FACTOR
),
553 DECL(AL_DOPPLER_VELOCITY
),
554 DECL(AL_DISTANCE_MODEL
),
555 DECL(AL_SPEED_OF_SOUND
),
556 DECL(AL_SOURCE_DISTANCE_MODEL
),
557 DECL(AL_DEFERRED_UPDATES_SOFT
),
558 DECL(AL_GAIN_LIMIT_SOFT
),
560 DECL(AL_INVERSE_DISTANCE
),
561 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
562 DECL(AL_LINEAR_DISTANCE
),
563 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
564 DECL(AL_EXPONENT_DISTANCE
),
565 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
567 DECL(AL_FILTER_TYPE
),
568 DECL(AL_FILTER_NULL
),
569 DECL(AL_FILTER_LOWPASS
),
570 DECL(AL_FILTER_HIGHPASS
),
571 DECL(AL_FILTER_BANDPASS
),
573 DECL(AL_LOWPASS_GAIN
),
574 DECL(AL_LOWPASS_GAINHF
),
576 DECL(AL_HIGHPASS_GAIN
),
577 DECL(AL_HIGHPASS_GAINLF
),
579 DECL(AL_BANDPASS_GAIN
),
580 DECL(AL_BANDPASS_GAINHF
),
581 DECL(AL_BANDPASS_GAINLF
),
583 DECL(AL_EFFECT_TYPE
),
584 DECL(AL_EFFECT_NULL
),
585 DECL(AL_EFFECT_REVERB
),
586 DECL(AL_EFFECT_EAXREVERB
),
587 DECL(AL_EFFECT_CHORUS
),
588 DECL(AL_EFFECT_DISTORTION
),
589 DECL(AL_EFFECT_ECHO
),
590 DECL(AL_EFFECT_FLANGER
),
592 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
593 DECL(AL_EFFECT_VOCAL_MORPHER
),
594 DECL(AL_EFFECT_PITCH_SHIFTER
),
596 DECL(AL_EFFECT_RING_MODULATOR
),
598 DECL(AL_EFFECT_AUTOWAH
),
600 DECL(AL_EFFECT_COMPRESSOR
),
601 DECL(AL_EFFECT_EQUALIZER
),
602 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
603 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
605 DECL(AL_EFFECTSLOT_EFFECT
),
606 DECL(AL_EFFECTSLOT_GAIN
),
607 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
608 DECL(AL_EFFECTSLOT_NULL
),
610 DECL(AL_EAXREVERB_DENSITY
),
611 DECL(AL_EAXREVERB_DIFFUSION
),
612 DECL(AL_EAXREVERB_GAIN
),
613 DECL(AL_EAXREVERB_GAINHF
),
614 DECL(AL_EAXREVERB_GAINLF
),
615 DECL(AL_EAXREVERB_DECAY_TIME
),
616 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
617 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
618 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
619 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
620 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
621 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
622 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
623 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
624 DECL(AL_EAXREVERB_ECHO_TIME
),
625 DECL(AL_EAXREVERB_ECHO_DEPTH
),
626 DECL(AL_EAXREVERB_MODULATION_TIME
),
627 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
628 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
629 DECL(AL_EAXREVERB_HFREFERENCE
),
630 DECL(AL_EAXREVERB_LFREFERENCE
),
631 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
632 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
634 DECL(AL_REVERB_DENSITY
),
635 DECL(AL_REVERB_DIFFUSION
),
636 DECL(AL_REVERB_GAIN
),
637 DECL(AL_REVERB_GAINHF
),
638 DECL(AL_REVERB_DECAY_TIME
),
639 DECL(AL_REVERB_DECAY_HFRATIO
),
640 DECL(AL_REVERB_REFLECTIONS_GAIN
),
641 DECL(AL_REVERB_REFLECTIONS_DELAY
),
642 DECL(AL_REVERB_LATE_REVERB_GAIN
),
643 DECL(AL_REVERB_LATE_REVERB_DELAY
),
644 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
645 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
646 DECL(AL_REVERB_DECAY_HFLIMIT
),
648 DECL(AL_CHORUS_WAVEFORM
),
649 DECL(AL_CHORUS_PHASE
),
650 DECL(AL_CHORUS_RATE
),
651 DECL(AL_CHORUS_DEPTH
),
652 DECL(AL_CHORUS_FEEDBACK
),
653 DECL(AL_CHORUS_DELAY
),
655 DECL(AL_DISTORTION_EDGE
),
656 DECL(AL_DISTORTION_GAIN
),
657 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
658 DECL(AL_DISTORTION_EQCENTER
),
659 DECL(AL_DISTORTION_EQBANDWIDTH
),
662 DECL(AL_ECHO_LRDELAY
),
663 DECL(AL_ECHO_DAMPING
),
664 DECL(AL_ECHO_FEEDBACK
),
665 DECL(AL_ECHO_SPREAD
),
667 DECL(AL_FLANGER_WAVEFORM
),
668 DECL(AL_FLANGER_PHASE
),
669 DECL(AL_FLANGER_RATE
),
670 DECL(AL_FLANGER_DEPTH
),
671 DECL(AL_FLANGER_FEEDBACK
),
672 DECL(AL_FLANGER_DELAY
),
674 DECL(AL_RING_MODULATOR_FREQUENCY
),
675 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
676 DECL(AL_RING_MODULATOR_WAVEFORM
),
678 DECL(AL_COMPRESSOR_ONOFF
),
680 DECL(AL_EQUALIZER_LOW_GAIN
),
681 DECL(AL_EQUALIZER_LOW_CUTOFF
),
682 DECL(AL_EQUALIZER_MID1_GAIN
),
683 DECL(AL_EQUALIZER_MID1_CENTER
),
684 DECL(AL_EQUALIZER_MID1_WIDTH
),
685 DECL(AL_EQUALIZER_MID2_GAIN
),
686 DECL(AL_EQUALIZER_MID2_CENTER
),
687 DECL(AL_EQUALIZER_MID2_WIDTH
),
688 DECL(AL_EQUALIZER_HIGH_GAIN
),
689 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
691 DECL(AL_DEDICATED_GAIN
),
693 DECL(AL_NUM_RESAMPLERS_SOFT
),
694 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
695 DECL(AL_SOURCE_RESAMPLER_SOFT
),
696 DECL(AL_RESAMPLER_NAME_SOFT
),
698 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
703 static const ALCchar alcNoError
[] = "No Error";
704 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
705 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
706 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
707 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
708 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
711 /************************************************
713 ************************************************/
715 /* Enumerated device names */
716 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
718 static al_string alcAllDevicesList
;
719 static al_string alcCaptureDeviceList
;
721 /* Default is always the first in the list */
722 static ALCchar
*alcDefaultAllDevicesSpecifier
;
723 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
725 /* Default context extensions */
726 static const ALchar alExtList
[] =
727 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
728 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
729 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
730 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
731 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
732 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
733 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length "
734 "AL_SOFT_source_resampler AL_SOFT_source_spatialize";
736 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
738 /* Thread-local current context */
739 static altss_t LocalContext
;
740 /* Process-wide current context */
741 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
743 /* Mixing thread piority level */
748 enum LogLevel LogLevel
= LogWarning
;
750 enum LogLevel LogLevel
= LogError
;
753 /* Flag to trap ALC device errors */
754 static ALCboolean TrapALCError
= ALC_FALSE
;
756 /* One-time configuration init control */
757 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
759 /* Default effect that applies to sources that don't have an effect on send 0 */
760 static ALeffect DefaultEffect
;
762 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
765 static ALCboolean SuspendDefers
= ALC_TRUE
;
768 /************************************************
770 ************************************************/
771 static const ALCchar alcNoDeviceExtList
[] =
772 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
773 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
774 static const ALCchar alcExtensionList
[] =
775 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
776 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
777 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
778 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
779 static const ALCint alcMajorVersion
= 1;
780 static const ALCint alcMinorVersion
= 1;
782 static const ALCint alcEFXMajorVersion
= 1;
783 static const ALCint alcEFXMinorVersion
= 0;
786 /************************************************
788 ************************************************/
789 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
791 static almtx_t ListLock
;
792 static inline void LockLists(void)
794 int ret
= almtx_lock(&ListLock
);
795 assert(ret
== althrd_success
);
797 static inline void UnlockLists(void)
799 int ret
= almtx_unlock(&ListLock
);
800 assert(ret
== althrd_success
);
803 /************************************************
804 * Library initialization
805 ************************************************/
807 static void alc_init(void);
808 static void alc_deinit(void);
809 static void alc_deinit_safe(void);
811 #ifndef AL_LIBTYPE_STATIC
812 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
816 case DLL_PROCESS_ATTACH
:
817 /* Pin the DLL so we won't get unloaded until the process terminates */
818 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
819 (WCHAR
*)hModule
, &hModule
);
823 case DLL_THREAD_DETACH
:
826 case DLL_PROCESS_DETACH
:
835 #elif defined(_MSC_VER)
836 #pragma section(".CRT$XCU",read)
837 static void alc_constructor(void);
838 static void alc_destructor(void);
839 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
841 static void alc_constructor(void)
843 atexit(alc_destructor
);
847 static void alc_destructor(void)
851 #elif defined(HAVE_GCC_DESTRUCTOR)
852 static void alc_init(void) __attribute__((constructor
));
853 static void alc_deinit(void) __attribute__((destructor
));
855 #error "No static initialization available on this platform!"
858 #elif defined(HAVE_GCC_DESTRUCTOR)
860 static void alc_init(void) __attribute__((constructor
));
861 static void alc_deinit(void) __attribute__((destructor
));
864 #error "No global initialization available on this platform!"
867 static void ReleaseThreadCtx(void *ptr
);
868 static void alc_init(void)
875 AL_STRING_INIT(alcAllDevicesList
);
876 AL_STRING_INIT(alcCaptureDeviceList
);
878 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
879 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
882 str
= getenv("__ALSOFT_REVERSE_Z");
883 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
886 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
887 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
888 OverrideReverbSpeedOfSound
= AL_TRUE
;
890 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
891 assert(ret
== althrd_success
);
893 ret
= almtx_init(&ListLock
, almtx_recursive
);
894 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 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1033 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1034 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1038 const char *next
= devs
;
1039 int endlist
, delitem
;
1044 while(isspace(devs
[0]))
1046 next
= strchr(devs
, ',');
1048 delitem
= (devs
[0] == '-');
1049 if(devs
[0] == '-') devs
++;
1051 if(!devs
[0] || devs
[0] == ',')
1058 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1059 while(len
> 0 && isspace(devs
[len
-1]))
1061 for(n
= i
;n
< BackendListSize
;n
++)
1063 if(len
== strlen(BackendList
[n
].name
) &&
1064 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1068 for(;n
+1 < BackendListSize
;n
++)
1069 BackendList
[n
] = BackendList
[n
+1];
1074 struct BackendInfo Bkp
= BackendList
[n
];
1076 BackendList
[n
] = BackendList
[n
-1];
1077 BackendList
[n
] = Bkp
;
1087 BackendListSize
= i
;
1090 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1092 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1093 if(!V0(factory
,init
)())
1095 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1099 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1100 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1102 PlaybackBackend
= BackendList
[i
];
1103 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1105 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1107 CaptureBackend
= BackendList
[i
];
1108 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1112 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1116 if(!PlaybackBackend
.name
)
1117 WARN("No playback backend available!\n");
1118 if(!CaptureBackend
.name
)
1119 WARN("No capture backend available!\n");
1121 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1124 const char *next
= str
;
1128 next
= strchr(str
, ',');
1130 if(!str
[0] || next
== str
)
1133 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1134 for(n
= 0;EffectList
[n
].name
;n
++)
1136 if(len
== strlen(EffectList
[n
].name
) &&
1137 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1138 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1143 InitEffectFactoryMap();
1145 InitEffect(&DefaultEffect
);
1146 str
= getenv("ALSOFT_DEFAULT_REVERB");
1147 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1148 LoadReverbPreset(str
, &DefaultEffect
);
1150 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1155 static JavaVM
*gJavaVM
;
1156 static pthread_key_t gJVMThreadKey
;
1158 static void CleanupJNIEnv(void* UNUSED(ptr
))
1160 JCALL0(gJavaVM
,DetachCurrentThread
)();
1163 void *Android_GetJNIEnv(void)
1167 WARN("gJavaVM is NULL!\n");
1171 /* http://developer.android.com/guide/practices/jni.html
1173 * All threads are Linux threads, scheduled by the kernel. They're usually
1174 * started from managed code (using Thread.start), but they can also be
1175 * created elsewhere and then attached to the JavaVM. For example, a thread
1176 * started with pthread_create can be attached with the JNI
1177 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1178 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1179 * Attaching a natively-created thread causes a java.lang.Thread object to
1180 * be constructed and added to the "main" ThreadGroup, making it visible to
1181 * the debugger. Calling AttachCurrentThread on an already-attached thread
1184 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1187 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1190 ERR("Failed to attach current thread\n");
1193 pthread_setspecific(gJVMThreadKey
, env
);
1198 /* Automatically called by JNI. */
1199 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1205 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1207 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1211 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1212 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1214 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1215 ERR("pthread_key_create failed: %d\n", err
);
1216 pthread_setspecific(gJVMThreadKey
, env
);
1217 return JNI_VERSION_1_4
;
1222 /************************************************
1223 * Library deinitialization
1224 ************************************************/
1225 static void alc_cleanup(void)
1229 AL_STRING_DEINIT(alcAllDevicesList
);
1230 AL_STRING_DEINIT(alcCaptureDeviceList
);
1232 free(alcDefaultAllDevicesSpecifier
);
1233 alcDefaultAllDevicesSpecifier
= NULL
;
1234 free(alcCaptureDefaultDeviceSpecifier
);
1235 alcCaptureDefaultDeviceSpecifier
= NULL
;
1237 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1242 } while((dev
=dev
->next
) != NULL
);
1243 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1246 DeinitEffectFactoryMap();
1249 static void alc_deinit_safe(void)
1257 almtx_destroy(&ListLock
);
1258 altss_delete(LocalContext
);
1260 if(LogFile
!= stderr
)
1265 static void alc_deinit(void)
1271 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1272 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1274 for(i
= 0;i
< BackendListSize
;i
++)
1276 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1277 V0(factory
,deinit
)();
1280 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1281 V0(factory
,deinit
)();
1288 /************************************************
1289 * Device enumeration
1290 ************************************************/
1291 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1298 if(backendinfo
->getFactory
)
1300 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1301 V(factory
,probe
)(type
);
1306 static void ProbeAllDevicesList(void)
1307 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1308 static void ProbeCaptureDeviceList(void)
1309 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1311 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1313 size_t len
= strlen(name
);
1315 alstr_append_range(devnames
, name
, name
+len
+1);
1317 void AppendAllDevicesList(const ALCchar
*name
)
1318 { AppendDevice(name
, &alcAllDevicesList
); }
1319 void AppendCaptureDeviceList(const ALCchar
*name
)
1320 { AppendDevice(name
, &alcCaptureDeviceList
); }
1323 /************************************************
1324 * Device format information
1325 ************************************************/
1326 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1330 case DevFmtByte
: return "Signed Byte";
1331 case DevFmtUByte
: return "Unsigned Byte";
1332 case DevFmtShort
: return "Signed Short";
1333 case DevFmtUShort
: return "Unsigned Short";
1334 case DevFmtInt
: return "Signed Int";
1335 case DevFmtUInt
: return "Unsigned Int";
1336 case DevFmtFloat
: return "Float";
1338 return "(unknown type)";
1340 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1344 case DevFmtMono
: return "Mono";
1345 case DevFmtStereo
: return "Stereo";
1346 case DevFmtQuad
: return "Quadraphonic";
1347 case DevFmtX51
: return "5.1 Surround";
1348 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1349 case DevFmtX61
: return "6.1 Surround";
1350 case DevFmtX71
: return "7.1 Surround";
1351 case DevFmtAmbi3D
: return "Ambisonic 3D";
1353 return "(unknown channels)";
1356 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1357 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1361 case DevFmtByte
: return sizeof(ALbyte
);
1362 case DevFmtUByte
: return sizeof(ALubyte
);
1363 case DevFmtShort
: return sizeof(ALshort
);
1364 case DevFmtUShort
: return sizeof(ALushort
);
1365 case DevFmtInt
: return sizeof(ALint
);
1366 case DevFmtUInt
: return sizeof(ALuint
);
1367 case DevFmtFloat
: return sizeof(ALfloat
);
1371 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1375 case DevFmtMono
: return 1;
1376 case DevFmtStereo
: return 2;
1377 case DevFmtQuad
: return 4;
1378 case DevFmtX51
: return 6;
1379 case DevFmtX51Rear
: return 6;
1380 case DevFmtX61
: return 7;
1381 case DevFmtX71
: return 8;
1382 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1383 (ambiorder
== 2) ? 9 :
1384 (ambiorder
== 1) ? 4 : 1;
1389 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1390 enum DevFmtType
*type
)
1392 static const struct {
1394 enum DevFmtChannels channels
;
1395 enum DevFmtType type
;
1397 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1398 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1399 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1401 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1402 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1403 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1405 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1406 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1407 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1409 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1410 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1411 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1413 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1414 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1415 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1417 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1418 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1419 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1423 for(i
= 0;i
< COUNTOF(list
);i
++)
1425 if(list
[i
].format
== format
)
1427 *chans
= list
[i
].channels
;
1428 *type
= list
[i
].type
;
1436 static ALCboolean
IsValidALCType(ALCenum type
)
1441 case ALC_UNSIGNED_BYTE_SOFT
:
1442 case ALC_SHORT_SOFT
:
1443 case ALC_UNSIGNED_SHORT_SOFT
:
1445 case ALC_UNSIGNED_INT_SOFT
:
1446 case ALC_FLOAT_SOFT
:
1452 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1457 case ALC_STEREO_SOFT
:
1459 case ALC_5POINT1_SOFT
:
1460 case ALC_6POINT1_SOFT
:
1461 case ALC_7POINT1_SOFT
:
1462 case ALC_BFORMAT3D_SOFT
:
1468 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1479 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1491 /************************************************
1492 * Miscellaneous ALC helpers
1493 ************************************************/
1495 void ALCdevice_Lock(ALCdevice
*device
)
1497 V0(device
->Backend
,lock
)();
1500 void ALCdevice_Unlock(ALCdevice
*device
)
1502 V0(device
->Backend
,unlock
)();
1506 /* SetDefaultWFXChannelOrder
1508 * Sets the default channel order used by WaveFormatEx.
1510 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1514 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1515 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1517 switch(device
->FmtChans
)
1520 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1523 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1524 device
->RealOut
.ChannelName
[1] = FrontRight
;
1527 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1528 device
->RealOut
.ChannelName
[1] = FrontRight
;
1529 device
->RealOut
.ChannelName
[2] = BackLeft
;
1530 device
->RealOut
.ChannelName
[3] = BackRight
;
1533 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1534 device
->RealOut
.ChannelName
[1] = FrontRight
;
1535 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1536 device
->RealOut
.ChannelName
[3] = LFE
;
1537 device
->RealOut
.ChannelName
[4] = SideLeft
;
1538 device
->RealOut
.ChannelName
[5] = SideRight
;
1541 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1542 device
->RealOut
.ChannelName
[1] = FrontRight
;
1543 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1544 device
->RealOut
.ChannelName
[3] = LFE
;
1545 device
->RealOut
.ChannelName
[4] = BackLeft
;
1546 device
->RealOut
.ChannelName
[5] = BackRight
;
1549 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1550 device
->RealOut
.ChannelName
[1] = FrontRight
;
1551 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1552 device
->RealOut
.ChannelName
[3] = LFE
;
1553 device
->RealOut
.ChannelName
[4] = BackCenter
;
1554 device
->RealOut
.ChannelName
[5] = SideLeft
;
1555 device
->RealOut
.ChannelName
[6] = SideRight
;
1558 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1559 device
->RealOut
.ChannelName
[1] = FrontRight
;
1560 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1561 device
->RealOut
.ChannelName
[3] = LFE
;
1562 device
->RealOut
.ChannelName
[4] = BackLeft
;
1563 device
->RealOut
.ChannelName
[5] = BackRight
;
1564 device
->RealOut
.ChannelName
[6] = SideLeft
;
1565 device
->RealOut
.ChannelName
[7] = SideRight
;
1568 device
->RealOut
.ChannelName
[0] = Aux0
;
1569 if(device
->AmbiOrder
> 0)
1571 device
->RealOut
.ChannelName
[1] = Aux1
;
1572 device
->RealOut
.ChannelName
[2] = Aux2
;
1573 device
->RealOut
.ChannelName
[3] = Aux3
;
1575 if(device
->AmbiOrder
> 1)
1577 device
->RealOut
.ChannelName
[4] = Aux4
;
1578 device
->RealOut
.ChannelName
[5] = Aux5
;
1579 device
->RealOut
.ChannelName
[6] = Aux6
;
1580 device
->RealOut
.ChannelName
[7] = Aux7
;
1581 device
->RealOut
.ChannelName
[8] = Aux8
;
1583 if(device
->AmbiOrder
> 2)
1585 device
->RealOut
.ChannelName
[9] = Aux9
;
1586 device
->RealOut
.ChannelName
[10] = Aux10
;
1587 device
->RealOut
.ChannelName
[11] = Aux11
;
1588 device
->RealOut
.ChannelName
[12] = Aux12
;
1589 device
->RealOut
.ChannelName
[13] = Aux13
;
1590 device
->RealOut
.ChannelName
[14] = Aux14
;
1591 device
->RealOut
.ChannelName
[15] = Aux15
;
1597 /* SetDefaultChannelOrder
1599 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1601 void SetDefaultChannelOrder(ALCdevice
*device
)
1605 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1606 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1608 switch(device
->FmtChans
)
1611 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1612 device
->RealOut
.ChannelName
[1] = FrontRight
;
1613 device
->RealOut
.ChannelName
[2] = BackLeft
;
1614 device
->RealOut
.ChannelName
[3] = BackRight
;
1615 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1616 device
->RealOut
.ChannelName
[5] = LFE
;
1619 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1620 device
->RealOut
.ChannelName
[1] = FrontRight
;
1621 device
->RealOut
.ChannelName
[2] = BackLeft
;
1622 device
->RealOut
.ChannelName
[3] = BackRight
;
1623 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1624 device
->RealOut
.ChannelName
[5] = LFE
;
1625 device
->RealOut
.ChannelName
[6] = SideLeft
;
1626 device
->RealOut
.ChannelName
[7] = SideRight
;
1629 /* Same as WFX order */
1636 SetDefaultWFXChannelOrder(device
);
1641 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1644 /* ALCcontext_DeferUpdates
1646 * Defers/suspends updates for the given context's listener and sources. This
1647 * does *NOT* stop mixing, but rather prevents certain property changes from
1650 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1652 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1655 /* ALCcontext_ProcessUpdates
1657 * Resumes update processing after being deferred.
1659 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1661 ReadLock(&context
->PropLock
);
1662 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1664 /* Tell the mixer to stop applying updates, then wait for any active
1665 * updating to finish, before providing updates.
1667 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1668 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1671 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1672 UpdateContextProps(context
);
1673 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1674 UpdateListenerProps(context
);
1675 UpdateAllEffectSlotProps(context
);
1676 UpdateAllSourceProps(context
);
1678 /* Now with all updates declared, let the mixer continue applying them
1679 * so they all happen at once.
1681 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1683 ReadUnlock(&context
->PropLock
);
1689 * Stores the latest ALC device error
1691 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1693 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1697 /* DebugBreak() will cause an exception if there is no debugger */
1698 if(IsDebuggerPresent())
1700 #elif defined(SIGTRAP)
1706 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1708 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1712 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1714 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1715 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1720 * Updates the device's base clock time with however many samples have been
1721 * done. This is used so frequency changes on the device don't cause the time
1722 * to jump forward or back. Must not be called while the device is running/
1725 static inline void UpdateClockBase(ALCdevice
*device
)
1727 IncrementRef(&device
->MixCount
);
1728 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1729 device
->SamplesDone
= 0;
1730 IncrementRef(&device
->MixCount
);
1733 /* UpdateDeviceParams
1735 * Updates device parameters according to the attribute list (caller is
1736 * responsible for holding the list lock).
1738 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1740 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1741 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1742 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1743 const ALsizei old_sends
= device
->NumAuxSends
;
1744 ALsizei new_sends
= device
->NumAuxSends
;
1745 enum DevFmtChannels oldChans
;
1746 enum DevFmtType oldType
;
1747 ALboolean update_failed
;
1748 ALCsizei hrtf_id
= -1;
1749 ALCcontext
*context
;
1755 // Check for attributes
1756 if(device
->Type
== Loopback
)
1758 ALCsizei numMono
, numStereo
, numSends
;
1759 ALCenum alayout
= AL_NONE
;
1760 ALCenum ascale
= AL_NONE
;
1761 ALCenum schans
= AL_NONE
;
1762 ALCenum stype
= AL_NONE
;
1763 ALCsizei attrIdx
= 0;
1764 ALCsizei aorder
= 0;
1769 WARN("Missing attributes for loopback device\n");
1770 return ALC_INVALID_VALUE
;
1773 numMono
= device
->NumMonoSources
;
1774 numStereo
= device
->NumStereoSources
;
1775 numSends
= old_sends
;
1777 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1778 while(attrList
[attrIdx
])
1780 switch(attrList
[attrIdx
])
1782 case ALC_FORMAT_CHANNELS_SOFT
:
1783 schans
= attrList
[attrIdx
+ 1];
1784 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1785 if(!IsValidALCChannels(schans
))
1786 return ALC_INVALID_VALUE
;
1789 case ALC_FORMAT_TYPE_SOFT
:
1790 stype
= attrList
[attrIdx
+ 1];
1791 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1792 if(!IsValidALCType(stype
))
1793 return ALC_INVALID_VALUE
;
1797 freq
= attrList
[attrIdx
+ 1];
1798 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1799 if(freq
< MIN_OUTPUT_RATE
)
1800 return ALC_INVALID_VALUE
;
1803 case ALC_AMBISONIC_LAYOUT_SOFT
:
1804 alayout
= attrList
[attrIdx
+ 1];
1805 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1806 if(!IsValidAmbiLayout(alayout
))
1807 return ALC_INVALID_VALUE
;
1810 case ALC_AMBISONIC_SCALING_SOFT
:
1811 ascale
= attrList
[attrIdx
+ 1];
1812 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1813 if(!IsValidAmbiScaling(ascale
))
1814 return ALC_INVALID_VALUE
;
1817 case ALC_AMBISONIC_ORDER_SOFT
:
1818 aorder
= attrList
[attrIdx
+ 1];
1819 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1820 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1821 return ALC_INVALID_VALUE
;
1824 case ALC_MONO_SOURCES
:
1825 numMono
= attrList
[attrIdx
+ 1];
1826 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1827 numMono
= maxi(numMono
, 0);
1830 case ALC_STEREO_SOURCES
:
1831 numStereo
= attrList
[attrIdx
+ 1];
1832 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1833 numStereo
= maxi(numStereo
, 0);
1836 case ALC_MAX_AUXILIARY_SENDS
:
1837 numSends
= attrList
[attrIdx
+ 1];
1838 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1839 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1843 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1844 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1845 hrtf_appreq
= Hrtf_Disable
;
1846 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1847 hrtf_appreq
= Hrtf_Enable
;
1849 hrtf_appreq
= Hrtf_Default
;
1852 case ALC_HRTF_ID_SOFT
:
1853 hrtf_id
= attrList
[attrIdx
+ 1];
1854 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1857 case ALC_OUTPUT_LIMITER_SOFT
:
1858 gainLimiter
= attrList
[attrIdx
+ 1];
1859 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1863 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1864 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1872 if(!schans
|| !stype
|| !freq
)
1874 WARN("Missing format for loopback device\n");
1875 return ALC_INVALID_VALUE
;
1877 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1879 WARN("Missing ambisonic info for loopback device\n");
1880 return ALC_INVALID_VALUE
;
1883 if((device
->Flags
&DEVICE_RUNNING
))
1884 V0(device
->Backend
,stop
)();
1885 device
->Flags
&= ~DEVICE_RUNNING
;
1887 UpdateClockBase(device
);
1889 device
->Frequency
= freq
;
1890 device
->FmtChans
= schans
;
1891 device
->FmtType
= stype
;
1892 if(schans
== ALC_BFORMAT3D_SOFT
)
1894 device
->AmbiOrder
= aorder
;
1895 device
->AmbiLayout
= alayout
;
1896 device
->AmbiScale
= ascale
;
1899 if(numMono
> INT_MAX
-numStereo
)
1900 numMono
= INT_MAX
-numStereo
;
1901 numMono
+= numStereo
;
1902 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1908 numMono
= maxi(numMono
, 256);
1909 numStereo
= mini(numStereo
, numMono
);
1910 numMono
-= numStereo
;
1911 device
->SourcesMax
= numMono
+ numStereo
;
1913 device
->NumMonoSources
= numMono
;
1914 device
->NumStereoSources
= numStereo
;
1916 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1917 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1919 new_sends
= numSends
;
1921 else if(attrList
&& attrList
[0])
1923 ALCsizei numMono
, numStereo
, numSends
;
1924 ALCsizei attrIdx
= 0;
1927 /* If a context is already running on the device, stop playback so the
1928 * device attributes can be updated. */
1929 if((device
->Flags
&DEVICE_RUNNING
))
1930 V0(device
->Backend
,stop
)();
1931 device
->Flags
&= ~DEVICE_RUNNING
;
1933 UpdateClockBase(device
);
1935 freq
= device
->Frequency
;
1936 numMono
= device
->NumMonoSources
;
1937 numStereo
= device
->NumStereoSources
;
1938 numSends
= old_sends
;
1940 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1941 while(attrList
[attrIdx
])
1943 switch(attrList
[attrIdx
])
1946 freq
= attrList
[attrIdx
+ 1];
1947 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1948 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1951 case ALC_MONO_SOURCES
:
1952 numMono
= attrList
[attrIdx
+ 1];
1953 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1954 numMono
= maxi(numMono
, 0);
1957 case ALC_STEREO_SOURCES
:
1958 numStereo
= attrList
[attrIdx
+ 1];
1959 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1960 numStereo
= maxi(numStereo
, 0);
1963 case ALC_MAX_AUXILIARY_SENDS
:
1964 numSends
= attrList
[attrIdx
+ 1];
1965 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1966 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1970 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1971 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1972 hrtf_appreq
= Hrtf_Disable
;
1973 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1974 hrtf_appreq
= Hrtf_Enable
;
1976 hrtf_appreq
= Hrtf_Default
;
1979 case ALC_HRTF_ID_SOFT
:
1980 hrtf_id
= attrList
[attrIdx
+ 1];
1981 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1984 case ALC_OUTPUT_LIMITER_SOFT
:
1985 gainLimiter
= attrList
[attrIdx
+ 1];
1986 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1990 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1991 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1999 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2000 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2002 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2004 /* SSE and Neon do best with the update size being a multiple of 4 */
2005 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2006 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2008 device
->Frequency
= freq
;
2010 if(numMono
> INT_MAX
-numStereo
)
2011 numMono
= INT_MAX
-numStereo
;
2012 numMono
+= numStereo
;
2013 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2019 numMono
= maxi(numMono
, 256);
2020 numStereo
= mini(numStereo
, numMono
);
2021 numMono
-= numStereo
;
2022 device
->SourcesMax
= numMono
+ numStereo
;
2024 device
->NumMonoSources
= numMono
;
2025 device
->NumStereoSources
= numStereo
;
2027 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2028 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2030 new_sends
= numSends
;
2033 if((device
->Flags
&DEVICE_RUNNING
))
2034 return ALC_NO_ERROR
;
2036 al_free(device
->Uhj_Encoder
);
2037 device
->Uhj_Encoder
= NULL
;
2039 al_free(device
->Bs2b
);
2040 device
->Bs2b
= NULL
;
2042 al_free(device
->ChannelDelay
[0].Buffer
);
2043 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2045 device
->ChannelDelay
[i
].Length
= 0;
2046 device
->ChannelDelay
[i
].Buffer
= NULL
;
2049 al_free(device
->Dry
.Buffer
);
2050 device
->Dry
.Buffer
= NULL
;
2051 device
->Dry
.NumChannels
= 0;
2052 device
->FOAOut
.Buffer
= NULL
;
2053 device
->FOAOut
.NumChannels
= 0;
2054 device
->RealOut
.Buffer
= NULL
;
2055 device
->RealOut
.NumChannels
= 0;
2057 UpdateClockBase(device
);
2059 device
->DitherSeed
= DITHER_RNG_SEED
;
2061 /*************************************************************************
2062 * Update device format request if HRTF is requested
2064 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2065 if(device
->Type
!= Loopback
)
2068 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2070 if(strcasecmp(hrtf
, "true") == 0)
2071 hrtf_userreq
= Hrtf_Enable
;
2072 else if(strcasecmp(hrtf
, "false") == 0)
2073 hrtf_userreq
= Hrtf_Disable
;
2074 else if(strcasecmp(hrtf
, "auto") != 0)
2075 ERR("Unexpected hrtf value: %s\n", hrtf
);
2078 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2080 struct Hrtf
*hrtf
= NULL
;
2081 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2083 VECTOR_DEINIT(device
->HrtfList
);
2084 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2086 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2088 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2089 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2091 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2096 device
->FmtChans
= DevFmtStereo
;
2097 device
->Frequency
= hrtf
->sampleRate
;
2098 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2099 if(device
->HrtfHandle
)
2100 Hrtf_DecRef(device
->HrtfHandle
);
2101 device
->HrtfHandle
= hrtf
;
2105 hrtf_userreq
= Hrtf_Default
;
2106 hrtf_appreq
= Hrtf_Disable
;
2107 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2112 oldFreq
= device
->Frequency
;
2113 oldChans
= device
->FmtChans
;
2114 oldType
= device
->FmtType
;
2116 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2117 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2118 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2119 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2120 device
->UpdateSize
, device
->NumUpdates
2123 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2124 return ALC_INVALID_DEVICE
;
2126 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2128 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2129 DevFmtChannelsString(device
->FmtChans
));
2130 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2132 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2134 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2135 DevFmtTypeString(device
->FmtType
));
2136 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2138 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2140 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2141 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2144 if((device
->UpdateSize
&3) != 0)
2146 if((CPUCapFlags
&CPU_CAP_SSE
))
2147 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2148 if((CPUCapFlags
&CPU_CAP_NEON
))
2149 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2152 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2153 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2154 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2157 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2158 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2159 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2161 /* Allocate extra channels for any post-filter output. */
2162 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2163 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2165 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2166 device
->Dry
.Buffer
= al_calloc(16, size
);
2167 if(!device
->Dry
.Buffer
)
2169 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2170 return ALC_INVALID_DEVICE
;
2173 if(device
->RealOut
.NumChannels
!= 0)
2174 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2175 device
->FOAOut
.NumChannels
;
2178 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2179 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2182 if(device
->FOAOut
.NumChannels
!= 0)
2183 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2186 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2187 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2190 device
->NumAuxSends
= new_sends
;
2191 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2192 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2193 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2195 device
->DitherDepth
= 0.0f
;
2196 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2199 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2202 switch(device
->FmtType
)
2220 device
->DitherDepth
= (depth
> 0) ? powf(2.0f
, (ALfloat
)(depth
-1)) : 0.0f
;
2222 if(!(device
->DitherDepth
> 0.0f
))
2223 TRACE("Dithering disabled\n");
2225 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2226 device
->DitherDepth
);
2228 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2229 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2230 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2231 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2234 if(gainLimiter
!= ALC_FALSE
)
2236 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2238 al_free(device
->Limiter
);
2239 device
->Limiter
= CreateDeviceLimiter(device
);
2244 al_free(device
->Limiter
);
2245 device
->Limiter
= NULL
;
2247 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2249 /* Need to delay returning failure until replacement Send arrays have been
2250 * allocated with the appropriate size.
2252 update_failed
= AL_FALSE
;
2254 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2257 struct ALvoiceProps
*vprops
;
2260 if(context
->DefaultSlot
)
2262 ALeffectslot
*slot
= context
->DefaultSlot
;
2263 ALeffectState
*state
= slot
->Effect
.State
;
2265 state
->OutBuffer
= device
->Dry
.Buffer
;
2266 state
->OutChannels
= device
->Dry
.NumChannels
;
2267 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2268 update_failed
= AL_TRUE
;
2270 UpdateEffectSlotProps(slot
, context
);
2273 WriteLock(&context
->PropLock
);
2274 LockUIntMapRead(&context
->EffectSlotMap
);
2275 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2277 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2278 ALeffectState
*state
= slot
->Effect
.State
;
2280 state
->OutBuffer
= device
->Dry
.Buffer
;
2281 state
->OutChannels
= device
->Dry
.NumChannels
;
2282 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2283 update_failed
= AL_TRUE
;
2285 UpdateEffectSlotProps(slot
, context
);
2287 UnlockUIntMapRead(&context
->EffectSlotMap
);
2289 LockUIntMapRead(&context
->SourceMap
);
2290 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2291 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2293 ALsource
*source
= context
->SourceMap
.values
[pos
];
2295 if(old_sends
!= device
->NumAuxSends
)
2297 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2300 memcpy(sends
, source
->Send
,
2301 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2303 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2305 if(source
->Send
[s
].Slot
)
2306 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2307 source
->Send
[s
].Slot
= NULL
;
2309 al_free(source
->Send
);
2310 source
->Send
= sends
;
2311 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2313 source
->Send
[s
].Slot
= NULL
;
2314 source
->Send
[s
].Gain
= 1.0f
;
2315 source
->Send
[s
].GainHF
= 1.0f
;
2316 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2317 source
->Send
[s
].GainLF
= 1.0f
;
2318 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2322 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2325 /* Clear any pre-existing voice property structs, in case the number of
2326 * auxiliary sends is changing. Active sources will have updates
2327 * respecified in UpdateAllSourceProps.
2329 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2332 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2337 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2338 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2340 ALvoice
*voice
= context
->Voices
[pos
];
2342 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2344 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2347 if(device
->AvgSpeakerDist
> 0.0f
)
2349 /* Reinitialize the NFC filters for new parameters. */
2350 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2351 (device
->AvgSpeakerDist
* device
->Frequency
);
2352 for(i
= 0;i
< voice
->NumChannels
;i
++)
2354 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2355 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2356 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2360 UnlockUIntMapRead(&context
->SourceMap
);
2362 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2363 UpdateContextProps(context
);
2364 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2365 UpdateListenerProps(context
);
2366 UpdateAllSourceProps(context
);
2367 WriteUnlock(&context
->PropLock
);
2369 context
= context
->next
;
2373 return ALC_INVALID_DEVICE
;
2375 if(!(device
->Flags
&DEVICE_PAUSED
))
2377 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2378 return ALC_INVALID_DEVICE
;
2379 device
->Flags
|= DEVICE_RUNNING
;
2382 return ALC_NO_ERROR
;
2387 * Frees the device structure, and destroys any objects the app failed to
2388 * delete. Called once there's no more references on the device.
2390 static ALCvoid
FreeDevice(ALCdevice
*device
)
2394 TRACE("%p\n", device
);
2396 V0(device
->Backend
,close
)();
2397 DELETE_OBJ(device
->Backend
);
2398 device
->Backend
= NULL
;
2400 almtx_destroy(&device
->BackendLock
);
2402 if(device
->BufferMap
.size
> 0)
2404 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2405 (device
->BufferMap
.size
==1)?"":"s");
2406 ReleaseALBuffers(device
);
2408 ResetUIntMap(&device
->BufferMap
);
2410 if(device
->EffectMap
.size
> 0)
2412 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2413 (device
->EffectMap
.size
==1)?"":"s");
2414 ReleaseALEffects(device
);
2416 ResetUIntMap(&device
->EffectMap
);
2418 if(device
->FilterMap
.size
> 0)
2420 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2421 (device
->FilterMap
.size
==1)?"":"s");
2422 ReleaseALFilters(device
);
2424 ResetUIntMap(&device
->FilterMap
);
2426 AL_STRING_DEINIT(device
->HrtfName
);
2427 FreeHrtfList(&device
->HrtfList
);
2428 if(device
->HrtfHandle
)
2429 Hrtf_DecRef(device
->HrtfHandle
);
2430 device
->HrtfHandle
= NULL
;
2431 al_free(device
->Hrtf
);
2432 device
->Hrtf
= NULL
;
2434 al_free(device
->Bs2b
);
2435 device
->Bs2b
= NULL
;
2437 al_free(device
->Uhj_Encoder
);
2438 device
->Uhj_Encoder
= NULL
;
2440 bformatdec_free(device
->AmbiDecoder
);
2441 device
->AmbiDecoder
= NULL
;
2443 ambiup_free(device
->AmbiUp
);
2444 device
->AmbiUp
= NULL
;
2446 al_free(device
->Stablizer
);
2447 device
->Stablizer
= NULL
;
2449 al_free(device
->Limiter
);
2450 device
->Limiter
= NULL
;
2452 al_free(device
->ChannelDelay
[0].Buffer
);
2453 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2455 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2456 device
->ChannelDelay
[i
].Length
= 0;
2457 device
->ChannelDelay
[i
].Buffer
= NULL
;
2460 AL_STRING_DEINIT(device
->DeviceName
);
2462 al_free(device
->Dry
.Buffer
);
2463 device
->Dry
.Buffer
= NULL
;
2464 device
->Dry
.NumChannels
= 0;
2465 device
->FOAOut
.Buffer
= NULL
;
2466 device
->FOAOut
.NumChannels
= 0;
2467 device
->RealOut
.Buffer
= NULL
;
2468 device
->RealOut
.NumChannels
= 0;
2474 void ALCdevice_IncRef(ALCdevice
*device
)
2477 ref
= IncrementRef(&device
->ref
);
2478 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2481 void ALCdevice_DecRef(ALCdevice
*device
)
2484 ref
= DecrementRef(&device
->ref
);
2485 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2486 if(ref
== 0) FreeDevice(device
);
2491 * Checks if the device handle is valid, and increments its ref count if so.
2493 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2495 ALCdevice
*tmpDevice
;
2498 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2501 if(tmpDevice
== *device
)
2503 ALCdevice_IncRef(tmpDevice
);
2507 tmpDevice
= tmpDevice
->next
;
2518 * Initializes context fields
2520 static ALvoid
InitContext(ALCcontext
*Context
)
2522 ALlistener
*listener
= Context
->Listener
;
2523 struct ALeffectslotArray
*auxslots
;
2525 //Initialise listener
2526 listener
->Gain
= 1.0f
;
2527 listener
->Position
[0] = 0.0f
;
2528 listener
->Position
[1] = 0.0f
;
2529 listener
->Position
[2] = 0.0f
;
2530 listener
->Velocity
[0] = 0.0f
;
2531 listener
->Velocity
[1] = 0.0f
;
2532 listener
->Velocity
[2] = 0.0f
;
2533 listener
->Forward
[0] = 0.0f
;
2534 listener
->Forward
[1] = 0.0f
;
2535 listener
->Forward
[2] = -1.0f
;
2536 listener
->Up
[0] = 0.0f
;
2537 listener
->Up
[1] = 1.0f
;
2538 listener
->Up
[2] = 0.0f
;
2539 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2541 ATOMIC_INIT(&listener
->Update
, NULL
);
2544 InitRef(&Context
->UpdateCount
, 0);
2545 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2546 Context
->GainBoost
= 1.0f
;
2547 RWLockInit(&Context
->PropLock
);
2548 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2549 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2550 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2552 if(Context
->DefaultSlot
)
2554 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2555 auxslots
->count
= 1;
2556 auxslots
->slot
[0] = Context
->DefaultSlot
;
2560 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2561 auxslots
->count
= 0;
2563 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2566 Context
->DistanceModel
= DefaultDistanceModel
;
2567 Context
->SourceDistanceModel
= AL_FALSE
;
2568 Context
->DopplerFactor
= 1.0f
;
2569 Context
->DopplerVelocity
= 1.0f
;
2570 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2571 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2572 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2573 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2575 ATOMIC_INIT(&Context
->Update
, NULL
);
2576 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2577 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2578 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2579 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2581 Context
->ExtensionList
= alExtList
;
2584 listener
->Params
.Matrix
= IdentityMatrixf
;
2585 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2586 listener
->Params
.Gain
= listener
->Gain
;
2587 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2588 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2589 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2590 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2591 listener
->Params
.MetersPerUnit
;
2592 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2593 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2599 * Cleans up the context, and destroys any remaining objects the app failed to
2600 * delete. Called once there's no more references on the context.
2602 static void FreeContext(ALCcontext
*context
)
2604 ALlistener
*listener
= context
->Listener
;
2605 struct ALeffectslotArray
*auxslots
;
2606 struct ALeffectslotProps
*eprops
;
2607 struct ALlistenerProps
*lprops
;
2608 struct ALcontextProps
*cprops
;
2609 struct ALvoiceProps
*vprops
;
2613 TRACE("%p\n", context
);
2615 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2617 TRACE("Freed unapplied context update %p\n", cprops
);
2622 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2625 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2630 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2632 if(context
->DefaultSlot
)
2634 DeinitEffectSlot(context
->DefaultSlot
);
2635 context
->DefaultSlot
= NULL
;
2638 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2641 if(context
->SourceMap
.size
> 0)
2643 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2644 (context
->SourceMap
.size
==1)?"":"s");
2645 ReleaseALSources(context
);
2647 ResetUIntMap(&context
->SourceMap
);
2650 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2653 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2654 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2659 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2660 if(context
->EffectSlotMap
.size
> 0)
2662 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2663 (context
->EffectSlotMap
.size
==1)?"":"s");
2664 ReleaseALAuxiliaryEffectSlots(context
);
2666 ResetUIntMap(&context
->EffectSlotMap
);
2669 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2672 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2677 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2679 for(i
= 0;i
< context
->VoiceCount
;i
++)
2680 DeinitVoice(context
->Voices
[i
]);
2681 al_free(context
->Voices
);
2682 context
->Voices
= NULL
;
2683 context
->VoiceCount
= 0;
2684 context
->MaxVoices
= 0;
2686 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2688 TRACE("Freed unapplied listener update %p\n", lprops
);
2692 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2695 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2700 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2702 ALCdevice_DecRef(context
->Device
);
2703 context
->Device
= NULL
;
2705 //Invalidate context
2706 memset(context
, 0, sizeof(ALCcontext
));
2712 * Removes the context reference from the given device and removes it from
2713 * being current on the running thread or globally. Returns true if other
2714 * contexts still exist on the device.
2716 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2718 ALCcontext
*origctx
, *newhead
;
2721 if(altss_get(LocalContext
) == context
)
2723 WARN("%p released while current on thread\n", context
);
2724 altss_set(LocalContext
, NULL
);
2725 ALCcontext_DecRef(context
);
2729 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2730 ALCcontext_DecRef(context
);
2732 ALCdevice_Lock(device
);
2734 newhead
= context
->next
;
2735 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2737 ALCcontext
*volatile*list
= &origctx
->next
;
2740 if(*list
== context
)
2742 *list
= (*list
)->next
;
2745 list
= &(*list
)->next
;
2750 ALCdevice_Unlock(device
);
2752 ALCcontext_DecRef(context
);
2756 void ALCcontext_IncRef(ALCcontext
*context
)
2758 uint ref
= IncrementRef(&context
->ref
);
2759 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2762 void ALCcontext_DecRef(ALCcontext
*context
)
2764 uint ref
= DecrementRef(&context
->ref
);
2765 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2766 if(ref
== 0) FreeContext(context
);
2769 static void ReleaseThreadCtx(void *ptr
)
2771 ALCcontext
*context
= ptr
;
2772 uint ref
= DecrementRef(&context
->ref
);
2773 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2774 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2779 * Checks that the given context is valid, and increments its reference count.
2781 static ALCboolean
VerifyContext(ALCcontext
**context
)
2786 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2789 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2794 ALCcontext_IncRef(ctx
);
2811 * Returns the currently active context for this thread, and adds a reference
2812 * without locking it.
2814 ALCcontext
*GetContextRef(void)
2816 ALCcontext
*context
;
2818 context
= altss_get(LocalContext
);
2820 ALCcontext_IncRef(context
);
2824 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2826 ALCcontext_IncRef(context
);
2834 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2836 ALCdevice
*device
= context
->Device
;
2837 ALsizei num_sends
= device
->NumAuxSends
;
2838 struct ALvoiceProps
*props
;
2839 size_t sizeof_props
;
2840 size_t sizeof_voice
;
2846 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2849 /* Allocate the voice pointers, voices, and the voices' stored source
2850 * property set (including the dynamically-sized Send[] array) in one
2853 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2854 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2855 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2857 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2858 /* The voice and property objects are stored interleaved since they're
2861 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2862 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2866 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2867 const ALsizei s_count
= mini(old_sends
, num_sends
);
2869 for(;v
< v_count
;v
++)
2871 ALvoice
*old_voice
= context
->Voices
[v
];
2874 /* Copy the old voice data and source property set to the new
2877 *voice
= *old_voice
;
2878 for(i
= 0;i
< s_count
;i
++)
2879 voice
->Send
[i
] = old_voice
->Send
[i
];
2880 *props
= *(old_voice
->Props
);
2881 for(i
= 0;i
< s_count
;i
++)
2882 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2884 /* Set this voice's property set pointer and voice reference. */
2885 voice
->Props
= props
;
2888 /* Increment pointers to the next storage space. */
2889 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2890 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2892 /* Deinit any left over voices that weren't copied over to the new
2893 * array. NOTE: If this does anything, v equals num_voices and
2894 * num_voices is less than VoiceCount, so the following loop won't do
2897 for(;v
< context
->VoiceCount
;v
++)
2898 DeinitVoice(context
->Voices
[v
]);
2900 /* Finish setting the voices' property set pointers and references. */
2901 for(;v
< num_voices
;v
++)
2903 ATOMIC_INIT(&voice
->Update
, NULL
);
2905 voice
->Props
= props
;
2908 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2909 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2912 al_free(context
->Voices
);
2913 context
->Voices
= voices
;
2914 context
->MaxVoices
= num_voices
;
2915 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2919 /************************************************
2920 * Standard ALC functions
2921 ************************************************/
2925 * Return last ALC generated error code for the given device
2927 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2931 if(VerifyDevice(&device
))
2933 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2934 ALCdevice_DecRef(device
);
2937 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2943 /* alcSuspendContext
2945 * Suspends updates for the given context
2947 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2952 if(!VerifyContext(&context
))
2953 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2956 ALCcontext_DeferUpdates(context
);
2957 ALCcontext_DecRef(context
);
2961 /* alcProcessContext
2963 * Resumes processing updates for the given context
2965 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2970 if(!VerifyContext(&context
))
2971 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2974 ALCcontext_ProcessUpdates(context
);
2975 ALCcontext_DecRef(context
);
2982 * Returns information about the device, and error strings
2984 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2986 const ALCchar
*value
= NULL
;
2994 case ALC_INVALID_ENUM
:
2995 value
= alcErrInvalidEnum
;
2998 case ALC_INVALID_VALUE
:
2999 value
= alcErrInvalidValue
;
3002 case ALC_INVALID_DEVICE
:
3003 value
= alcErrInvalidDevice
;
3006 case ALC_INVALID_CONTEXT
:
3007 value
= alcErrInvalidContext
;
3010 case ALC_OUT_OF_MEMORY
:
3011 value
= alcErrOutOfMemory
;
3014 case ALC_DEVICE_SPECIFIER
:
3015 value
= alcDefaultName
;
3018 case ALC_ALL_DEVICES_SPECIFIER
:
3019 if(VerifyDevice(&Device
))
3021 value
= alstr_get_cstr(Device
->DeviceName
);
3022 ALCdevice_DecRef(Device
);
3026 ProbeAllDevicesList();
3027 value
= alstr_get_cstr(alcAllDevicesList
);
3031 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3032 if(VerifyDevice(&Device
))
3034 value
= alstr_get_cstr(Device
->DeviceName
);
3035 ALCdevice_DecRef(Device
);
3039 ProbeCaptureDeviceList();
3040 value
= alstr_get_cstr(alcCaptureDeviceList
);
3044 /* Default devices are always first in the list */
3045 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3046 value
= alcDefaultName
;
3049 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3050 if(alstr_empty(alcAllDevicesList
))
3051 ProbeAllDevicesList();
3053 VerifyDevice(&Device
);
3055 free(alcDefaultAllDevicesSpecifier
);
3056 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3057 if(!alcDefaultAllDevicesSpecifier
)
3058 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3060 value
= alcDefaultAllDevicesSpecifier
;
3061 if(Device
) ALCdevice_DecRef(Device
);
3064 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3065 if(alstr_empty(alcCaptureDeviceList
))
3066 ProbeCaptureDeviceList();
3068 VerifyDevice(&Device
);
3070 free(alcCaptureDefaultDeviceSpecifier
);
3071 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3072 if(!alcCaptureDefaultDeviceSpecifier
)
3073 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3075 value
= alcCaptureDefaultDeviceSpecifier
;
3076 if(Device
) ALCdevice_DecRef(Device
);
3079 case ALC_EXTENSIONS
:
3080 if(!VerifyDevice(&Device
))
3081 value
= alcNoDeviceExtList
;
3084 value
= alcExtensionList
;
3085 ALCdevice_DecRef(Device
);
3089 case ALC_HRTF_SPECIFIER_SOFT
:
3090 if(!VerifyDevice(&Device
))
3091 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3094 almtx_lock(&Device
->BackendLock
);
3095 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3096 almtx_unlock(&Device
->BackendLock
);
3097 ALCdevice_DecRef(Device
);
3102 VerifyDevice(&Device
);
3103 alcSetError(Device
, ALC_INVALID_ENUM
);
3104 if(Device
) ALCdevice_DecRef(Device
);
3112 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3114 if(device
->Type
== Loopback
&& device
->FmtChans
== DevFmtAmbi3D
)
3119 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3123 if(size
<= 0 || values
== NULL
)
3125 alcSetError(device
, ALC_INVALID_VALUE
);
3133 case ALC_MAJOR_VERSION
:
3134 values
[0] = alcMajorVersion
;
3136 case ALC_MINOR_VERSION
:
3137 values
[0] = alcMinorVersion
;
3140 case ALC_ATTRIBUTES_SIZE
:
3141 case ALC_ALL_ATTRIBUTES
:
3145 case ALC_MONO_SOURCES
:
3146 case ALC_STEREO_SOURCES
:
3147 case ALC_CAPTURE_SAMPLES
:
3148 case ALC_FORMAT_CHANNELS_SOFT
:
3149 case ALC_FORMAT_TYPE_SOFT
:
3150 case ALC_AMBISONIC_LAYOUT_SOFT
:
3151 case ALC_AMBISONIC_SCALING_SOFT
:
3152 case ALC_AMBISONIC_ORDER_SOFT
:
3153 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3154 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3158 alcSetError(NULL
, ALC_INVALID_ENUM
);
3164 if(device
->Type
== Capture
)
3168 case ALC_CAPTURE_SAMPLES
:
3169 almtx_lock(&device
->BackendLock
);
3170 values
[0] = V0(device
->Backend
,availableSamples
)();
3171 almtx_unlock(&device
->BackendLock
);
3175 values
[0] = device
->Connected
;
3179 alcSetError(device
, ALC_INVALID_ENUM
);
3188 case ALC_MAJOR_VERSION
:
3189 values
[0] = alcMajorVersion
;
3192 case ALC_MINOR_VERSION
:
3193 values
[0] = alcMinorVersion
;
3196 case ALC_EFX_MAJOR_VERSION
:
3197 values
[0] = alcEFXMajorVersion
;
3200 case ALC_EFX_MINOR_VERSION
:
3201 values
[0] = alcEFXMinorVersion
;
3204 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3205 values
[0] = MAX_AMBI_ORDER
;
3208 case ALC_ATTRIBUTES_SIZE
:
3209 values
[0] = NumAttrsForDevice(device
);
3212 case ALC_ALL_ATTRIBUTES
:
3213 if(size
< NumAttrsForDevice(device
))
3215 alcSetError(device
, ALC_INVALID_VALUE
);
3220 almtx_lock(&device
->BackendLock
);
3221 values
[i
++] = ALC_FREQUENCY
;
3222 values
[i
++] = device
->Frequency
;
3224 if(device
->Type
!= Loopback
)
3226 values
[i
++] = ALC_REFRESH
;
3227 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3229 values
[i
++] = ALC_SYNC
;
3230 values
[i
++] = ALC_FALSE
;
3234 if(device
->FmtChans
== DevFmtAmbi3D
)
3236 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3237 values
[i
++] = device
->AmbiLayout
;
3239 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3240 values
[i
++] = device
->AmbiScale
;
3242 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3243 values
[i
++] = device
->AmbiOrder
;
3246 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3247 values
[i
++] = device
->FmtChans
;
3249 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3250 values
[i
++] = device
->FmtType
;
3253 values
[i
++] = ALC_MONO_SOURCES
;
3254 values
[i
++] = device
->NumMonoSources
;
3256 values
[i
++] = ALC_STEREO_SOURCES
;
3257 values
[i
++] = device
->NumStereoSources
;
3259 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3260 values
[i
++] = device
->NumAuxSends
;
3262 values
[i
++] = ALC_HRTF_SOFT
;
3263 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3265 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3266 values
[i
++] = device
->HrtfStatus
;
3268 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3269 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3271 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3272 values
[i
++] = MAX_AMBI_ORDER
;
3273 almtx_unlock(&device
->BackendLock
);
3279 values
[0] = device
->Frequency
;
3283 if(device
->Type
== Loopback
)
3285 alcSetError(device
, ALC_INVALID_DEVICE
);
3288 almtx_lock(&device
->BackendLock
);
3289 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3290 almtx_unlock(&device
->BackendLock
);
3294 if(device
->Type
== Loopback
)
3296 alcSetError(device
, ALC_INVALID_DEVICE
);
3299 values
[0] = ALC_FALSE
;
3302 case ALC_FORMAT_CHANNELS_SOFT
:
3303 if(device
->Type
!= Loopback
)
3305 alcSetError(device
, ALC_INVALID_DEVICE
);
3308 values
[0] = device
->FmtChans
;
3311 case ALC_FORMAT_TYPE_SOFT
:
3312 if(device
->Type
!= Loopback
)
3314 alcSetError(device
, ALC_INVALID_DEVICE
);
3317 values
[0] = device
->FmtType
;
3320 case ALC_AMBISONIC_LAYOUT_SOFT
:
3321 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3323 alcSetError(device
, ALC_INVALID_DEVICE
);
3326 values
[0] = device
->AmbiLayout
;
3329 case ALC_AMBISONIC_SCALING_SOFT
:
3330 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3332 alcSetError(device
, ALC_INVALID_DEVICE
);
3335 values
[0] = device
->AmbiScale
;
3338 case ALC_AMBISONIC_ORDER_SOFT
:
3339 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3341 alcSetError(device
, ALC_INVALID_DEVICE
);
3344 values
[0] = device
->AmbiOrder
;
3347 case ALC_MONO_SOURCES
:
3348 values
[0] = device
->NumMonoSources
;
3351 case ALC_STEREO_SOURCES
:
3352 values
[0] = device
->NumStereoSources
;
3355 case ALC_MAX_AUXILIARY_SENDS
:
3356 values
[0] = device
->NumAuxSends
;
3360 values
[0] = device
->Connected
;
3364 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3367 case ALC_HRTF_STATUS_SOFT
:
3368 values
[0] = device
->HrtfStatus
;
3371 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3372 almtx_lock(&device
->BackendLock
);
3373 FreeHrtfList(&device
->HrtfList
);
3374 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3375 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3376 almtx_unlock(&device
->BackendLock
);
3379 case ALC_OUTPUT_LIMITER_SOFT
:
3380 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3384 alcSetError(device
, ALC_INVALID_ENUM
);
3392 * Returns information about the device and the version of OpenAL
3394 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3396 VerifyDevice(&device
);
3397 if(size
<= 0 || values
== NULL
)
3398 alcSetError(device
, ALC_INVALID_VALUE
);
3400 GetIntegerv(device
, param
, size
, values
);
3401 if(device
) ALCdevice_DecRef(device
);
3404 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3409 VerifyDevice(&device
);
3410 if(size
<= 0 || values
== NULL
)
3411 alcSetError(device
, ALC_INVALID_VALUE
);
3412 else if(!device
|| device
->Type
== Capture
)
3414 ivals
= malloc(size
* sizeof(ALCint
));
3415 size
= GetIntegerv(device
, pname
, size
, ivals
);
3416 for(i
= 0;i
< size
;i
++)
3417 values
[i
] = ivals
[i
];
3420 else /* render device */
3429 case ALC_ATTRIBUTES_SIZE
:
3430 *values
= NumAttrsForDevice(device
)+4;
3433 case ALC_ALL_ATTRIBUTES
:
3434 if(size
< NumAttrsForDevice(device
)+4)
3435 alcSetError(device
, ALC_INVALID_VALUE
);
3439 almtx_lock(&device
->BackendLock
);
3440 values
[i
++] = ALC_FREQUENCY
;
3441 values
[i
++] = device
->Frequency
;
3443 if(device
->Type
!= Loopback
)
3445 values
[i
++] = ALC_REFRESH
;
3446 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3448 values
[i
++] = ALC_SYNC
;
3449 values
[i
++] = ALC_FALSE
;
3453 if(device
->FmtChans
== DevFmtAmbi3D
)
3455 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3456 values
[i
++] = device
->AmbiLayout
;
3458 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3459 values
[i
++] = device
->AmbiScale
;
3461 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3462 values
[i
++] = device
->AmbiOrder
;
3465 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3466 values
[i
++] = device
->FmtChans
;
3468 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3469 values
[i
++] = device
->FmtType
;
3472 values
[i
++] = ALC_MONO_SOURCES
;
3473 values
[i
++] = device
->NumMonoSources
;
3475 values
[i
++] = ALC_STEREO_SOURCES
;
3476 values
[i
++] = device
->NumStereoSources
;
3478 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3479 values
[i
++] = device
->NumAuxSends
;
3481 values
[i
++] = ALC_HRTF_SOFT
;
3482 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3484 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3485 values
[i
++] = device
->HrtfStatus
;
3487 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3488 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3490 clock
= V0(device
->Backend
,getClockLatency
)();
3491 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3492 values
[i
++] = clock
.ClockTime
;
3494 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3495 values
[i
++] = clock
.Latency
;
3496 almtx_unlock(&device
->BackendLock
);
3502 case ALC_DEVICE_CLOCK_SOFT
:
3503 almtx_lock(&device
->BackendLock
);
3505 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3507 basecount
= device
->ClockBase
;
3508 samplecount
= device
->SamplesDone
;
3509 } while(refcount
!= ReadRef(&device
->MixCount
));
3510 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3511 almtx_unlock(&device
->BackendLock
);
3514 case ALC_DEVICE_LATENCY_SOFT
:
3515 almtx_lock(&device
->BackendLock
);
3516 clock
= V0(device
->Backend
,getClockLatency
)();
3517 almtx_unlock(&device
->BackendLock
);
3518 *values
= clock
.Latency
;
3521 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3523 alcSetError(device
, ALC_INVALID_VALUE
);
3526 almtx_lock(&device
->BackendLock
);
3527 clock
= V0(device
->Backend
,getClockLatency
)();
3528 almtx_unlock(&device
->BackendLock
);
3529 values
[0] = clock
.ClockTime
;
3530 values
[1] = clock
.Latency
;
3535 ivals
= malloc(size
* sizeof(ALCint
));
3536 size
= GetIntegerv(device
, pname
, size
, ivals
);
3537 for(i
= 0;i
< size
;i
++)
3538 values
[i
] = ivals
[i
];
3544 ALCdevice_DecRef(device
);
3548 /* alcIsExtensionPresent
3550 * Determines if there is support for a particular extension
3552 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3554 ALCboolean bResult
= ALC_FALSE
;
3556 VerifyDevice(&device
);
3559 alcSetError(device
, ALC_INVALID_VALUE
);
3562 size_t len
= strlen(extName
);
3563 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3566 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3567 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3572 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3576 } while(isspace(*ptr
));
3581 ALCdevice_DecRef(device
);
3586 /* alcGetProcAddress
3588 * Retrieves the function address for a particular extension function
3590 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3592 ALCvoid
*ptr
= NULL
;
3596 VerifyDevice(&device
);
3597 alcSetError(device
, ALC_INVALID_VALUE
);
3598 if(device
) ALCdevice_DecRef(device
);
3603 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3605 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3607 ptr
= alcFunctions
[i
].address
;
3619 * Get the value for a particular ALC enumeration name
3621 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3627 VerifyDevice(&device
);
3628 alcSetError(device
, ALC_INVALID_VALUE
);
3629 if(device
) ALCdevice_DecRef(device
);
3634 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3636 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3638 val
= alcEnumerations
[i
].value
;
3650 * Create and attach a context to the given device.
3652 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3654 ALCcontext
*ALContext
;
3658 /* Explicitly hold the list lock while taking the BackendLock in case the
3659 * device is asynchronously destropyed, to ensure this new context is
3660 * properly cleaned up after being made.
3663 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3666 alcSetError(device
, ALC_INVALID_DEVICE
);
3667 if(device
) ALCdevice_DecRef(device
);
3670 almtx_lock(&device
->BackendLock
);
3673 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3675 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3676 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3678 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3681 almtx_unlock(&device
->BackendLock
);
3683 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3684 ALCdevice_DecRef(device
);
3688 InitRef(&ALContext
->ref
, 1);
3689 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3690 ALContext
->DefaultSlot
= NULL
;
3692 ALContext
->Voices
= NULL
;
3693 ALContext
->VoiceCount
= 0;
3694 ALContext
->MaxVoices
= 0;
3695 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3696 ALContext
->Device
= device
;
3698 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3700 almtx_unlock(&device
->BackendLock
);
3705 alcSetError(device
, err
);
3706 if(err
== ALC_INVALID_DEVICE
)
3708 V0(device
->Backend
,lock
)();
3709 aluHandleDisconnect(device
);
3710 V0(device
->Backend
,unlock
)();
3712 ALCdevice_DecRef(device
);
3715 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3717 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3719 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3720 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3721 aluInitEffectPanning(ALContext
->DefaultSlot
);
3724 ALContext
->DefaultSlot
= NULL
;
3725 ERR("Failed to initialize the default effect slot\n");
3729 ALCdevice_IncRef(ALContext
->Device
);
3730 InitContext(ALContext
);
3732 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3735 ERR("volume-adjust must be finite: %f\n", valf
);
3738 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3740 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3741 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3742 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3745 UpdateListenerProps(ALContext
);
3748 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3750 ALContext
->next
= head
;
3751 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3754 almtx_unlock(&device
->BackendLock
);
3756 if(ALContext
->DefaultSlot
)
3758 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3759 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3761 ERR("Failed to initialize the default effect\n");
3764 ALCdevice_DecRef(device
);
3766 TRACE("Created context %p\n", ALContext
);
3770 /* alcDestroyContext
3772 * Remove a context from its device
3774 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3779 if(!VerifyContext(&context
))
3782 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3786 Device
= context
->Device
;
3789 almtx_lock(&Device
->BackendLock
);
3790 if(!ReleaseContext(context
, Device
))
3792 V0(Device
->Backend
,stop
)();
3793 Device
->Flags
&= ~DEVICE_RUNNING
;
3795 almtx_unlock(&Device
->BackendLock
);
3799 ALCcontext_DecRef(context
);
3803 /* alcGetCurrentContext
3805 * Returns the currently active context on the calling thread
3807 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3809 ALCcontext
*Context
= altss_get(LocalContext
);
3810 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3814 /* alcGetThreadContext
3816 * Returns the currently active thread-local context
3818 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3820 return altss_get(LocalContext
);
3824 /* alcMakeContextCurrent
3826 * Makes the given context the active process-wide context, and removes the
3827 * thread-local context for the calling thread.
3829 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3831 /* context must be valid or NULL */
3832 if(context
&& !VerifyContext(&context
))
3834 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3837 /* context's reference count is already incremented */
3838 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3839 if(context
) ALCcontext_DecRef(context
);
3841 if((context
=altss_get(LocalContext
)) != NULL
)
3843 altss_set(LocalContext
, NULL
);
3844 ALCcontext_DecRef(context
);
3850 /* alcSetThreadContext
3852 * Makes the given context the active context for the current thread
3854 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3858 /* context must be valid or NULL */
3859 if(context
&& !VerifyContext(&context
))
3861 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3864 /* context's reference count is already incremented */
3865 old
= altss_get(LocalContext
);
3866 altss_set(LocalContext
, context
);
3867 if(old
) ALCcontext_DecRef(old
);
3873 /* alcGetContextsDevice
3875 * Returns the device that a particular context is attached to
3877 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3881 if(!VerifyContext(&Context
))
3883 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3886 Device
= Context
->Device
;
3887 ALCcontext_DecRef(Context
);
3895 * Opens the named device.
3897 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3899 ALCbackendFactory
*factory
;
3907 if(!PlaybackBackend
.name
)
3909 alcSetError(NULL
, ALC_INVALID_VALUE
);
3913 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3915 /* Some old Windows apps hardcode these expecting OpenAL to use a
3916 * specific audio API, even when they're not enumerated. Creative's
3917 * router effectively ignores them too.
3919 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3920 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3925 device
= al_calloc(16, sizeof(ALCdevice
));
3928 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3933 InitRef(&device
->ref
, 1);
3934 device
->Connected
= ALC_TRUE
;
3935 device
->Type
= Playback
;
3936 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3939 device
->Bs2b
= NULL
;
3940 device
->Uhj_Encoder
= NULL
;
3941 device
->Hrtf
= NULL
;
3942 device
->HrtfHandle
= NULL
;
3943 VECTOR_INIT(device
->HrtfList
);
3944 AL_STRING_INIT(device
->HrtfName
);
3945 device
->Render_Mode
= NormalRender
;
3946 AL_STRING_INIT(device
->DeviceName
);
3947 device
->Dry
.Buffer
= NULL
;
3948 device
->Dry
.NumChannels
= 0;
3949 device
->FOAOut
.Buffer
= NULL
;
3950 device
->FOAOut
.NumChannels
= 0;
3951 device
->RealOut
.Buffer
= NULL
;
3952 device
->RealOut
.NumChannels
= 0;
3953 device
->Limiter
= NULL
;
3954 device
->AvgSpeakerDist
= 0.0f
;
3956 ATOMIC_INIT(&device
->ContextList
, NULL
);
3958 device
->ClockBase
= 0;
3959 device
->SamplesDone
= 0;
3961 device
->SourcesMax
= 256;
3962 device
->AuxiliaryEffectSlotMax
= 64;
3963 device
->NumAuxSends
= DEFAULT_SENDS
;
3965 InitUIntMap(&device
->BufferMap
, INT_MAX
);
3966 InitUIntMap(&device
->EffectMap
, INT_MAX
);
3967 InitUIntMap(&device
->FilterMap
, INT_MAX
);
3969 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3971 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3972 device
->ChannelDelay
[i
].Length
= 0;
3973 device
->ChannelDelay
[i
].Buffer
= NULL
;
3977 device
->FmtChans
= DevFmtChannelsDefault
;
3978 device
->FmtType
= DevFmtTypeDefault
;
3979 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3980 device
->IsHeadphones
= AL_FALSE
;
3981 device
->AmbiLayout
= AmbiLayout_Default
;
3982 device
->AmbiScale
= AmbiNorm_Default
;
3983 device
->NumUpdates
= 3;
3984 device
->UpdateSize
= 1024;
3986 factory
= PlaybackBackend
.getFactory();
3987 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3988 if(!device
->Backend
)
3991 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3996 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3998 static const struct {
3999 const char name
[16];
4000 enum DevFmtChannels chans
;
4003 { "mono", DevFmtMono
, 0 },
4004 { "stereo", DevFmtStereo
, 0 },
4005 { "quad", DevFmtQuad
, 0 },
4006 { "surround51", DevFmtX51
, 0 },
4007 { "surround61", DevFmtX61
, 0 },
4008 { "surround71", DevFmtX71
, 0 },
4009 { "surround51rear", DevFmtX51Rear
, 0 },
4010 { "ambi1", DevFmtAmbi3D
, 1 },
4011 { "ambi2", DevFmtAmbi3D
, 2 },
4012 { "ambi3", DevFmtAmbi3D
, 3 },
4016 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4018 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4020 device
->FmtChans
= chanlist
[i
].chans
;
4021 device
->AmbiOrder
= chanlist
[i
].order
;
4022 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4026 if(i
== COUNTOF(chanlist
))
4027 ERR("Unsupported channels: %s\n", fmt
);
4029 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4031 static const struct {
4032 const char name
[16];
4033 enum DevFmtType type
;
4035 { "int8", DevFmtByte
},
4036 { "uint8", DevFmtUByte
},
4037 { "int16", DevFmtShort
},
4038 { "uint16", DevFmtUShort
},
4039 { "int32", DevFmtInt
},
4040 { "uint32", DevFmtUInt
},
4041 { "float32", DevFmtFloat
},
4045 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4047 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4049 device
->FmtType
= typelist
[i
].type
;
4050 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4054 if(i
== COUNTOF(typelist
))
4055 ERR("Unsupported sample-type: %s\n", fmt
);
4058 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4060 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4061 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4062 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4063 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4066 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4067 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4069 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4070 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4071 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4072 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4074 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4075 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4077 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4078 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4080 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4081 device
->NumAuxSends
= clampi(
4082 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4085 device
->NumStereoSources
= 1;
4086 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4088 // Find a playback device to open
4089 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4091 DELETE_OBJ(device
->Backend
);
4093 alcSetError(NULL
, err
);
4096 almtx_init(&device
->BackendLock
, almtx_plain
);
4098 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4100 if(strcasecmp(fmt
, "fuma") == 0)
4102 device
->AmbiLayout
= AmbiLayout_FuMa
;
4103 device
->AmbiScale
= AmbiNorm_FuMa
;
4105 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4107 device
->AmbiLayout
= AmbiLayout_ACN
;
4108 device
->AmbiScale
= AmbiNorm_SN3D
;
4110 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4112 device
->AmbiLayout
= AmbiLayout_ACN
;
4113 device
->AmbiScale
= AmbiNorm_N3D
;
4116 ERR("Unsupported ambi-format: %s\n", fmt
);
4119 device
->Limiter
= CreateDeviceLimiter(device
);
4122 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4124 device
->next
= head
;
4125 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4128 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4134 * Closes the given device.
4136 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4138 ALCdevice
*iter
, *origdev
;
4142 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4146 } while((iter
=iter
->next
) != NULL
);
4147 if(!iter
|| iter
->Type
== Capture
)
4149 alcSetError(iter
, ALC_INVALID_DEVICE
);
4153 almtx_lock(&device
->BackendLock
);
4156 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4158 ALCdevice
*volatile*list
= &origdev
->next
;
4163 *list
= (*list
)->next
;
4166 list
= &(*list
)->next
;
4171 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4174 ALCcontext
*next
= ctx
->next
;
4175 WARN("Releasing context %p\n", ctx
);
4176 ReleaseContext(ctx
, device
);
4179 if((device
->Flags
&DEVICE_RUNNING
))
4180 V0(device
->Backend
,stop
)();
4181 device
->Flags
&= ~DEVICE_RUNNING
;
4182 almtx_unlock(&device
->BackendLock
);
4184 ALCdevice_DecRef(device
);
4190 /************************************************
4191 * ALC capture functions
4192 ************************************************/
4193 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4195 ALCbackendFactory
*factory
;
4196 ALCdevice
*device
= NULL
;
4202 if(!CaptureBackend
.name
)
4204 alcSetError(NULL
, ALC_INVALID_VALUE
);
4210 alcSetError(NULL
, ALC_INVALID_VALUE
);
4214 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4217 device
= al_calloc(16, sizeof(ALCdevice
));
4220 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4225 InitRef(&device
->ref
, 1);
4226 device
->Connected
= ALC_TRUE
;
4227 device
->Type
= Capture
;
4229 device
->Hrtf
= NULL
;
4230 device
->HrtfHandle
= NULL
;
4231 VECTOR_INIT(device
->HrtfList
);
4232 AL_STRING_INIT(device
->HrtfName
);
4234 AL_STRING_INIT(device
->DeviceName
);
4235 device
->Dry
.Buffer
= NULL
;
4236 device
->Dry
.NumChannels
= 0;
4237 device
->FOAOut
.Buffer
= NULL
;
4238 device
->FOAOut
.NumChannels
= 0;
4239 device
->RealOut
.Buffer
= NULL
;
4240 device
->RealOut
.NumChannels
= 0;
4242 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4243 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4244 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4246 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4248 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4249 device
->ChannelDelay
[i
].Length
= 0;
4250 device
->ChannelDelay
[i
].Buffer
= NULL
;
4253 factory
= CaptureBackend
.getFactory();
4254 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4255 if(!device
->Backend
)
4258 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4262 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4263 device
->Frequency
= frequency
;
4265 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4266 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4269 alcSetError(NULL
, ALC_INVALID_ENUM
);
4272 device
->IsHeadphones
= AL_FALSE
;
4273 device
->AmbiOrder
= 0;
4274 device
->AmbiLayout
= AmbiLayout_Default
;
4275 device
->AmbiScale
= AmbiNorm_Default
;
4277 device
->UpdateSize
= samples
;
4278 device
->NumUpdates
= 1;
4280 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4281 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4282 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4284 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4287 alcSetError(NULL
, err
);
4290 almtx_init(&device
->BackendLock
, almtx_plain
);
4293 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4295 device
->next
= head
;
4296 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4299 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4303 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4305 ALCdevice
*iter
, *origdev
;
4308 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4312 } while((iter
=iter
->next
) != NULL
);
4313 if(!iter
|| iter
->Type
!= Capture
)
4315 alcSetError(iter
, ALC_INVALID_DEVICE
);
4321 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4323 ALCdevice
*volatile*list
= &origdev
->next
;
4328 *list
= (*list
)->next
;
4331 list
= &(*list
)->next
;
4336 ALCdevice_DecRef(device
);
4341 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4343 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4344 alcSetError(device
, ALC_INVALID_DEVICE
);
4347 almtx_lock(&device
->BackendLock
);
4348 if(!device
->Connected
)
4349 alcSetError(device
, ALC_INVALID_DEVICE
);
4350 else if(!(device
->Flags
&DEVICE_RUNNING
))
4352 if(V0(device
->Backend
,start
)())
4353 device
->Flags
|= DEVICE_RUNNING
;
4356 aluHandleDisconnect(device
);
4357 alcSetError(device
, ALC_INVALID_DEVICE
);
4360 almtx_unlock(&device
->BackendLock
);
4363 if(device
) ALCdevice_DecRef(device
);
4366 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4368 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4369 alcSetError(device
, ALC_INVALID_DEVICE
);
4372 almtx_lock(&device
->BackendLock
);
4373 if((device
->Flags
&DEVICE_RUNNING
))
4374 V0(device
->Backend
,stop
)();
4375 device
->Flags
&= ~DEVICE_RUNNING
;
4376 almtx_unlock(&device
->BackendLock
);
4379 if(device
) ALCdevice_DecRef(device
);
4382 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4384 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4385 alcSetError(device
, ALC_INVALID_DEVICE
);
4388 ALCenum err
= ALC_INVALID_VALUE
;
4390 almtx_lock(&device
->BackendLock
);
4391 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4392 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4393 almtx_unlock(&device
->BackendLock
);
4395 if(err
!= ALC_NO_ERROR
)
4396 alcSetError(device
, err
);
4398 if(device
) ALCdevice_DecRef(device
);
4402 /************************************************
4403 * ALC loopback functions
4404 ************************************************/
4406 /* alcLoopbackOpenDeviceSOFT
4408 * Open a loopback device, for manual rendering.
4410 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4412 ALCbackendFactory
*factory
;
4418 /* Make sure the device name, if specified, is us. */
4419 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4421 alcSetError(NULL
, ALC_INVALID_VALUE
);
4425 device
= al_calloc(16, sizeof(ALCdevice
));
4428 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4433 InitRef(&device
->ref
, 1);
4434 device
->Connected
= ALC_TRUE
;
4435 device
->Type
= Loopback
;
4436 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4439 device
->Hrtf
= NULL
;
4440 device
->HrtfHandle
= NULL
;
4441 VECTOR_INIT(device
->HrtfList
);
4442 AL_STRING_INIT(device
->HrtfName
);
4443 device
->Bs2b
= NULL
;
4444 device
->Uhj_Encoder
= NULL
;
4445 device
->Render_Mode
= NormalRender
;
4446 AL_STRING_INIT(device
->DeviceName
);
4447 device
->Dry
.Buffer
= NULL
;
4448 device
->Dry
.NumChannels
= 0;
4449 device
->FOAOut
.Buffer
= NULL
;
4450 device
->FOAOut
.NumChannels
= 0;
4451 device
->RealOut
.Buffer
= NULL
;
4452 device
->RealOut
.NumChannels
= 0;
4453 device
->Limiter
= NULL
;
4454 device
->AvgSpeakerDist
= 0.0f
;
4456 ATOMIC_INIT(&device
->ContextList
, NULL
);
4458 device
->ClockBase
= 0;
4459 device
->SamplesDone
= 0;
4461 device
->SourcesMax
= 256;
4462 device
->AuxiliaryEffectSlotMax
= 64;
4463 device
->NumAuxSends
= DEFAULT_SENDS
;
4465 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4466 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4467 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4469 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4471 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4472 device
->ChannelDelay
[i
].Length
= 0;
4473 device
->ChannelDelay
[i
].Buffer
= NULL
;
4476 factory
= ALCloopbackFactory_getFactory();
4477 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4478 if(!device
->Backend
)
4481 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4484 almtx_init(&device
->BackendLock
, almtx_plain
);
4487 device
->NumUpdates
= 0;
4488 device
->UpdateSize
= 0;
4490 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4491 device
->FmtChans
= DevFmtChannelsDefault
;
4492 device
->FmtType
= DevFmtTypeDefault
;
4493 device
->IsHeadphones
= AL_FALSE
;
4494 device
->AmbiLayout
= AmbiLayout_Default
;
4495 device
->AmbiScale
= AmbiNorm_Default
;
4497 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4498 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4500 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4501 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4503 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4504 device
->NumAuxSends
= clampi(
4505 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4508 device
->NumStereoSources
= 1;
4509 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4511 // Open the "backend"
4512 V(device
->Backend
,open
)("Loopback");
4514 device
->Limiter
= CreateDeviceLimiter(device
);
4517 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4519 device
->next
= head
;
4520 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4523 TRACE("Created device %p\n", device
);
4527 /* alcIsRenderFormatSupportedSOFT
4529 * Determines if the loopback device supports the given format for rendering.
4531 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4533 ALCboolean ret
= ALC_FALSE
;
4535 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4536 alcSetError(device
, ALC_INVALID_DEVICE
);
4538 alcSetError(device
, ALC_INVALID_VALUE
);
4541 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4544 if(device
) ALCdevice_DecRef(device
);
4549 /* alcRenderSamplesSOFT
4551 * Renders some samples into a buffer, using the format last set by the
4552 * attributes given to alcCreateContext.
4554 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4556 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4557 alcSetError(device
, ALC_INVALID_DEVICE
);
4558 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4559 alcSetError(device
, ALC_INVALID_VALUE
);
4562 V0(device
->Backend
,lock
)();
4563 aluMixData(device
, buffer
, samples
);
4564 V0(device
->Backend
,unlock
)();
4566 if(device
) ALCdevice_DecRef(device
);
4570 /************************************************
4571 * ALC DSP pause/resume functions
4572 ************************************************/
4574 /* alcDevicePauseSOFT
4576 * Pause the DSP to stop audio processing.
4578 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4580 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4581 alcSetError(device
, ALC_INVALID_DEVICE
);
4584 almtx_lock(&device
->BackendLock
);
4585 if((device
->Flags
&DEVICE_RUNNING
))
4586 V0(device
->Backend
,stop
)();
4587 device
->Flags
&= ~DEVICE_RUNNING
;
4588 device
->Flags
|= DEVICE_PAUSED
;
4589 almtx_unlock(&device
->BackendLock
);
4591 if(device
) ALCdevice_DecRef(device
);
4594 /* alcDeviceResumeSOFT
4596 * Resume the DSP to restart audio processing.
4598 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4600 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4601 alcSetError(device
, ALC_INVALID_DEVICE
);
4604 almtx_lock(&device
->BackendLock
);
4605 if((device
->Flags
&DEVICE_PAUSED
))
4607 device
->Flags
&= ~DEVICE_PAUSED
;
4608 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4610 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4611 device
->Flags
|= DEVICE_RUNNING
;
4614 alcSetError(device
, ALC_INVALID_DEVICE
);
4615 V0(device
->Backend
,lock
)();
4616 aluHandleDisconnect(device
);
4617 V0(device
->Backend
,unlock
)();
4621 almtx_unlock(&device
->BackendLock
);
4623 if(device
) ALCdevice_DecRef(device
);
4627 /************************************************
4628 * ALC HRTF functions
4629 ************************************************/
4631 /* alcGetStringiSOFT
4633 * Gets a string parameter at the given index.
4635 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4637 const ALCchar
*str
= NULL
;
4639 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4640 alcSetError(device
, ALC_INVALID_DEVICE
);
4641 else switch(paramName
)
4643 case ALC_HRTF_SPECIFIER_SOFT
:
4644 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4645 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4647 alcSetError(device
, ALC_INVALID_VALUE
);
4651 alcSetError(device
, ALC_INVALID_ENUM
);
4654 if(device
) ALCdevice_DecRef(device
);
4659 /* alcResetDeviceSOFT
4661 * Resets the given device output, using the specified attribute list.
4663 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4668 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4671 alcSetError(device
, ALC_INVALID_DEVICE
);
4672 if(device
) ALCdevice_DecRef(device
);
4675 almtx_lock(&device
->BackendLock
);
4678 err
= UpdateDeviceParams(device
, attribs
);
4679 almtx_unlock(&device
->BackendLock
);
4681 if(err
!= ALC_NO_ERROR
)
4683 alcSetError(device
, err
);
4684 if(err
== ALC_INVALID_DEVICE
)
4686 V0(device
->Backend
,lock
)();
4687 aluHandleDisconnect(device
);
4688 V0(device
->Backend
,unlock
)();
4690 ALCdevice_DecRef(device
);
4693 ALCdevice_DecRef(device
);