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 "mastering.h"
41 #include "bformatdec.h"
51 #include "backends/base.h"
54 /************************************************
56 ************************************************/
59 ALCbackendFactory
* (*getFactory
)(void);
62 static struct BackendInfo BackendList
[] = {
64 { "jack", ALCjackBackendFactory_getFactory
},
66 #ifdef HAVE_PULSEAUDIO
67 { "pulse", ALCpulseBackendFactory_getFactory
},
70 { "alsa", ALCalsaBackendFactory_getFactory
},
73 { "core", ALCcoreAudioBackendFactory_getFactory
},
76 { "oss", ALCossBackendFactory_getFactory
},
79 { "solaris", ALCsolarisBackendFactory_getFactory
},
82 { "sndio", ALCsndioBackendFactory_getFactory
},
85 { "qsa", ALCqsaBackendFactory_getFactory
},
88 { "mmdevapi", ALCmmdevBackendFactory_getFactory
},
91 { "dsound", ALCdsoundBackendFactory_getFactory
},
94 { "winmm", ALCwinmmBackendFactory_getFactory
},
97 { "port", ALCportBackendFactory_getFactory
},
100 { "opensl", ALCopenslBackendFactory_getFactory
},
103 { "null", ALCnullBackendFactory_getFactory
},
105 { "wave", ALCwaveBackendFactory_getFactory
},
108 static ALsizei BackendListSize
= COUNTOF(BackendList
);
111 static struct BackendInfo PlaybackBackend
;
112 static struct BackendInfo CaptureBackend
;
115 /************************************************
116 * Functions, enums, and errors
117 ************************************************/
118 #define DECL(x) { #x, (ALCvoid*)(x) }
119 static const struct {
120 const ALCchar
*funcName
;
123 DECL(alcCreateContext
),
124 DECL(alcMakeContextCurrent
),
125 DECL(alcProcessContext
),
126 DECL(alcSuspendContext
),
127 DECL(alcDestroyContext
),
128 DECL(alcGetCurrentContext
),
129 DECL(alcGetContextsDevice
),
131 DECL(alcCloseDevice
),
133 DECL(alcIsExtensionPresent
),
134 DECL(alcGetProcAddress
),
135 DECL(alcGetEnumValue
),
137 DECL(alcGetIntegerv
),
138 DECL(alcCaptureOpenDevice
),
139 DECL(alcCaptureCloseDevice
),
140 DECL(alcCaptureStart
),
141 DECL(alcCaptureStop
),
142 DECL(alcCaptureSamples
),
144 DECL(alcSetThreadContext
),
145 DECL(alcGetThreadContext
),
147 DECL(alcLoopbackOpenDeviceSOFT
),
148 DECL(alcIsRenderFormatSupportedSOFT
),
149 DECL(alcRenderSamplesSOFT
),
151 DECL(alcDevicePauseSOFT
),
152 DECL(alcDeviceResumeSOFT
),
154 DECL(alcGetStringiSOFT
),
155 DECL(alcResetDeviceSOFT
),
157 DECL(alcGetInteger64vSOFT
),
172 DECL(alIsExtensionPresent
),
173 DECL(alGetProcAddress
),
174 DECL(alGetEnumValue
),
181 DECL(alGetListenerf
),
182 DECL(alGetListener3f
),
183 DECL(alGetListenerfv
),
184 DECL(alGetListeneri
),
185 DECL(alGetListener3i
),
186 DECL(alGetListeneriv
),
188 DECL(alDeleteSources
),
204 DECL(alSourceRewindv
),
205 DECL(alSourcePausev
),
208 DECL(alSourceRewind
),
210 DECL(alSourceQueueBuffers
),
211 DECL(alSourceUnqueueBuffers
),
213 DECL(alDeleteBuffers
),
228 DECL(alDopplerFactor
),
229 DECL(alDopplerVelocity
),
230 DECL(alSpeedOfSound
),
231 DECL(alDistanceModel
),
234 DECL(alDeleteFilters
),
245 DECL(alDeleteEffects
),
255 DECL(alGenAuxiliaryEffectSlots
),
256 DECL(alDeleteAuxiliaryEffectSlots
),
257 DECL(alIsAuxiliaryEffectSlot
),
258 DECL(alAuxiliaryEffectSloti
),
259 DECL(alAuxiliaryEffectSlotiv
),
260 DECL(alAuxiliaryEffectSlotf
),
261 DECL(alAuxiliaryEffectSlotfv
),
262 DECL(alGetAuxiliaryEffectSloti
),
263 DECL(alGetAuxiliaryEffectSlotiv
),
264 DECL(alGetAuxiliaryEffectSlotf
),
265 DECL(alGetAuxiliaryEffectSlotfv
),
267 DECL(alDeferUpdatesSOFT
),
268 DECL(alProcessUpdatesSOFT
),
271 DECL(alSource3dSOFT
),
272 DECL(alSourcedvSOFT
),
273 DECL(alGetSourcedSOFT
),
274 DECL(alGetSource3dSOFT
),
275 DECL(alGetSourcedvSOFT
),
276 DECL(alSourcei64SOFT
),
277 DECL(alSource3i64SOFT
),
278 DECL(alSourcei64vSOFT
),
279 DECL(alGetSourcei64SOFT
),
280 DECL(alGetSource3i64SOFT
),
281 DECL(alGetSourcei64vSOFT
),
283 DECL(alBufferSamplesSOFT
),
284 DECL(alGetBufferSamplesSOFT
),
285 DECL(alIsBufferFormatSupportedSOFT
),
287 DECL(alGetStringiSOFT
),
291 #define DECL(x) { #x, (x) }
292 static const struct {
293 const ALCchar
*enumName
;
295 } alcEnumerations
[] = {
300 DECL(ALC_MAJOR_VERSION
),
301 DECL(ALC_MINOR_VERSION
),
302 DECL(ALC_ATTRIBUTES_SIZE
),
303 DECL(ALC_ALL_ATTRIBUTES
),
304 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
305 DECL(ALC_DEVICE_SPECIFIER
),
306 DECL(ALC_ALL_DEVICES_SPECIFIER
),
307 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
308 DECL(ALC_EXTENSIONS
),
312 DECL(ALC_MONO_SOURCES
),
313 DECL(ALC_STEREO_SOURCES
),
314 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
315 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
316 DECL(ALC_CAPTURE_SAMPLES
),
319 DECL(ALC_EFX_MAJOR_VERSION
),
320 DECL(ALC_EFX_MINOR_VERSION
),
321 DECL(ALC_MAX_AUXILIARY_SENDS
),
323 DECL(ALC_FORMAT_CHANNELS_SOFT
),
324 DECL(ALC_FORMAT_TYPE_SOFT
),
327 DECL(ALC_STEREO_SOFT
),
329 DECL(ALC_5POINT1_SOFT
),
330 DECL(ALC_6POINT1_SOFT
),
331 DECL(ALC_7POINT1_SOFT
),
332 DECL(ALC_BFORMAT3D_SOFT
),
335 DECL(ALC_UNSIGNED_BYTE_SOFT
),
336 DECL(ALC_SHORT_SOFT
),
337 DECL(ALC_UNSIGNED_SHORT_SOFT
),
339 DECL(ALC_UNSIGNED_INT_SOFT
),
340 DECL(ALC_FLOAT_SOFT
),
343 DECL(ALC_DONT_CARE_SOFT
),
344 DECL(ALC_HRTF_STATUS_SOFT
),
345 DECL(ALC_HRTF_DISABLED_SOFT
),
346 DECL(ALC_HRTF_ENABLED_SOFT
),
347 DECL(ALC_HRTF_DENIED_SOFT
),
348 DECL(ALC_HRTF_REQUIRED_SOFT
),
349 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
350 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
351 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
352 DECL(ALC_HRTF_SPECIFIER_SOFT
),
353 DECL(ALC_HRTF_ID_SOFT
),
355 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
356 DECL(ALC_AMBISONIC_SCALING_SOFT
),
357 DECL(ALC_AMBISONIC_ORDER_SOFT
),
363 DECL(ALC_OUTPUT_LIMITER_SOFT
),
366 DECL(ALC_INVALID_DEVICE
),
367 DECL(ALC_INVALID_CONTEXT
),
368 DECL(ALC_INVALID_ENUM
),
369 DECL(ALC_INVALID_VALUE
),
370 DECL(ALC_OUT_OF_MEMORY
),
378 DECL(AL_SOURCE_RELATIVE
),
379 DECL(AL_CONE_INNER_ANGLE
),
380 DECL(AL_CONE_OUTER_ANGLE
),
390 DECL(AL_ORIENTATION
),
391 DECL(AL_REFERENCE_DISTANCE
),
392 DECL(AL_ROLLOFF_FACTOR
),
393 DECL(AL_CONE_OUTER_GAIN
),
394 DECL(AL_MAX_DISTANCE
),
396 DECL(AL_SAMPLE_OFFSET
),
397 DECL(AL_BYTE_OFFSET
),
398 DECL(AL_SOURCE_TYPE
),
401 DECL(AL_UNDETERMINED
),
402 DECL(AL_METERS_PER_UNIT
),
403 DECL(AL_LOOP_POINTS_SOFT
),
404 DECL(AL_DIRECT_CHANNELS_SOFT
),
406 DECL(AL_DIRECT_FILTER
),
407 DECL(AL_AUXILIARY_SEND_FILTER
),
408 DECL(AL_AIR_ABSORPTION_FACTOR
),
409 DECL(AL_ROOM_ROLLOFF_FACTOR
),
410 DECL(AL_CONE_OUTER_GAINHF
),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
415 DECL(AL_SOURCE_STATE
),
421 DECL(AL_BUFFERS_QUEUED
),
422 DECL(AL_BUFFERS_PROCESSED
),
424 DECL(AL_FORMAT_MONO8
),
425 DECL(AL_FORMAT_MONO16
),
426 DECL(AL_FORMAT_MONO_FLOAT32
),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
428 DECL(AL_FORMAT_STEREO8
),
429 DECL(AL_FORMAT_STEREO16
),
430 DECL(AL_FORMAT_STEREO_FLOAT32
),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
432 DECL(AL_FORMAT_MONO_IMA4
),
433 DECL(AL_FORMAT_STEREO_IMA4
),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
436 DECL(AL_FORMAT_QUAD8_LOKI
),
437 DECL(AL_FORMAT_QUAD16_LOKI
),
438 DECL(AL_FORMAT_QUAD8
),
439 DECL(AL_FORMAT_QUAD16
),
440 DECL(AL_FORMAT_QUAD32
),
441 DECL(AL_FORMAT_51CHN8
),
442 DECL(AL_FORMAT_51CHN16
),
443 DECL(AL_FORMAT_51CHN32
),
444 DECL(AL_FORMAT_61CHN8
),
445 DECL(AL_FORMAT_61CHN16
),
446 DECL(AL_FORMAT_61CHN32
),
447 DECL(AL_FORMAT_71CHN8
),
448 DECL(AL_FORMAT_71CHN16
),
449 DECL(AL_FORMAT_71CHN32
),
450 DECL(AL_FORMAT_REAR8
),
451 DECL(AL_FORMAT_REAR16
),
452 DECL(AL_FORMAT_REAR32
),
453 DECL(AL_FORMAT_MONO_MULAW
),
454 DECL(AL_FORMAT_MONO_MULAW_EXT
),
455 DECL(AL_FORMAT_STEREO_MULAW
),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
457 DECL(AL_FORMAT_QUAD_MULAW
),
458 DECL(AL_FORMAT_51CHN_MULAW
),
459 DECL(AL_FORMAT_61CHN_MULAW
),
460 DECL(AL_FORMAT_71CHN_MULAW
),
461 DECL(AL_FORMAT_REAR_MULAW
),
462 DECL(AL_FORMAT_MONO_ALAW_EXT
),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
465 DECL(AL_FORMAT_BFORMAT2D_8
),
466 DECL(AL_FORMAT_BFORMAT2D_16
),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
469 DECL(AL_FORMAT_BFORMAT3D_8
),
470 DECL(AL_FORMAT_BFORMAT3D_16
),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
475 DECL(AL_MONO16_SOFT
),
476 DECL(AL_MONO32F_SOFT
),
477 DECL(AL_STEREO8_SOFT
),
478 DECL(AL_STEREO16_SOFT
),
479 DECL(AL_STEREO32F_SOFT
),
481 DECL(AL_QUAD16_SOFT
),
482 DECL(AL_QUAD32F_SOFT
),
484 DECL(AL_REAR16_SOFT
),
485 DECL(AL_REAR32F_SOFT
),
486 DECL(AL_5POINT1_8_SOFT
),
487 DECL(AL_5POINT1_16_SOFT
),
488 DECL(AL_5POINT1_32F_SOFT
),
489 DECL(AL_6POINT1_8_SOFT
),
490 DECL(AL_6POINT1_16_SOFT
),
491 DECL(AL_6POINT1_32F_SOFT
),
492 DECL(AL_7POINT1_8_SOFT
),
493 DECL(AL_7POINT1_16_SOFT
),
494 DECL(AL_7POINT1_32F_SOFT
),
495 DECL(AL_BFORMAT2D_8_SOFT
),
496 DECL(AL_BFORMAT2D_16_SOFT
),
497 DECL(AL_BFORMAT2D_32F_SOFT
),
498 DECL(AL_BFORMAT3D_8_SOFT
),
499 DECL(AL_BFORMAT3D_16_SOFT
),
500 DECL(AL_BFORMAT3D_32F_SOFT
),
503 DECL(AL_STEREO_SOFT
),
506 DECL(AL_5POINT1_SOFT
),
507 DECL(AL_6POINT1_SOFT
),
508 DECL(AL_7POINT1_SOFT
),
509 DECL(AL_BFORMAT2D_SOFT
),
510 DECL(AL_BFORMAT3D_SOFT
),
513 DECL(AL_UNSIGNED_BYTE_SOFT
),
515 DECL(AL_UNSIGNED_SHORT_SOFT
),
517 DECL(AL_UNSIGNED_INT_SOFT
),
519 DECL(AL_DOUBLE_SOFT
),
521 DECL(AL_UNSIGNED_BYTE3_SOFT
),
528 DECL(AL_INTERNAL_FORMAT_SOFT
),
529 DECL(AL_BYTE_LENGTH_SOFT
),
530 DECL(AL_SAMPLE_LENGTH_SOFT
),
531 DECL(AL_SEC_LENGTH_SOFT
),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
535 DECL(AL_SOURCE_RADIUS
),
537 DECL(AL_STEREO_ANGLES
),
544 DECL(AL_INVALID_NAME
),
545 DECL(AL_INVALID_ENUM
),
546 DECL(AL_INVALID_VALUE
),
547 DECL(AL_INVALID_OPERATION
),
548 DECL(AL_OUT_OF_MEMORY
),
555 DECL(AL_DOPPLER_FACTOR
),
556 DECL(AL_DOPPLER_VELOCITY
),
557 DECL(AL_DISTANCE_MODEL
),
558 DECL(AL_SPEED_OF_SOUND
),
559 DECL(AL_SOURCE_DISTANCE_MODEL
),
560 DECL(AL_DEFERRED_UPDATES_SOFT
),
561 DECL(AL_GAIN_LIMIT_SOFT
),
563 DECL(AL_INVERSE_DISTANCE
),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
565 DECL(AL_LINEAR_DISTANCE
),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
567 DECL(AL_EXPONENT_DISTANCE
),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
570 DECL(AL_FILTER_TYPE
),
571 DECL(AL_FILTER_NULL
),
572 DECL(AL_FILTER_LOWPASS
),
573 DECL(AL_FILTER_HIGHPASS
),
574 DECL(AL_FILTER_BANDPASS
),
576 DECL(AL_LOWPASS_GAIN
),
577 DECL(AL_LOWPASS_GAINHF
),
579 DECL(AL_HIGHPASS_GAIN
),
580 DECL(AL_HIGHPASS_GAINLF
),
582 DECL(AL_BANDPASS_GAIN
),
583 DECL(AL_BANDPASS_GAINHF
),
584 DECL(AL_BANDPASS_GAINLF
),
586 DECL(AL_EFFECT_TYPE
),
587 DECL(AL_EFFECT_NULL
),
588 DECL(AL_EFFECT_REVERB
),
589 DECL(AL_EFFECT_EAXREVERB
),
590 DECL(AL_EFFECT_CHORUS
),
591 DECL(AL_EFFECT_DISTORTION
),
592 DECL(AL_EFFECT_ECHO
),
593 DECL(AL_EFFECT_FLANGER
),
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
596 DECL(AL_EFFECT_VOCAL_MORPHER
),
597 DECL(AL_EFFECT_PITCH_SHIFTER
),
599 DECL(AL_EFFECT_RING_MODULATOR
),
601 DECL(AL_EFFECT_AUTOWAH
),
603 DECL(AL_EFFECT_COMPRESSOR
),
604 DECL(AL_EFFECT_EQUALIZER
),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
608 DECL(AL_EFFECTSLOT_EFFECT
),
609 DECL(AL_EFFECTSLOT_GAIN
),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
611 DECL(AL_EFFECTSLOT_NULL
),
613 DECL(AL_EAXREVERB_DENSITY
),
614 DECL(AL_EAXREVERB_DIFFUSION
),
615 DECL(AL_EAXREVERB_GAIN
),
616 DECL(AL_EAXREVERB_GAINHF
),
617 DECL(AL_EAXREVERB_GAINLF
),
618 DECL(AL_EAXREVERB_DECAY_TIME
),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
627 DECL(AL_EAXREVERB_ECHO_TIME
),
628 DECL(AL_EAXREVERB_ECHO_DEPTH
),
629 DECL(AL_EAXREVERB_MODULATION_TIME
),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
632 DECL(AL_EAXREVERB_HFREFERENCE
),
633 DECL(AL_EAXREVERB_LFREFERENCE
),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
637 DECL(AL_REVERB_DENSITY
),
638 DECL(AL_REVERB_DIFFUSION
),
639 DECL(AL_REVERB_GAIN
),
640 DECL(AL_REVERB_GAINHF
),
641 DECL(AL_REVERB_DECAY_TIME
),
642 DECL(AL_REVERB_DECAY_HFRATIO
),
643 DECL(AL_REVERB_REFLECTIONS_GAIN
),
644 DECL(AL_REVERB_REFLECTIONS_DELAY
),
645 DECL(AL_REVERB_LATE_REVERB_GAIN
),
646 DECL(AL_REVERB_LATE_REVERB_DELAY
),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
649 DECL(AL_REVERB_DECAY_HFLIMIT
),
651 DECL(AL_CHORUS_WAVEFORM
),
652 DECL(AL_CHORUS_PHASE
),
653 DECL(AL_CHORUS_RATE
),
654 DECL(AL_CHORUS_DEPTH
),
655 DECL(AL_CHORUS_FEEDBACK
),
656 DECL(AL_CHORUS_DELAY
),
658 DECL(AL_DISTORTION_EDGE
),
659 DECL(AL_DISTORTION_GAIN
),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
661 DECL(AL_DISTORTION_EQCENTER
),
662 DECL(AL_DISTORTION_EQBANDWIDTH
),
665 DECL(AL_ECHO_LRDELAY
),
666 DECL(AL_ECHO_DAMPING
),
667 DECL(AL_ECHO_FEEDBACK
),
668 DECL(AL_ECHO_SPREAD
),
670 DECL(AL_FLANGER_WAVEFORM
),
671 DECL(AL_FLANGER_PHASE
),
672 DECL(AL_FLANGER_RATE
),
673 DECL(AL_FLANGER_DEPTH
),
674 DECL(AL_FLANGER_FEEDBACK
),
675 DECL(AL_FLANGER_DELAY
),
677 DECL(AL_RING_MODULATOR_FREQUENCY
),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
679 DECL(AL_RING_MODULATOR_WAVEFORM
),
681 DECL(AL_COMPRESSOR_ONOFF
),
683 DECL(AL_EQUALIZER_LOW_GAIN
),
684 DECL(AL_EQUALIZER_LOW_CUTOFF
),
685 DECL(AL_EQUALIZER_MID1_GAIN
),
686 DECL(AL_EQUALIZER_MID1_CENTER
),
687 DECL(AL_EQUALIZER_MID1_WIDTH
),
688 DECL(AL_EQUALIZER_MID2_GAIN
),
689 DECL(AL_EQUALIZER_MID2_CENTER
),
690 DECL(AL_EQUALIZER_MID2_WIDTH
),
691 DECL(AL_EQUALIZER_HIGH_GAIN
),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
694 DECL(AL_DEDICATED_GAIN
),
696 DECL(AL_NUM_RESAMPLERS_SOFT
),
697 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
698 DECL(AL_SOURCE_RESAMPLER_SOFT
),
699 DECL(AL_RESAMPLER_NAME_SOFT
),
701 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
706 static const ALCchar alcNoError
[] = "No Error";
707 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
708 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
709 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
710 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
711 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
714 /************************************************
716 ************************************************/
718 /* Enumerated device names */
719 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
721 static al_string alcAllDevicesList
;
722 static al_string alcCaptureDeviceList
;
724 /* Default is always the first in the list */
725 static ALCchar
*alcDefaultAllDevicesSpecifier
;
726 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
728 /* Default context extensions */
729 static const ALchar alExtList
[] =
730 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
731 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
732 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
733 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
734 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
735 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
736 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length "
737 "AL_SOFT_source_resampler AL_SOFT_source_spatialize";
739 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
741 /* Thread-local current context */
742 static altss_t LocalContext
;
743 /* Process-wide current context */
744 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
746 /* Mixing thread piority level */
751 enum LogLevel LogLevel
= LogWarning
;
753 enum LogLevel LogLevel
= LogError
;
756 /* Flag to trap ALC device errors */
757 static ALCboolean TrapALCError
= ALC_FALSE
;
759 /* One-time configuration init control */
760 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
762 /* Default effect that applies to sources that don't have an effect on send 0 */
763 static ALeffect DefaultEffect
;
765 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
768 static ALCboolean SuspendDefers
= ALC_TRUE
;
771 /************************************************
773 ************************************************/
774 static const ALCchar alcNoDeviceExtList
[] =
775 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
776 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
777 static const ALCchar alcExtensionList
[] =
778 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
779 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
780 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
781 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
782 static const ALCint alcMajorVersion
= 1;
783 static const ALCint alcMinorVersion
= 1;
785 static const ALCint alcEFXMajorVersion
= 1;
786 static const ALCint alcEFXMinorVersion
= 0;
789 /************************************************
791 ************************************************/
792 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
794 static almtx_t ListLock
;
795 static inline void LockLists(void)
797 int ret
= almtx_lock(&ListLock
);
798 assert(ret
== althrd_success
);
800 static inline void UnlockLists(void)
802 int ret
= almtx_unlock(&ListLock
);
803 assert(ret
== althrd_success
);
806 /************************************************
807 * Library initialization
808 ************************************************/
810 static void alc_init(void);
811 static void alc_deinit(void);
812 static void alc_deinit_safe(void);
814 #ifndef AL_LIBTYPE_STATIC
815 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
819 case DLL_PROCESS_ATTACH
:
820 /* Pin the DLL so we won't get unloaded until the process terminates */
821 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
822 (WCHAR
*)hModule
, &hModule
);
826 case DLL_THREAD_DETACH
:
829 case DLL_PROCESS_DETACH
:
838 #elif defined(_MSC_VER)
839 #pragma section(".CRT$XCU",read)
840 static void alc_constructor(void);
841 static void alc_destructor(void);
842 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
844 static void alc_constructor(void)
846 atexit(alc_destructor
);
850 static void alc_destructor(void)
854 #elif defined(HAVE_GCC_DESTRUCTOR)
855 static void alc_init(void) __attribute__((constructor
));
856 static void alc_deinit(void) __attribute__((destructor
));
858 #error "No static initialization available on this platform!"
861 #elif defined(HAVE_GCC_DESTRUCTOR)
863 static void alc_init(void) __attribute__((constructor
));
864 static void alc_deinit(void) __attribute__((destructor
));
867 #error "No global initialization available on this platform!"
870 static void ReleaseThreadCtx(void *ptr
);
871 static void alc_init(void)
878 AL_STRING_INIT(alcAllDevicesList
);
879 AL_STRING_INIT(alcCaptureDeviceList
);
881 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
882 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
885 str
= getenv("__ALSOFT_REVERSE_Z");
886 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
889 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
890 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
891 OverrideReverbSpeedOfSound
= AL_TRUE
;
893 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
894 assert(ret
== althrd_success
);
896 ret
= almtx_init(&ListLock
, almtx_recursive
);
897 assert(ret
== althrd_success
);
902 static void alc_initconfig(void)
904 const char *devs
, *str
;
909 str
= getenv("ALSOFT_LOGLEVEL");
912 long lvl
= strtol(str
, NULL
, 0);
913 if(lvl
>= NoLog
&& lvl
<= LogRef
)
917 str
= getenv("ALSOFT_LOGFILE");
920 FILE *logfile
= al_fopen(str
, "wt");
921 if(logfile
) LogFile
= logfile
;
922 else ERR("Failed to open log file '%s'\n", str
);
925 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
926 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
931 if(BackendListSize
> 0)
932 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
933 for(i
= 1;i
< BackendListSize
;i
++)
934 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
935 TRACE("Supported backends: %s\n", buf
);
939 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
942 if(strcasecmp(str
, "ignore") == 0)
944 SuspendDefers
= ALC_FALSE
;
945 TRACE("Selected context suspend behavior, \"ignore\"\n");
948 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
952 #if defined(HAVE_SSE4_1)
953 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
954 #elif defined(HAVE_SSE3)
955 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
956 #elif defined(HAVE_SSE2)
957 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
958 #elif defined(HAVE_SSE)
959 capfilter
|= CPU_CAP_SSE
;
962 capfilter
|= CPU_CAP_NEON
;
964 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
966 if(strcasecmp(str
, "all") == 0)
971 const char *next
= str
;
975 while(isspace(str
[0]))
977 next
= strchr(str
, ',');
979 if(!str
[0] || str
[0] == ',')
982 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
983 while(len
> 0 && isspace(str
[len
-1]))
985 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
986 capfilter
&= ~CPU_CAP_SSE
;
987 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
988 capfilter
&= ~CPU_CAP_SSE2
;
989 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
990 capfilter
&= ~CPU_CAP_SSE3
;
991 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
992 capfilter
&= ~CPU_CAP_SSE4_1
;
993 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
994 capfilter
&= ~CPU_CAP_NEON
;
996 WARN("Invalid CPU extension \"%s\"\n", str
);
1000 FillCPUCaps(capfilter
);
1007 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1012 str
= getenv("ALSOFT_TRAP_ERROR");
1013 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1015 TrapALError
= AL_TRUE
;
1016 TrapALCError
= AL_TRUE
;
1020 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1021 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1022 TrapALError
= AL_TRUE
;
1023 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1025 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1026 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1027 TrapALCError
= ALC_TRUE
;
1028 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1031 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1032 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1034 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1035 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1039 const char *next
= devs
;
1040 int endlist
, delitem
;
1045 while(isspace(devs
[0]))
1047 next
= strchr(devs
, ',');
1049 delitem
= (devs
[0] == '-');
1050 if(devs
[0] == '-') devs
++;
1052 if(!devs
[0] || devs
[0] == ',')
1059 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1060 while(len
> 0 && isspace(devs
[len
-1]))
1062 for(n
= i
;n
< BackendListSize
;n
++)
1064 if(len
== strlen(BackendList
[n
].name
) &&
1065 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1069 for(;n
+1 < BackendListSize
;n
++)
1070 BackendList
[n
] = BackendList
[n
+1];
1075 struct BackendInfo Bkp
= BackendList
[n
];
1077 BackendList
[n
] = BackendList
[n
-1];
1078 BackendList
[n
] = Bkp
;
1088 BackendListSize
= i
;
1091 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1093 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1094 if(!V0(factory
,init
)())
1096 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1100 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1101 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1103 PlaybackBackend
= BackendList
[i
];
1104 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1106 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1108 CaptureBackend
= BackendList
[i
];
1109 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1113 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1117 if(!PlaybackBackend
.name
)
1118 WARN("No playback backend available!\n");
1119 if(!CaptureBackend
.name
)
1120 WARN("No capture backend available!\n");
1122 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1125 const char *next
= str
;
1129 next
= strchr(str
, ',');
1131 if(!str
[0] || next
== str
)
1134 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1135 for(n
= 0;EffectList
[n
].name
;n
++)
1137 if(len
== strlen(EffectList
[n
].name
) &&
1138 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1139 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1144 InitEffectFactoryMap();
1146 InitEffect(&DefaultEffect
);
1147 str
= getenv("ALSOFT_DEFAULT_REVERB");
1148 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1149 LoadReverbPreset(str
, &DefaultEffect
);
1151 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1156 static JavaVM
*gJavaVM
;
1157 static pthread_key_t gJVMThreadKey
;
1159 static void CleanupJNIEnv(void* UNUSED(ptr
))
1161 JCALL0(gJavaVM
,DetachCurrentThread
)();
1164 void *Android_GetJNIEnv(void)
1168 WARN("gJavaVM is NULL!\n");
1172 /* http://developer.android.com/guide/practices/jni.html
1174 * All threads are Linux threads, scheduled by the kernel. They're usually
1175 * started from managed code (using Thread.start), but they can also be
1176 * created elsewhere and then attached to the JavaVM. For example, a thread
1177 * started with pthread_create can be attached with the JNI
1178 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1179 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1180 * Attaching a natively-created thread causes a java.lang.Thread object to
1181 * be constructed and added to the "main" ThreadGroup, making it visible to
1182 * the debugger. Calling AttachCurrentThread on an already-attached thread
1185 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1188 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1191 ERR("Failed to attach current thread\n");
1194 pthread_setspecific(gJVMThreadKey
, env
);
1199 /* Automatically called by JNI. */
1200 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1206 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1208 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1212 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1213 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1215 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1216 ERR("pthread_key_create failed: %d\n", err
);
1217 pthread_setspecific(gJVMThreadKey
, env
);
1218 return JNI_VERSION_1_4
;
1223 /************************************************
1224 * Library deinitialization
1225 ************************************************/
1226 static void alc_cleanup(void)
1230 AL_STRING_DEINIT(alcAllDevicesList
);
1231 AL_STRING_DEINIT(alcCaptureDeviceList
);
1233 free(alcDefaultAllDevicesSpecifier
);
1234 alcDefaultAllDevicesSpecifier
= NULL
;
1235 free(alcCaptureDefaultDeviceSpecifier
);
1236 alcCaptureDefaultDeviceSpecifier
= NULL
;
1238 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1243 } while((dev
=dev
->next
) != NULL
);
1244 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1247 DeinitEffectFactoryMap();
1250 static void alc_deinit_safe(void)
1258 almtx_destroy(&ListLock
);
1259 altss_delete(LocalContext
);
1261 if(LogFile
!= stderr
)
1266 static void alc_deinit(void)
1272 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1273 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1275 for(i
= 0;i
< BackendListSize
;i
++)
1277 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1278 V0(factory
,deinit
)();
1281 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1282 V0(factory
,deinit
)();
1289 /************************************************
1290 * Device enumeration
1291 ************************************************/
1292 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1299 if(backendinfo
->getFactory
)
1301 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1302 V(factory
,probe
)(type
);
1307 static void ProbeAllDevicesList(void)
1308 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1309 static void ProbeCaptureDeviceList(void)
1310 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1312 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1314 size_t len
= strlen(name
);
1316 alstr_append_range(devnames
, name
, name
+len
+1);
1318 void AppendAllDevicesList(const ALCchar
*name
)
1319 { AppendDevice(name
, &alcAllDevicesList
); }
1320 void AppendCaptureDeviceList(const ALCchar
*name
)
1321 { AppendDevice(name
, &alcCaptureDeviceList
); }
1324 /************************************************
1325 * Device format information
1326 ************************************************/
1327 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1331 case DevFmtByte
: return "Signed Byte";
1332 case DevFmtUByte
: return "Unsigned Byte";
1333 case DevFmtShort
: return "Signed Short";
1334 case DevFmtUShort
: return "Unsigned Short";
1335 case DevFmtInt
: return "Signed Int";
1336 case DevFmtUInt
: return "Unsigned Int";
1337 case DevFmtFloat
: return "Float";
1339 return "(unknown type)";
1341 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1345 case DevFmtMono
: return "Mono";
1346 case DevFmtStereo
: return "Stereo";
1347 case DevFmtQuad
: return "Quadraphonic";
1348 case DevFmtX51
: return "5.1 Surround";
1349 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1350 case DevFmtX61
: return "6.1 Surround";
1351 case DevFmtX71
: return "7.1 Surround";
1352 case DevFmtAmbi3D
: return "Ambisonic 3D";
1354 return "(unknown channels)";
1357 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1358 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1362 case DevFmtByte
: return sizeof(ALbyte
);
1363 case DevFmtUByte
: return sizeof(ALubyte
);
1364 case DevFmtShort
: return sizeof(ALshort
);
1365 case DevFmtUShort
: return sizeof(ALushort
);
1366 case DevFmtInt
: return sizeof(ALint
);
1367 case DevFmtUInt
: return sizeof(ALuint
);
1368 case DevFmtFloat
: return sizeof(ALfloat
);
1372 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1376 case DevFmtMono
: return 1;
1377 case DevFmtStereo
: return 2;
1378 case DevFmtQuad
: return 4;
1379 case DevFmtX51
: return 6;
1380 case DevFmtX51Rear
: return 6;
1381 case DevFmtX61
: return 7;
1382 case DevFmtX71
: return 8;
1383 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1384 (ambiorder
== 2) ? 9 :
1385 (ambiorder
== 1) ? 4 : 1;
1390 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1391 enum DevFmtType
*type
)
1393 static const struct {
1395 enum DevFmtChannels channels
;
1396 enum DevFmtType type
;
1398 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1399 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1400 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1402 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1403 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1404 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1406 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1407 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1408 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1410 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1411 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1412 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1414 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1415 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1416 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1418 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1419 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1420 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1424 for(i
= 0;i
< COUNTOF(list
);i
++)
1426 if(list
[i
].format
== format
)
1428 *chans
= list
[i
].channels
;
1429 *type
= list
[i
].type
;
1437 static ALCboolean
IsValidALCType(ALCenum type
)
1442 case ALC_UNSIGNED_BYTE_SOFT
:
1443 case ALC_SHORT_SOFT
:
1444 case ALC_UNSIGNED_SHORT_SOFT
:
1446 case ALC_UNSIGNED_INT_SOFT
:
1447 case ALC_FLOAT_SOFT
:
1453 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1458 case ALC_STEREO_SOFT
:
1460 case ALC_5POINT1_SOFT
:
1461 case ALC_6POINT1_SOFT
:
1462 case ALC_7POINT1_SOFT
:
1463 case ALC_BFORMAT3D_SOFT
:
1469 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1480 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1492 /************************************************
1493 * Miscellaneous ALC helpers
1494 ************************************************/
1496 void ALCdevice_Lock(ALCdevice
*device
)
1498 V0(device
->Backend
,lock
)();
1501 void ALCdevice_Unlock(ALCdevice
*device
)
1503 V0(device
->Backend
,unlock
)();
1507 /* SetDefaultWFXChannelOrder
1509 * Sets the default channel order used by WaveFormatEx.
1511 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1515 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1516 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1518 switch(device
->FmtChans
)
1521 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1524 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1525 device
->RealOut
.ChannelName
[1] = FrontRight
;
1528 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1529 device
->RealOut
.ChannelName
[1] = FrontRight
;
1530 device
->RealOut
.ChannelName
[2] = BackLeft
;
1531 device
->RealOut
.ChannelName
[3] = BackRight
;
1534 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1535 device
->RealOut
.ChannelName
[1] = FrontRight
;
1536 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1537 device
->RealOut
.ChannelName
[3] = LFE
;
1538 device
->RealOut
.ChannelName
[4] = SideLeft
;
1539 device
->RealOut
.ChannelName
[5] = SideRight
;
1542 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1543 device
->RealOut
.ChannelName
[1] = FrontRight
;
1544 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1545 device
->RealOut
.ChannelName
[3] = LFE
;
1546 device
->RealOut
.ChannelName
[4] = BackLeft
;
1547 device
->RealOut
.ChannelName
[5] = BackRight
;
1550 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1551 device
->RealOut
.ChannelName
[1] = FrontRight
;
1552 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1553 device
->RealOut
.ChannelName
[3] = LFE
;
1554 device
->RealOut
.ChannelName
[4] = BackCenter
;
1555 device
->RealOut
.ChannelName
[5] = SideLeft
;
1556 device
->RealOut
.ChannelName
[6] = SideRight
;
1559 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1560 device
->RealOut
.ChannelName
[1] = FrontRight
;
1561 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1562 device
->RealOut
.ChannelName
[3] = LFE
;
1563 device
->RealOut
.ChannelName
[4] = BackLeft
;
1564 device
->RealOut
.ChannelName
[5] = BackRight
;
1565 device
->RealOut
.ChannelName
[6] = SideLeft
;
1566 device
->RealOut
.ChannelName
[7] = SideRight
;
1569 device
->RealOut
.ChannelName
[0] = Aux0
;
1570 if(device
->AmbiOrder
> 0)
1572 device
->RealOut
.ChannelName
[1] = Aux1
;
1573 device
->RealOut
.ChannelName
[2] = Aux2
;
1574 device
->RealOut
.ChannelName
[3] = Aux3
;
1576 if(device
->AmbiOrder
> 1)
1578 device
->RealOut
.ChannelName
[4] = Aux4
;
1579 device
->RealOut
.ChannelName
[5] = Aux5
;
1580 device
->RealOut
.ChannelName
[6] = Aux6
;
1581 device
->RealOut
.ChannelName
[7] = Aux7
;
1582 device
->RealOut
.ChannelName
[8] = Aux8
;
1584 if(device
->AmbiOrder
> 2)
1586 device
->RealOut
.ChannelName
[9] = Aux9
;
1587 device
->RealOut
.ChannelName
[10] = Aux10
;
1588 device
->RealOut
.ChannelName
[11] = Aux11
;
1589 device
->RealOut
.ChannelName
[12] = Aux12
;
1590 device
->RealOut
.ChannelName
[13] = Aux13
;
1591 device
->RealOut
.ChannelName
[14] = Aux14
;
1592 device
->RealOut
.ChannelName
[15] = Aux15
;
1598 /* SetDefaultChannelOrder
1600 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1602 void SetDefaultChannelOrder(ALCdevice
*device
)
1606 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1607 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1609 switch(device
->FmtChans
)
1612 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1613 device
->RealOut
.ChannelName
[1] = FrontRight
;
1614 device
->RealOut
.ChannelName
[2] = BackLeft
;
1615 device
->RealOut
.ChannelName
[3] = BackRight
;
1616 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1617 device
->RealOut
.ChannelName
[5] = LFE
;
1620 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1621 device
->RealOut
.ChannelName
[1] = FrontRight
;
1622 device
->RealOut
.ChannelName
[2] = BackLeft
;
1623 device
->RealOut
.ChannelName
[3] = BackRight
;
1624 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1625 device
->RealOut
.ChannelName
[5] = LFE
;
1626 device
->RealOut
.ChannelName
[6] = SideLeft
;
1627 device
->RealOut
.ChannelName
[7] = SideRight
;
1630 /* Same as WFX order */
1637 SetDefaultWFXChannelOrder(device
);
1642 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1643 extern inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
);
1646 /* ALCcontext_DeferUpdates
1648 * Defers/suspends updates for the given context's listener and sources. This
1649 * does *NOT* stop mixing, but rather prevents certain property changes from
1652 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1654 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1657 /* ALCcontext_ProcessUpdates
1659 * Resumes update processing after being deferred.
1661 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1663 ReadLock(&context
->PropLock
);
1664 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1666 /* Tell the mixer to stop applying updates, then wait for any active
1667 * updating to finish, before providing updates.
1669 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1670 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1673 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1674 UpdateContextProps(context
);
1675 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1676 UpdateListenerProps(context
);
1677 UpdateAllEffectSlotProps(context
);
1678 UpdateAllSourceProps(context
);
1680 /* Now with all updates declared, let the mixer continue applying them
1681 * so they all happen at once.
1683 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1685 ReadUnlock(&context
->PropLock
);
1691 * Stores the latest ALC device error
1693 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1695 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1699 /* DebugBreak() will cause an exception if there is no debugger */
1700 if(IsDebuggerPresent())
1702 #elif defined(SIGTRAP)
1708 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1710 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1714 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1716 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1717 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1722 * Updates the device's base clock time with however many samples have been
1723 * done. This is used so frequency changes on the device don't cause the time
1724 * to jump forward or back. Must not be called while the device is running/
1727 static inline void UpdateClockBase(ALCdevice
*device
)
1729 IncrementRef(&device
->MixCount
);
1730 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1731 device
->SamplesDone
= 0;
1732 IncrementRef(&device
->MixCount
);
1735 /* UpdateDeviceParams
1737 * Updates device parameters according to the attribute list (caller is
1738 * responsible for holding the list lock).
1740 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1742 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1743 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1744 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1745 const ALsizei old_sends
= device
->NumAuxSends
;
1746 ALsizei new_sends
= device
->NumAuxSends
;
1747 enum DevFmtChannels oldChans
;
1748 enum DevFmtType oldType
;
1749 ALboolean update_failed
;
1750 ALCsizei hrtf_id
= -1;
1751 ALCcontext
*context
;
1757 // Check for attributes
1758 if(device
->Type
== Loopback
)
1760 ALCsizei numMono
, numStereo
, numSends
;
1761 ALCenum alayout
= AL_NONE
;
1762 ALCenum ascale
= AL_NONE
;
1763 ALCenum schans
= AL_NONE
;
1764 ALCenum stype
= AL_NONE
;
1765 ALCsizei attrIdx
= 0;
1766 ALCsizei aorder
= 0;
1771 WARN("Missing attributes for loopback device\n");
1772 return ALC_INVALID_VALUE
;
1775 numMono
= device
->NumMonoSources
;
1776 numStereo
= device
->NumStereoSources
;
1777 numSends
= old_sends
;
1779 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1780 while(attrList
[attrIdx
])
1782 switch(attrList
[attrIdx
])
1784 case ALC_FORMAT_CHANNELS_SOFT
:
1785 schans
= attrList
[attrIdx
+ 1];
1786 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1787 if(!IsValidALCChannels(schans
))
1788 return ALC_INVALID_VALUE
;
1791 case ALC_FORMAT_TYPE_SOFT
:
1792 stype
= attrList
[attrIdx
+ 1];
1793 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1794 if(!IsValidALCType(stype
))
1795 return ALC_INVALID_VALUE
;
1799 freq
= attrList
[attrIdx
+ 1];
1800 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1801 if(freq
< MIN_OUTPUT_RATE
)
1802 return ALC_INVALID_VALUE
;
1805 case ALC_AMBISONIC_LAYOUT_SOFT
:
1806 alayout
= attrList
[attrIdx
+ 1];
1807 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1808 if(!IsValidAmbiLayout(alayout
))
1809 return ALC_INVALID_VALUE
;
1812 case ALC_AMBISONIC_SCALING_SOFT
:
1813 ascale
= attrList
[attrIdx
+ 1];
1814 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1815 if(!IsValidAmbiScaling(ascale
))
1816 return ALC_INVALID_VALUE
;
1819 case ALC_AMBISONIC_ORDER_SOFT
:
1820 aorder
= attrList
[attrIdx
+ 1];
1821 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1822 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1823 return ALC_INVALID_VALUE
;
1826 case ALC_MONO_SOURCES
:
1827 numMono
= attrList
[attrIdx
+ 1];
1828 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1829 numMono
= maxi(numMono
, 0);
1832 case ALC_STEREO_SOURCES
:
1833 numStereo
= attrList
[attrIdx
+ 1];
1834 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1835 numStereo
= maxi(numStereo
, 0);
1838 case ALC_MAX_AUXILIARY_SENDS
:
1839 numSends
= attrList
[attrIdx
+ 1];
1840 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1841 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1845 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1846 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1847 hrtf_appreq
= Hrtf_Disable
;
1848 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1849 hrtf_appreq
= Hrtf_Enable
;
1851 hrtf_appreq
= Hrtf_Default
;
1854 case ALC_HRTF_ID_SOFT
:
1855 hrtf_id
= attrList
[attrIdx
+ 1];
1856 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1859 case ALC_OUTPUT_LIMITER_SOFT
:
1860 gainLimiter
= attrList
[attrIdx
+ 1];
1861 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1865 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1866 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1874 if(!schans
|| !stype
|| !freq
)
1876 WARN("Missing format for loopback device\n");
1877 return ALC_INVALID_VALUE
;
1879 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1881 WARN("Missing ambisonic info for loopback device\n");
1882 return ALC_INVALID_VALUE
;
1885 if((device
->Flags
&DEVICE_RUNNING
))
1886 V0(device
->Backend
,stop
)();
1887 device
->Flags
&= ~DEVICE_RUNNING
;
1889 UpdateClockBase(device
);
1891 device
->Frequency
= freq
;
1892 device
->FmtChans
= schans
;
1893 device
->FmtType
= stype
;
1894 if(schans
== ALC_BFORMAT3D_SOFT
)
1896 device
->AmbiOrder
= aorder
;
1897 device
->AmbiLayout
= alayout
;
1898 device
->AmbiScale
= ascale
;
1901 if(numMono
> INT_MAX
-numStereo
)
1902 numMono
= INT_MAX
-numStereo
;
1903 numMono
+= numStereo
;
1904 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1910 numMono
= maxi(numMono
, 256);
1911 numStereo
= mini(numStereo
, numMono
);
1912 numMono
-= numStereo
;
1913 device
->SourcesMax
= numMono
+ numStereo
;
1915 device
->NumMonoSources
= numMono
;
1916 device
->NumStereoSources
= numStereo
;
1918 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1919 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1921 new_sends
= numSends
;
1923 else if(attrList
&& attrList
[0])
1925 ALCsizei numMono
, numStereo
, numSends
;
1926 ALCsizei attrIdx
= 0;
1929 /* If a context is already running on the device, stop playback so the
1930 * device attributes can be updated. */
1931 if((device
->Flags
&DEVICE_RUNNING
))
1932 V0(device
->Backend
,stop
)();
1933 device
->Flags
&= ~DEVICE_RUNNING
;
1935 UpdateClockBase(device
);
1937 freq
= device
->Frequency
;
1938 numMono
= device
->NumMonoSources
;
1939 numStereo
= device
->NumStereoSources
;
1940 numSends
= old_sends
;
1942 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1943 while(attrList
[attrIdx
])
1945 switch(attrList
[attrIdx
])
1948 freq
= attrList
[attrIdx
+ 1];
1949 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1950 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1953 case ALC_MONO_SOURCES
:
1954 numMono
= attrList
[attrIdx
+ 1];
1955 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1956 numMono
= maxi(numMono
, 0);
1959 case ALC_STEREO_SOURCES
:
1960 numStereo
= attrList
[attrIdx
+ 1];
1961 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1962 numStereo
= maxi(numStereo
, 0);
1965 case ALC_MAX_AUXILIARY_SENDS
:
1966 numSends
= attrList
[attrIdx
+ 1];
1967 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1968 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1972 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1973 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1974 hrtf_appreq
= Hrtf_Disable
;
1975 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1976 hrtf_appreq
= Hrtf_Enable
;
1978 hrtf_appreq
= Hrtf_Default
;
1981 case ALC_HRTF_ID_SOFT
:
1982 hrtf_id
= attrList
[attrIdx
+ 1];
1983 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1986 case ALC_OUTPUT_LIMITER_SOFT
:
1987 gainLimiter
= attrList
[attrIdx
+ 1];
1988 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1992 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1993 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
2001 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2002 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2004 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2006 /* SSE and Neon do best with the update size being a multiple of 4 */
2007 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2008 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2010 device
->Frequency
= freq
;
2012 if(numMono
> INT_MAX
-numStereo
)
2013 numMono
= INT_MAX
-numStereo
;
2014 numMono
+= numStereo
;
2015 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2021 numMono
= maxi(numMono
, 256);
2022 numStereo
= mini(numStereo
, numMono
);
2023 numMono
-= numStereo
;
2024 device
->SourcesMax
= numMono
+ numStereo
;
2026 device
->NumMonoSources
= numMono
;
2027 device
->NumStereoSources
= numStereo
;
2029 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2030 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2032 new_sends
= numSends
;
2035 if((device
->Flags
&DEVICE_RUNNING
))
2036 return ALC_NO_ERROR
;
2038 al_free(device
->Uhj_Encoder
);
2039 device
->Uhj_Encoder
= NULL
;
2041 al_free(device
->Bs2b
);
2042 device
->Bs2b
= NULL
;
2044 al_free(device
->ChannelDelay
[0].Buffer
);
2045 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2047 device
->ChannelDelay
[i
].Length
= 0;
2048 device
->ChannelDelay
[i
].Buffer
= NULL
;
2051 al_free(device
->Dry
.Buffer
);
2052 device
->Dry
.Buffer
= NULL
;
2053 device
->Dry
.NumChannels
= 0;
2054 device
->FOAOut
.Buffer
= NULL
;
2055 device
->FOAOut
.NumChannels
= 0;
2056 device
->RealOut
.Buffer
= NULL
;
2057 device
->RealOut
.NumChannels
= 0;
2059 UpdateClockBase(device
);
2061 device
->DitherSeed
= DITHER_RNG_SEED
;
2063 /*************************************************************************
2064 * Update device format request if HRTF is requested
2066 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2067 if(device
->Type
!= Loopback
)
2070 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2072 if(strcasecmp(hrtf
, "true") == 0)
2073 hrtf_userreq
= Hrtf_Enable
;
2074 else if(strcasecmp(hrtf
, "false") == 0)
2075 hrtf_userreq
= Hrtf_Disable
;
2076 else if(strcasecmp(hrtf
, "auto") != 0)
2077 ERR("Unexpected hrtf value: %s\n", hrtf
);
2080 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2082 struct Hrtf
*hrtf
= NULL
;
2083 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2085 VECTOR_DEINIT(device
->HrtfList
);
2086 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2088 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2090 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2091 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2093 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2098 device
->FmtChans
= DevFmtStereo
;
2099 device
->Frequency
= hrtf
->sampleRate
;
2100 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2101 if(device
->HrtfHandle
)
2102 Hrtf_DecRef(device
->HrtfHandle
);
2103 device
->HrtfHandle
= hrtf
;
2107 hrtf_userreq
= Hrtf_Default
;
2108 hrtf_appreq
= Hrtf_Disable
;
2109 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2114 oldFreq
= device
->Frequency
;
2115 oldChans
= device
->FmtChans
;
2116 oldType
= device
->FmtType
;
2118 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2119 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2120 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2121 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2122 device
->UpdateSize
, device
->NumUpdates
2125 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2126 return ALC_INVALID_DEVICE
;
2128 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2130 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2131 DevFmtChannelsString(device
->FmtChans
));
2132 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2134 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2136 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2137 DevFmtTypeString(device
->FmtType
));
2138 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2140 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2142 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2143 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2146 if((device
->UpdateSize
&3) != 0)
2148 if((CPUCapFlags
&CPU_CAP_SSE
))
2149 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2150 if((CPUCapFlags
&CPU_CAP_NEON
))
2151 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2154 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2155 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2156 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2159 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2160 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2161 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2163 /* Allocate extra channels for any post-filter output. */
2164 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2165 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2167 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2168 device
->Dry
.Buffer
= al_calloc(16, size
);
2169 if(!device
->Dry
.Buffer
)
2171 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2172 return ALC_INVALID_DEVICE
;
2175 if(device
->RealOut
.NumChannels
!= 0)
2176 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2177 device
->FOAOut
.NumChannels
;
2180 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2181 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2184 if(device
->FOAOut
.NumChannels
!= 0)
2185 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2188 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2189 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2192 device
->NumAuxSends
= new_sends
;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2195 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2197 device
->DitherDepth
= 0.0f
;
2198 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2201 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2204 switch(device
->FmtType
)
2222 device
->DitherDepth
= (depth
> 0) ? powf(2.0f
, (ALfloat
)(depth
-1)) : 0.0f
;
2224 if(!(device
->DitherDepth
> 0.0f
))
2225 TRACE("Dithering disabled\n");
2227 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2228 device
->DitherDepth
);
2230 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2231 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2232 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2233 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2236 if(gainLimiter
!= ALC_FALSE
)
2238 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2240 al_free(device
->Limiter
);
2241 device
->Limiter
= CreateDeviceLimiter(device
);
2246 al_free(device
->Limiter
);
2247 device
->Limiter
= NULL
;
2249 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2251 /* Need to delay returning failure until replacement Send arrays have been
2252 * allocated with the appropriate size.
2254 update_failed
= AL_FALSE
;
2256 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2259 struct ALvoiceProps
*vprops
;
2262 if(context
->DefaultSlot
)
2264 ALeffectslot
*slot
= context
->DefaultSlot
;
2265 ALeffectState
*state
= slot
->Effect
.State
;
2267 state
->OutBuffer
= device
->Dry
.Buffer
;
2268 state
->OutChannels
= device
->Dry
.NumChannels
;
2269 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2270 update_failed
= AL_TRUE
;
2272 UpdateEffectSlotProps(slot
, context
);
2275 WriteLock(&context
->PropLock
);
2276 LockUIntMapRead(&context
->EffectSlotMap
);
2277 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2279 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2280 ALeffectState
*state
= slot
->Effect
.State
;
2282 state
->OutBuffer
= device
->Dry
.Buffer
;
2283 state
->OutChannels
= device
->Dry
.NumChannels
;
2284 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2285 update_failed
= AL_TRUE
;
2287 UpdateEffectSlotProps(slot
, context
);
2289 UnlockUIntMapRead(&context
->EffectSlotMap
);
2291 LockUIntMapRead(&context
->SourceMap
);
2292 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2293 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2295 ALsource
*source
= context
->SourceMap
.values
[pos
];
2297 if(old_sends
!= device
->NumAuxSends
)
2299 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2302 memcpy(sends
, source
->Send
,
2303 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2305 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2307 if(source
->Send
[s
].Slot
)
2308 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2309 source
->Send
[s
].Slot
= NULL
;
2311 al_free(source
->Send
);
2312 source
->Send
= sends
;
2313 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2315 source
->Send
[s
].Slot
= NULL
;
2316 source
->Send
[s
].Gain
= 1.0f
;
2317 source
->Send
[s
].GainHF
= 1.0f
;
2318 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2319 source
->Send
[s
].GainLF
= 1.0f
;
2320 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2324 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2327 /* Clear any pre-existing voice property structs, in case the number of
2328 * auxiliary sends is changing. Active sources will have updates
2329 * respecified in UpdateAllSourceProps.
2331 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2334 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2339 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2340 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2342 ALvoice
*voice
= context
->Voices
[pos
];
2344 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2346 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2349 if(device
->AvgSpeakerDist
> 0.0f
)
2351 /* Reinitialize the NFC filters for new parameters. */
2352 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2353 (device
->AvgSpeakerDist
* device
->Frequency
);
2354 for(i
= 0;i
< voice
->NumChannels
;i
++)
2356 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2357 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2358 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2362 UnlockUIntMapRead(&context
->SourceMap
);
2364 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2365 UpdateContextProps(context
);
2366 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2367 UpdateListenerProps(context
);
2368 UpdateAllSourceProps(context
);
2369 WriteUnlock(&context
->PropLock
);
2371 context
= context
->next
;
2375 return ALC_INVALID_DEVICE
;
2377 if(!(device
->Flags
&DEVICE_PAUSED
))
2379 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2380 return ALC_INVALID_DEVICE
;
2381 device
->Flags
|= DEVICE_RUNNING
;
2384 return ALC_NO_ERROR
;
2389 * Frees the device structure, and destroys any objects the app failed to
2390 * delete. Called once there's no more references on the device.
2392 static ALCvoid
FreeDevice(ALCdevice
*device
)
2396 TRACE("%p\n", device
);
2398 V0(device
->Backend
,close
)();
2399 DELETE_OBJ(device
->Backend
);
2400 device
->Backend
= NULL
;
2402 almtx_destroy(&device
->BackendLock
);
2404 if(device
->BufferMap
.size
> 0)
2406 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2407 (device
->BufferMap
.size
==1)?"":"s");
2408 ReleaseALBuffers(device
);
2410 ResetUIntMap(&device
->BufferMap
);
2412 if(device
->EffectMap
.size
> 0)
2414 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2415 (device
->EffectMap
.size
==1)?"":"s");
2416 ReleaseALEffects(device
);
2418 ResetUIntMap(&device
->EffectMap
);
2420 if(device
->FilterMap
.size
> 0)
2422 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2423 (device
->FilterMap
.size
==1)?"":"s");
2424 ReleaseALFilters(device
);
2426 ResetUIntMap(&device
->FilterMap
);
2428 AL_STRING_DEINIT(device
->HrtfName
);
2429 FreeHrtfList(&device
->HrtfList
);
2430 if(device
->HrtfHandle
)
2431 Hrtf_DecRef(device
->HrtfHandle
);
2432 device
->HrtfHandle
= NULL
;
2433 al_free(device
->Hrtf
);
2434 device
->Hrtf
= NULL
;
2436 al_free(device
->Bs2b
);
2437 device
->Bs2b
= NULL
;
2439 al_free(device
->Uhj_Encoder
);
2440 device
->Uhj_Encoder
= NULL
;
2442 bformatdec_free(device
->AmbiDecoder
);
2443 device
->AmbiDecoder
= NULL
;
2445 ambiup_free(device
->AmbiUp
);
2446 device
->AmbiUp
= NULL
;
2448 al_free(device
->Stablizer
);
2449 device
->Stablizer
= NULL
;
2451 al_free(device
->Limiter
);
2452 device
->Limiter
= NULL
;
2454 al_free(device
->ChannelDelay
[0].Buffer
);
2455 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2457 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2458 device
->ChannelDelay
[i
].Length
= 0;
2459 device
->ChannelDelay
[i
].Buffer
= NULL
;
2462 AL_STRING_DEINIT(device
->DeviceName
);
2464 al_free(device
->Dry
.Buffer
);
2465 device
->Dry
.Buffer
= NULL
;
2466 device
->Dry
.NumChannels
= 0;
2467 device
->FOAOut
.Buffer
= NULL
;
2468 device
->FOAOut
.NumChannels
= 0;
2469 device
->RealOut
.Buffer
= NULL
;
2470 device
->RealOut
.NumChannels
= 0;
2476 void ALCdevice_IncRef(ALCdevice
*device
)
2479 ref
= IncrementRef(&device
->ref
);
2480 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2483 void ALCdevice_DecRef(ALCdevice
*device
)
2486 ref
= DecrementRef(&device
->ref
);
2487 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2488 if(ref
== 0) FreeDevice(device
);
2493 * Checks if the device handle is valid, and increments its ref count if so.
2495 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2497 ALCdevice
*tmpDevice
;
2500 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2503 if(tmpDevice
== *device
)
2505 ALCdevice_IncRef(tmpDevice
);
2509 tmpDevice
= tmpDevice
->next
;
2520 * Initializes context fields
2522 static ALvoid
InitContext(ALCcontext
*Context
)
2524 ALlistener
*listener
= Context
->Listener
;
2525 struct ALeffectslotArray
*auxslots
;
2527 //Initialise listener
2528 listener
->Gain
= 1.0f
;
2529 listener
->Position
[0] = 0.0f
;
2530 listener
->Position
[1] = 0.0f
;
2531 listener
->Position
[2] = 0.0f
;
2532 listener
->Velocity
[0] = 0.0f
;
2533 listener
->Velocity
[1] = 0.0f
;
2534 listener
->Velocity
[2] = 0.0f
;
2535 listener
->Forward
[0] = 0.0f
;
2536 listener
->Forward
[1] = 0.0f
;
2537 listener
->Forward
[2] = -1.0f
;
2538 listener
->Up
[0] = 0.0f
;
2539 listener
->Up
[1] = 1.0f
;
2540 listener
->Up
[2] = 0.0f
;
2541 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2543 ATOMIC_INIT(&listener
->Update
, NULL
);
2546 InitRef(&Context
->UpdateCount
, 0);
2547 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2548 Context
->GainBoost
= 1.0f
;
2549 RWLockInit(&Context
->PropLock
);
2550 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2551 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2552 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2554 if(Context
->DefaultSlot
)
2556 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2557 auxslots
->count
= 1;
2558 auxslots
->slot
[0] = Context
->DefaultSlot
;
2562 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2563 auxslots
->count
= 0;
2565 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2568 Context
->DistanceModel
= DefaultDistanceModel
;
2569 Context
->SourceDistanceModel
= AL_FALSE
;
2570 Context
->DopplerFactor
= 1.0f
;
2571 Context
->DopplerVelocity
= 1.0f
;
2572 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2573 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2574 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2575 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2577 ATOMIC_INIT(&Context
->Update
, NULL
);
2578 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2579 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2580 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2581 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2583 Context
->ExtensionList
= alExtList
;
2586 listener
->Params
.Matrix
= IdentityMatrixf
;
2587 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2588 listener
->Params
.Gain
= listener
->Gain
;
2589 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2590 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2591 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2592 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2593 listener
->Params
.MetersPerUnit
;
2594 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2595 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2601 * Cleans up the context, and destroys any remaining objects the app failed to
2602 * delete. Called once there's no more references on the context.
2604 static void FreeContext(ALCcontext
*context
)
2606 ALlistener
*listener
= context
->Listener
;
2607 struct ALeffectslotArray
*auxslots
;
2608 struct ALeffectslotProps
*eprops
;
2609 struct ALlistenerProps
*lprops
;
2610 struct ALcontextProps
*cprops
;
2611 struct ALvoiceProps
*vprops
;
2615 TRACE("%p\n", context
);
2617 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2619 TRACE("Freed unapplied context update %p\n", cprops
);
2624 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2627 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2632 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2634 if(context
->DefaultSlot
)
2636 DeinitEffectSlot(context
->DefaultSlot
);
2637 context
->DefaultSlot
= NULL
;
2640 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2643 if(context
->SourceMap
.size
> 0)
2645 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2646 (context
->SourceMap
.size
==1)?"":"s");
2647 ReleaseALSources(context
);
2649 ResetUIntMap(&context
->SourceMap
);
2652 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2655 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2656 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2661 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2662 if(context
->EffectSlotMap
.size
> 0)
2664 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2665 (context
->EffectSlotMap
.size
==1)?"":"s");
2666 ReleaseALAuxiliaryEffectSlots(context
);
2668 ResetUIntMap(&context
->EffectSlotMap
);
2671 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2674 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2679 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2681 for(i
= 0;i
< context
->VoiceCount
;i
++)
2682 DeinitVoice(context
->Voices
[i
]);
2683 al_free(context
->Voices
);
2684 context
->Voices
= NULL
;
2685 context
->VoiceCount
= 0;
2686 context
->MaxVoices
= 0;
2688 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2690 TRACE("Freed unapplied listener update %p\n", lprops
);
2694 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2697 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2702 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2704 ALCdevice_DecRef(context
->Device
);
2705 context
->Device
= NULL
;
2707 //Invalidate context
2708 memset(context
, 0, sizeof(ALCcontext
));
2714 * Removes the context reference from the given device and removes it from
2715 * being current on the running thread or globally. Returns true if other
2716 * contexts still exist on the device.
2718 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2720 ALCcontext
*origctx
, *newhead
;
2723 if(altss_get(LocalContext
) == context
)
2725 WARN("%p released while current on thread\n", context
);
2726 altss_set(LocalContext
, NULL
);
2727 ALCcontext_DecRef(context
);
2731 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2732 ALCcontext_DecRef(context
);
2734 ALCdevice_Lock(device
);
2736 newhead
= context
->next
;
2737 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2739 ALCcontext
*volatile*list
= &origctx
->next
;
2742 if(*list
== context
)
2744 *list
= (*list
)->next
;
2747 list
= &(*list
)->next
;
2752 ALCdevice_Unlock(device
);
2754 ALCcontext_DecRef(context
);
2758 void ALCcontext_IncRef(ALCcontext
*context
)
2760 uint ref
= IncrementRef(&context
->ref
);
2761 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2764 void ALCcontext_DecRef(ALCcontext
*context
)
2766 uint ref
= DecrementRef(&context
->ref
);
2767 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2768 if(ref
== 0) FreeContext(context
);
2771 static void ReleaseThreadCtx(void *ptr
)
2773 ALCcontext
*context
= ptr
;
2774 uint ref
= DecrementRef(&context
->ref
);
2775 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2776 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2781 * Checks that the given context is valid, and increments its reference count.
2783 static ALCboolean
VerifyContext(ALCcontext
**context
)
2788 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2791 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2796 ALCcontext_IncRef(ctx
);
2813 * Returns the currently active context for this thread, and adds a reference
2814 * without locking it.
2816 ALCcontext
*GetContextRef(void)
2818 ALCcontext
*context
;
2820 context
= altss_get(LocalContext
);
2822 ALCcontext_IncRef(context
);
2826 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2828 ALCcontext_IncRef(context
);
2836 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2838 ALCdevice
*device
= context
->Device
;
2839 ALsizei num_sends
= device
->NumAuxSends
;
2840 struct ALvoiceProps
*props
;
2841 size_t sizeof_props
;
2842 size_t sizeof_voice
;
2848 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2851 /* Allocate the voice pointers, voices, and the voices' stored source
2852 * property set (including the dynamically-sized Send[] array) in one
2855 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2856 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2857 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2859 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2860 /* The voice and property objects are stored interleaved since they're
2863 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2864 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2868 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2869 const ALsizei s_count
= mini(old_sends
, num_sends
);
2871 for(;v
< v_count
;v
++)
2873 ALvoice
*old_voice
= context
->Voices
[v
];
2876 /* Copy the old voice data and source property set to the new
2879 *voice
= *old_voice
;
2880 for(i
= 0;i
< s_count
;i
++)
2881 voice
->Send
[i
] = old_voice
->Send
[i
];
2882 *props
= *(old_voice
->Props
);
2883 for(i
= 0;i
< s_count
;i
++)
2884 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2886 /* Set this voice's property set pointer and voice reference. */
2887 voice
->Props
= props
;
2890 /* Increment pointers to the next storage space. */
2891 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2892 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2894 /* Deinit any left over voices that weren't copied over to the new
2895 * array. NOTE: If this does anything, v equals num_voices and
2896 * num_voices is less than VoiceCount, so the following loop won't do
2899 for(;v
< context
->VoiceCount
;v
++)
2900 DeinitVoice(context
->Voices
[v
]);
2902 /* Finish setting the voices' property set pointers and references. */
2903 for(;v
< num_voices
;v
++)
2905 ATOMIC_INIT(&voice
->Update
, NULL
);
2907 voice
->Props
= props
;
2910 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2911 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2914 al_free(context
->Voices
);
2915 context
->Voices
= voices
;
2916 context
->MaxVoices
= num_voices
;
2917 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2921 /************************************************
2922 * Standard ALC functions
2923 ************************************************/
2927 * Return last ALC generated error code for the given device
2929 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2933 if(VerifyDevice(&device
))
2935 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2936 ALCdevice_DecRef(device
);
2939 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2945 /* alcSuspendContext
2947 * Suspends updates for the given context
2949 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2954 if(!VerifyContext(&context
))
2955 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2958 ALCcontext_DeferUpdates(context
);
2959 ALCcontext_DecRef(context
);
2963 /* alcProcessContext
2965 * Resumes processing updates for the given context
2967 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2972 if(!VerifyContext(&context
))
2973 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2976 ALCcontext_ProcessUpdates(context
);
2977 ALCcontext_DecRef(context
);
2984 * Returns information about the device, and error strings
2986 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2988 const ALCchar
*value
= NULL
;
2996 case ALC_INVALID_ENUM
:
2997 value
= alcErrInvalidEnum
;
3000 case ALC_INVALID_VALUE
:
3001 value
= alcErrInvalidValue
;
3004 case ALC_INVALID_DEVICE
:
3005 value
= alcErrInvalidDevice
;
3008 case ALC_INVALID_CONTEXT
:
3009 value
= alcErrInvalidContext
;
3012 case ALC_OUT_OF_MEMORY
:
3013 value
= alcErrOutOfMemory
;
3016 case ALC_DEVICE_SPECIFIER
:
3017 value
= alcDefaultName
;
3020 case ALC_ALL_DEVICES_SPECIFIER
:
3021 if(VerifyDevice(&Device
))
3023 value
= alstr_get_cstr(Device
->DeviceName
);
3024 ALCdevice_DecRef(Device
);
3028 ProbeAllDevicesList();
3029 value
= alstr_get_cstr(alcAllDevicesList
);
3033 case ALC_CAPTURE_DEVICE_SPECIFIER
:
3034 if(VerifyDevice(&Device
))
3036 value
= alstr_get_cstr(Device
->DeviceName
);
3037 ALCdevice_DecRef(Device
);
3041 ProbeCaptureDeviceList();
3042 value
= alstr_get_cstr(alcCaptureDeviceList
);
3046 /* Default devices are always first in the list */
3047 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3048 value
= alcDefaultName
;
3051 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3052 if(alstr_empty(alcAllDevicesList
))
3053 ProbeAllDevicesList();
3055 VerifyDevice(&Device
);
3057 free(alcDefaultAllDevicesSpecifier
);
3058 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3059 if(!alcDefaultAllDevicesSpecifier
)
3060 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3062 value
= alcDefaultAllDevicesSpecifier
;
3063 if(Device
) ALCdevice_DecRef(Device
);
3066 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3067 if(alstr_empty(alcCaptureDeviceList
))
3068 ProbeCaptureDeviceList();
3070 VerifyDevice(&Device
);
3072 free(alcCaptureDefaultDeviceSpecifier
);
3073 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3074 if(!alcCaptureDefaultDeviceSpecifier
)
3075 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3077 value
= alcCaptureDefaultDeviceSpecifier
;
3078 if(Device
) ALCdevice_DecRef(Device
);
3081 case ALC_EXTENSIONS
:
3082 if(!VerifyDevice(&Device
))
3083 value
= alcNoDeviceExtList
;
3086 value
= alcExtensionList
;
3087 ALCdevice_DecRef(Device
);
3091 case ALC_HRTF_SPECIFIER_SOFT
:
3092 if(!VerifyDevice(&Device
))
3093 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3096 almtx_lock(&Device
->BackendLock
);
3097 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3098 almtx_unlock(&Device
->BackendLock
);
3099 ALCdevice_DecRef(Device
);
3104 VerifyDevice(&Device
);
3105 alcSetError(Device
, ALC_INVALID_ENUM
);
3106 if(Device
) ALCdevice_DecRef(Device
);
3114 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3116 if(device
->Type
== Capture
) return 9;
3117 if(device
->Type
== Loopback
&& device
->FmtChans
== DevFmtAmbi3D
)
3122 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3126 if(size
<= 0 || values
== NULL
)
3128 alcSetError(device
, ALC_INVALID_VALUE
);
3136 case ALC_MAJOR_VERSION
:
3137 values
[0] = alcMajorVersion
;
3139 case ALC_MINOR_VERSION
:
3140 values
[0] = alcMinorVersion
;
3143 case ALC_ATTRIBUTES_SIZE
:
3144 case ALC_ALL_ATTRIBUTES
:
3148 case ALC_MONO_SOURCES
:
3149 case ALC_STEREO_SOURCES
:
3150 case ALC_CAPTURE_SAMPLES
:
3151 case ALC_FORMAT_CHANNELS_SOFT
:
3152 case ALC_FORMAT_TYPE_SOFT
:
3153 case ALC_AMBISONIC_LAYOUT_SOFT
:
3154 case ALC_AMBISONIC_SCALING_SOFT
:
3155 case ALC_AMBISONIC_ORDER_SOFT
:
3156 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3157 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3161 alcSetError(NULL
, ALC_INVALID_ENUM
);
3167 if(device
->Type
== Capture
)
3171 case ALC_ATTRIBUTES_SIZE
:
3172 values
[0] = NumAttrsForDevice(device
);
3175 case ALC_ALL_ATTRIBUTES
:
3176 if(size
< NumAttrsForDevice(device
))
3178 alcSetError(device
, ALC_INVALID_VALUE
);
3183 almtx_lock(&device
->BackendLock
);
3184 values
[i
++] = ALC_MAJOR_VERSION
;
3185 values
[i
++] = alcMajorVersion
;
3186 values
[i
++] = ALC_MINOR_VERSION
;
3187 values
[i
++] = alcMinorVersion
;
3188 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3189 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3190 values
[i
++] = ALC_CONNECTED
;
3191 values
[i
++] = device
->Connected
;
3192 almtx_unlock(&device
->BackendLock
);
3197 case ALC_MAJOR_VERSION
:
3198 values
[0] = alcMajorVersion
;
3200 case ALC_MINOR_VERSION
:
3201 values
[0] = alcMinorVersion
;
3204 case ALC_CAPTURE_SAMPLES
:
3205 almtx_lock(&device
->BackendLock
);
3206 values
[0] = V0(device
->Backend
,availableSamples
)();
3207 almtx_unlock(&device
->BackendLock
);
3211 values
[0] = device
->Connected
;
3215 alcSetError(device
, ALC_INVALID_ENUM
);
3224 case ALC_ATTRIBUTES_SIZE
:
3225 values
[0] = NumAttrsForDevice(device
);
3228 case ALC_ALL_ATTRIBUTES
:
3229 if(size
< NumAttrsForDevice(device
))
3231 alcSetError(device
, ALC_INVALID_VALUE
);
3236 almtx_lock(&device
->BackendLock
);
3237 values
[i
++] = ALC_MAJOR_VERSION
;
3238 values
[i
++] = alcMajorVersion
;
3239 values
[i
++] = ALC_MINOR_VERSION
;
3240 values
[i
++] = alcMinorVersion
;
3241 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3242 values
[i
++] = alcEFXMajorVersion
;
3243 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3244 values
[i
++] = alcEFXMinorVersion
;
3246 values
[i
++] = ALC_FREQUENCY
;
3247 values
[i
++] = device
->Frequency
;
3248 if(device
->Type
!= Loopback
)
3250 values
[i
++] = ALC_REFRESH
;
3251 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3253 values
[i
++] = ALC_SYNC
;
3254 values
[i
++] = ALC_FALSE
;
3258 if(device
->FmtChans
== DevFmtAmbi3D
)
3260 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3261 values
[i
++] = device
->AmbiLayout
;
3263 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3264 values
[i
++] = device
->AmbiScale
;
3266 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3267 values
[i
++] = device
->AmbiOrder
;
3270 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3271 values
[i
++] = device
->FmtChans
;
3273 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3274 values
[i
++] = device
->FmtType
;
3277 values
[i
++] = ALC_MONO_SOURCES
;
3278 values
[i
++] = device
->NumMonoSources
;
3280 values
[i
++] = ALC_STEREO_SOURCES
;
3281 values
[i
++] = device
->NumStereoSources
;
3283 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3284 values
[i
++] = device
->NumAuxSends
;
3286 values
[i
++] = ALC_HRTF_SOFT
;
3287 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3289 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3290 values
[i
++] = device
->HrtfStatus
;
3292 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3293 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3295 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3296 values
[i
++] = MAX_AMBI_ORDER
;
3297 almtx_unlock(&device
->BackendLock
);
3302 case ALC_MAJOR_VERSION
:
3303 values
[0] = alcMajorVersion
;
3306 case ALC_MINOR_VERSION
:
3307 values
[0] = alcMinorVersion
;
3310 case ALC_EFX_MAJOR_VERSION
:
3311 values
[0] = alcEFXMajorVersion
;
3314 case ALC_EFX_MINOR_VERSION
:
3315 values
[0] = alcEFXMinorVersion
;
3319 values
[0] = device
->Frequency
;
3323 if(device
->Type
== Loopback
)
3325 alcSetError(device
, ALC_INVALID_DEVICE
);
3328 almtx_lock(&device
->BackendLock
);
3329 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3330 almtx_unlock(&device
->BackendLock
);
3334 if(device
->Type
== Loopback
)
3336 alcSetError(device
, ALC_INVALID_DEVICE
);
3339 values
[0] = ALC_FALSE
;
3342 case ALC_FORMAT_CHANNELS_SOFT
:
3343 if(device
->Type
!= Loopback
)
3345 alcSetError(device
, ALC_INVALID_DEVICE
);
3348 values
[0] = device
->FmtChans
;
3351 case ALC_FORMAT_TYPE_SOFT
:
3352 if(device
->Type
!= Loopback
)
3354 alcSetError(device
, ALC_INVALID_DEVICE
);
3357 values
[0] = device
->FmtType
;
3360 case ALC_AMBISONIC_LAYOUT_SOFT
:
3361 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3363 alcSetError(device
, ALC_INVALID_DEVICE
);
3366 values
[0] = device
->AmbiLayout
;
3369 case ALC_AMBISONIC_SCALING_SOFT
:
3370 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3372 alcSetError(device
, ALC_INVALID_DEVICE
);
3375 values
[0] = device
->AmbiScale
;
3378 case ALC_AMBISONIC_ORDER_SOFT
:
3379 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3381 alcSetError(device
, ALC_INVALID_DEVICE
);
3384 values
[0] = device
->AmbiOrder
;
3387 case ALC_MONO_SOURCES
:
3388 values
[0] = device
->NumMonoSources
;
3391 case ALC_STEREO_SOURCES
:
3392 values
[0] = device
->NumStereoSources
;
3395 case ALC_MAX_AUXILIARY_SENDS
:
3396 values
[0] = device
->NumAuxSends
;
3400 values
[0] = device
->Connected
;
3404 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3407 case ALC_HRTF_STATUS_SOFT
:
3408 values
[0] = device
->HrtfStatus
;
3411 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3412 almtx_lock(&device
->BackendLock
);
3413 FreeHrtfList(&device
->HrtfList
);
3414 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3415 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3416 almtx_unlock(&device
->BackendLock
);
3419 case ALC_OUTPUT_LIMITER_SOFT
:
3420 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3423 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3424 values
[0] = MAX_AMBI_ORDER
;
3428 alcSetError(device
, ALC_INVALID_ENUM
);
3436 * Returns information about the device and the version of OpenAL
3438 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3440 VerifyDevice(&device
);
3441 if(size
<= 0 || values
== NULL
)
3442 alcSetError(device
, ALC_INVALID_VALUE
);
3444 GetIntegerv(device
, param
, size
, values
);
3445 if(device
) ALCdevice_DecRef(device
);
3448 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3453 VerifyDevice(&device
);
3454 if(size
<= 0 || values
== NULL
)
3455 alcSetError(device
, ALC_INVALID_VALUE
);
3456 else if(!device
|| device
->Type
== Capture
)
3458 ivals
= malloc(size
* sizeof(ALCint
));
3459 size
= GetIntegerv(device
, pname
, size
, ivals
);
3460 for(i
= 0;i
< size
;i
++)
3461 values
[i
] = ivals
[i
];
3464 else /* render device */
3473 case ALC_ATTRIBUTES_SIZE
:
3474 *values
= NumAttrsForDevice(device
)+4;
3477 case ALC_ALL_ATTRIBUTES
:
3478 if(size
< NumAttrsForDevice(device
)+4)
3479 alcSetError(device
, ALC_INVALID_VALUE
);
3483 almtx_lock(&device
->BackendLock
);
3484 values
[i
++] = ALC_FREQUENCY
;
3485 values
[i
++] = device
->Frequency
;
3487 if(device
->Type
!= Loopback
)
3489 values
[i
++] = ALC_REFRESH
;
3490 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3492 values
[i
++] = ALC_SYNC
;
3493 values
[i
++] = ALC_FALSE
;
3497 if(device
->FmtChans
== DevFmtAmbi3D
)
3499 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3500 values
[i
++] = device
->AmbiLayout
;
3502 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3503 values
[i
++] = device
->AmbiScale
;
3505 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3506 values
[i
++] = device
->AmbiOrder
;
3509 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3510 values
[i
++] = device
->FmtChans
;
3512 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3513 values
[i
++] = device
->FmtType
;
3516 values
[i
++] = ALC_MONO_SOURCES
;
3517 values
[i
++] = device
->NumMonoSources
;
3519 values
[i
++] = ALC_STEREO_SOURCES
;
3520 values
[i
++] = device
->NumStereoSources
;
3522 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3523 values
[i
++] = device
->NumAuxSends
;
3525 values
[i
++] = ALC_HRTF_SOFT
;
3526 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3528 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3529 values
[i
++] = device
->HrtfStatus
;
3531 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3532 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3534 clock
= V0(device
->Backend
,getClockLatency
)();
3535 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3536 values
[i
++] = clock
.ClockTime
;
3538 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3539 values
[i
++] = clock
.Latency
;
3540 almtx_unlock(&device
->BackendLock
);
3546 case ALC_DEVICE_CLOCK_SOFT
:
3547 almtx_lock(&device
->BackendLock
);
3549 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3551 basecount
= device
->ClockBase
;
3552 samplecount
= device
->SamplesDone
;
3553 } while(refcount
!= ReadRef(&device
->MixCount
));
3554 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3555 almtx_unlock(&device
->BackendLock
);
3558 case ALC_DEVICE_LATENCY_SOFT
:
3559 almtx_lock(&device
->BackendLock
);
3560 clock
= V0(device
->Backend
,getClockLatency
)();
3561 almtx_unlock(&device
->BackendLock
);
3562 *values
= clock
.Latency
;
3565 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3567 alcSetError(device
, ALC_INVALID_VALUE
);
3570 almtx_lock(&device
->BackendLock
);
3571 clock
= V0(device
->Backend
,getClockLatency
)();
3572 almtx_unlock(&device
->BackendLock
);
3573 values
[0] = clock
.ClockTime
;
3574 values
[1] = clock
.Latency
;
3579 ivals
= malloc(size
* sizeof(ALCint
));
3580 size
= GetIntegerv(device
, pname
, size
, ivals
);
3581 for(i
= 0;i
< size
;i
++)
3582 values
[i
] = ivals
[i
];
3588 ALCdevice_DecRef(device
);
3592 /* alcIsExtensionPresent
3594 * Determines if there is support for a particular extension
3596 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3598 ALCboolean bResult
= ALC_FALSE
;
3600 VerifyDevice(&device
);
3603 alcSetError(device
, ALC_INVALID_VALUE
);
3606 size_t len
= strlen(extName
);
3607 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3610 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3611 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3616 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3620 } while(isspace(*ptr
));
3625 ALCdevice_DecRef(device
);
3630 /* alcGetProcAddress
3632 * Retrieves the function address for a particular extension function
3634 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3636 ALCvoid
*ptr
= NULL
;
3640 VerifyDevice(&device
);
3641 alcSetError(device
, ALC_INVALID_VALUE
);
3642 if(device
) ALCdevice_DecRef(device
);
3647 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3649 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3651 ptr
= alcFunctions
[i
].address
;
3663 * Get the value for a particular ALC enumeration name
3665 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3671 VerifyDevice(&device
);
3672 alcSetError(device
, ALC_INVALID_VALUE
);
3673 if(device
) ALCdevice_DecRef(device
);
3678 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3680 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3682 val
= alcEnumerations
[i
].value
;
3694 * Create and attach a context to the given device.
3696 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3698 ALCcontext
*ALContext
;
3702 /* Explicitly hold the list lock while taking the BackendLock in case the
3703 * device is asynchronously destropyed, to ensure this new context is
3704 * properly cleaned up after being made.
3707 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3710 alcSetError(device
, ALC_INVALID_DEVICE
);
3711 if(device
) ALCdevice_DecRef(device
);
3714 almtx_lock(&device
->BackendLock
);
3717 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3719 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3720 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3722 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3725 almtx_unlock(&device
->BackendLock
);
3727 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3728 ALCdevice_DecRef(device
);
3732 InitRef(&ALContext
->ref
, 1);
3733 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3734 ALContext
->DefaultSlot
= NULL
;
3736 ALContext
->Voices
= NULL
;
3737 ALContext
->VoiceCount
= 0;
3738 ALContext
->MaxVoices
= 0;
3739 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3740 ALContext
->Device
= device
;
3742 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3744 almtx_unlock(&device
->BackendLock
);
3749 alcSetError(device
, err
);
3750 if(err
== ALC_INVALID_DEVICE
)
3752 V0(device
->Backend
,lock
)();
3753 aluHandleDisconnect(device
);
3754 V0(device
->Backend
,unlock
)();
3756 ALCdevice_DecRef(device
);
3759 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3761 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3763 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3764 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3765 aluInitEffectPanning(ALContext
->DefaultSlot
);
3768 ALContext
->DefaultSlot
= NULL
;
3769 ERR("Failed to initialize the default effect slot\n");
3773 ALCdevice_IncRef(ALContext
->Device
);
3774 InitContext(ALContext
);
3776 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3779 ERR("volume-adjust must be finite: %f\n", valf
);
3782 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3784 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3785 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3786 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3789 UpdateListenerProps(ALContext
);
3792 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3794 ALContext
->next
= head
;
3795 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3798 almtx_unlock(&device
->BackendLock
);
3800 if(ALContext
->DefaultSlot
)
3802 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3803 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3805 ERR("Failed to initialize the default effect\n");
3808 ALCdevice_DecRef(device
);
3810 TRACE("Created context %p\n", ALContext
);
3814 /* alcDestroyContext
3816 * Remove a context from its device
3818 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3823 if(!VerifyContext(&context
))
3826 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3830 Device
= context
->Device
;
3833 almtx_lock(&Device
->BackendLock
);
3834 if(!ReleaseContext(context
, Device
))
3836 V0(Device
->Backend
,stop
)();
3837 Device
->Flags
&= ~DEVICE_RUNNING
;
3839 almtx_unlock(&Device
->BackendLock
);
3843 ALCcontext_DecRef(context
);
3847 /* alcGetCurrentContext
3849 * Returns the currently active context on the calling thread
3851 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3853 ALCcontext
*Context
= altss_get(LocalContext
);
3854 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3858 /* alcGetThreadContext
3860 * Returns the currently active thread-local context
3862 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3864 return altss_get(LocalContext
);
3868 /* alcMakeContextCurrent
3870 * Makes the given context the active process-wide context, and removes the
3871 * thread-local context for the calling thread.
3873 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3875 /* context must be valid or NULL */
3876 if(context
&& !VerifyContext(&context
))
3878 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3881 /* context's reference count is already incremented */
3882 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3883 if(context
) ALCcontext_DecRef(context
);
3885 if((context
=altss_get(LocalContext
)) != NULL
)
3887 altss_set(LocalContext
, NULL
);
3888 ALCcontext_DecRef(context
);
3894 /* alcSetThreadContext
3896 * Makes the given context the active context for the current thread
3898 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3902 /* context must be valid or NULL */
3903 if(context
&& !VerifyContext(&context
))
3905 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3908 /* context's reference count is already incremented */
3909 old
= altss_get(LocalContext
);
3910 altss_set(LocalContext
, context
);
3911 if(old
) ALCcontext_DecRef(old
);
3917 /* alcGetContextsDevice
3919 * Returns the device that a particular context is attached to
3921 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3925 if(!VerifyContext(&Context
))
3927 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3930 Device
= Context
->Device
;
3931 ALCcontext_DecRef(Context
);
3939 * Opens the named device.
3941 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3943 ALCbackendFactory
*factory
;
3951 if(!PlaybackBackend
.name
)
3953 alcSetError(NULL
, ALC_INVALID_VALUE
);
3957 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3959 /* Some old Windows apps hardcode these expecting OpenAL to use a
3960 * specific audio API, even when they're not enumerated. Creative's
3961 * router effectively ignores them too.
3963 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3964 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3969 device
= al_calloc(16, sizeof(ALCdevice
));
3972 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3977 InitRef(&device
->ref
, 1);
3978 device
->Connected
= ALC_TRUE
;
3979 device
->Type
= Playback
;
3980 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3983 device
->Bs2b
= NULL
;
3984 device
->Uhj_Encoder
= NULL
;
3985 device
->Hrtf
= NULL
;
3986 device
->HrtfHandle
= NULL
;
3987 VECTOR_INIT(device
->HrtfList
);
3988 AL_STRING_INIT(device
->HrtfName
);
3989 device
->Render_Mode
= NormalRender
;
3990 AL_STRING_INIT(device
->DeviceName
);
3991 device
->Dry
.Buffer
= NULL
;
3992 device
->Dry
.NumChannels
= 0;
3993 device
->FOAOut
.Buffer
= NULL
;
3994 device
->FOAOut
.NumChannels
= 0;
3995 device
->RealOut
.Buffer
= NULL
;
3996 device
->RealOut
.NumChannels
= 0;
3997 device
->Limiter
= NULL
;
3998 device
->AvgSpeakerDist
= 0.0f
;
4000 ATOMIC_INIT(&device
->ContextList
, NULL
);
4002 device
->ClockBase
= 0;
4003 device
->SamplesDone
= 0;
4005 device
->SourcesMax
= 256;
4006 device
->AuxiliaryEffectSlotMax
= 64;
4007 device
->NumAuxSends
= DEFAULT_SENDS
;
4009 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4010 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4011 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4013 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4015 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4016 device
->ChannelDelay
[i
].Length
= 0;
4017 device
->ChannelDelay
[i
].Buffer
= NULL
;
4021 device
->FmtChans
= DevFmtChannelsDefault
;
4022 device
->FmtType
= DevFmtTypeDefault
;
4023 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4024 device
->IsHeadphones
= AL_FALSE
;
4025 device
->AmbiLayout
= AmbiLayout_Default
;
4026 device
->AmbiScale
= AmbiNorm_Default
;
4027 device
->NumUpdates
= 3;
4028 device
->UpdateSize
= 1024;
4030 factory
= PlaybackBackend
.getFactory();
4031 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
4032 if(!device
->Backend
)
4035 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4040 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
4042 static const struct {
4043 const char name
[16];
4044 enum DevFmtChannels chans
;
4047 { "mono", DevFmtMono
, 0 },
4048 { "stereo", DevFmtStereo
, 0 },
4049 { "quad", DevFmtQuad
, 0 },
4050 { "surround51", DevFmtX51
, 0 },
4051 { "surround61", DevFmtX61
, 0 },
4052 { "surround71", DevFmtX71
, 0 },
4053 { "surround51rear", DevFmtX51Rear
, 0 },
4054 { "ambi1", DevFmtAmbi3D
, 1 },
4055 { "ambi2", DevFmtAmbi3D
, 2 },
4056 { "ambi3", DevFmtAmbi3D
, 3 },
4060 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4062 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4064 device
->FmtChans
= chanlist
[i
].chans
;
4065 device
->AmbiOrder
= chanlist
[i
].order
;
4066 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4070 if(i
== COUNTOF(chanlist
))
4071 ERR("Unsupported channels: %s\n", fmt
);
4073 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4075 static const struct {
4076 const char name
[16];
4077 enum DevFmtType type
;
4079 { "int8", DevFmtByte
},
4080 { "uint8", DevFmtUByte
},
4081 { "int16", DevFmtShort
},
4082 { "uint16", DevFmtUShort
},
4083 { "int32", DevFmtInt
},
4084 { "uint32", DevFmtUInt
},
4085 { "float32", DevFmtFloat
},
4089 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4091 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4093 device
->FmtType
= typelist
[i
].type
;
4094 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4098 if(i
== COUNTOF(typelist
))
4099 ERR("Unsupported sample-type: %s\n", fmt
);
4102 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4104 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4105 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4106 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4107 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4110 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4111 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4113 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4114 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4115 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4116 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4118 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4119 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4121 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4122 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4124 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4125 device
->NumAuxSends
= clampi(
4126 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4129 device
->NumStereoSources
= 1;
4130 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4132 // Find a playback device to open
4133 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4135 DELETE_OBJ(device
->Backend
);
4137 alcSetError(NULL
, err
);
4140 almtx_init(&device
->BackendLock
, almtx_plain
);
4142 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4144 if(strcasecmp(fmt
, "fuma") == 0)
4146 device
->AmbiLayout
= AmbiLayout_FuMa
;
4147 device
->AmbiScale
= AmbiNorm_FuMa
;
4149 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4151 device
->AmbiLayout
= AmbiLayout_ACN
;
4152 device
->AmbiScale
= AmbiNorm_SN3D
;
4154 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4156 device
->AmbiLayout
= AmbiLayout_ACN
;
4157 device
->AmbiScale
= AmbiNorm_N3D
;
4160 ERR("Unsupported ambi-format: %s\n", fmt
);
4163 device
->Limiter
= CreateDeviceLimiter(device
);
4166 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4168 device
->next
= head
;
4169 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4172 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4178 * Closes the given device.
4180 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4182 ALCdevice
*iter
, *origdev
;
4186 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4190 } while((iter
=iter
->next
) != NULL
);
4191 if(!iter
|| iter
->Type
== Capture
)
4193 alcSetError(iter
, ALC_INVALID_DEVICE
);
4197 almtx_lock(&device
->BackendLock
);
4200 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4202 ALCdevice
*volatile*list
= &origdev
->next
;
4207 *list
= (*list
)->next
;
4210 list
= &(*list
)->next
;
4215 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4218 ALCcontext
*next
= ctx
->next
;
4219 WARN("Releasing context %p\n", ctx
);
4220 ReleaseContext(ctx
, device
);
4223 if((device
->Flags
&DEVICE_RUNNING
))
4224 V0(device
->Backend
,stop
)();
4225 device
->Flags
&= ~DEVICE_RUNNING
;
4226 almtx_unlock(&device
->BackendLock
);
4228 ALCdevice_DecRef(device
);
4234 /************************************************
4235 * ALC capture functions
4236 ************************************************/
4237 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4239 ALCbackendFactory
*factory
;
4240 ALCdevice
*device
= NULL
;
4246 if(!CaptureBackend
.name
)
4248 alcSetError(NULL
, ALC_INVALID_VALUE
);
4254 alcSetError(NULL
, ALC_INVALID_VALUE
);
4258 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4261 device
= al_calloc(16, sizeof(ALCdevice
));
4264 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4269 InitRef(&device
->ref
, 1);
4270 device
->Connected
= ALC_TRUE
;
4271 device
->Type
= Capture
;
4273 device
->Hrtf
= NULL
;
4274 device
->HrtfHandle
= NULL
;
4275 VECTOR_INIT(device
->HrtfList
);
4276 AL_STRING_INIT(device
->HrtfName
);
4278 AL_STRING_INIT(device
->DeviceName
);
4279 device
->Dry
.Buffer
= NULL
;
4280 device
->Dry
.NumChannels
= 0;
4281 device
->FOAOut
.Buffer
= NULL
;
4282 device
->FOAOut
.NumChannels
= 0;
4283 device
->RealOut
.Buffer
= NULL
;
4284 device
->RealOut
.NumChannels
= 0;
4286 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4287 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4288 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4290 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4292 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4293 device
->ChannelDelay
[i
].Length
= 0;
4294 device
->ChannelDelay
[i
].Buffer
= NULL
;
4297 factory
= CaptureBackend
.getFactory();
4298 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4299 if(!device
->Backend
)
4302 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4306 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4307 device
->Frequency
= frequency
;
4309 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4310 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4313 alcSetError(NULL
, ALC_INVALID_ENUM
);
4316 device
->IsHeadphones
= AL_FALSE
;
4317 device
->AmbiOrder
= 0;
4318 device
->AmbiLayout
= AmbiLayout_Default
;
4319 device
->AmbiScale
= AmbiNorm_Default
;
4321 device
->UpdateSize
= samples
;
4322 device
->NumUpdates
= 1;
4324 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4325 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4326 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4328 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4331 alcSetError(NULL
, err
);
4334 almtx_init(&device
->BackendLock
, almtx_plain
);
4337 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4339 device
->next
= head
;
4340 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4343 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4347 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4349 ALCdevice
*iter
, *origdev
;
4352 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4356 } while((iter
=iter
->next
) != NULL
);
4357 if(!iter
|| iter
->Type
!= Capture
)
4359 alcSetError(iter
, ALC_INVALID_DEVICE
);
4365 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4367 ALCdevice
*volatile*list
= &origdev
->next
;
4372 *list
= (*list
)->next
;
4375 list
= &(*list
)->next
;
4380 ALCdevice_DecRef(device
);
4385 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4387 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4388 alcSetError(device
, ALC_INVALID_DEVICE
);
4391 almtx_lock(&device
->BackendLock
);
4392 if(!device
->Connected
)
4393 alcSetError(device
, ALC_INVALID_DEVICE
);
4394 else if(!(device
->Flags
&DEVICE_RUNNING
))
4396 if(V0(device
->Backend
,start
)())
4397 device
->Flags
|= DEVICE_RUNNING
;
4400 aluHandleDisconnect(device
);
4401 alcSetError(device
, ALC_INVALID_DEVICE
);
4404 almtx_unlock(&device
->BackendLock
);
4407 if(device
) ALCdevice_DecRef(device
);
4410 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4412 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4413 alcSetError(device
, ALC_INVALID_DEVICE
);
4416 almtx_lock(&device
->BackendLock
);
4417 if((device
->Flags
&DEVICE_RUNNING
))
4418 V0(device
->Backend
,stop
)();
4419 device
->Flags
&= ~DEVICE_RUNNING
;
4420 almtx_unlock(&device
->BackendLock
);
4423 if(device
) ALCdevice_DecRef(device
);
4426 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4428 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4429 alcSetError(device
, ALC_INVALID_DEVICE
);
4432 ALCenum err
= ALC_INVALID_VALUE
;
4434 almtx_lock(&device
->BackendLock
);
4435 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4436 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4437 almtx_unlock(&device
->BackendLock
);
4439 if(err
!= ALC_NO_ERROR
)
4440 alcSetError(device
, err
);
4442 if(device
) ALCdevice_DecRef(device
);
4446 /************************************************
4447 * ALC loopback functions
4448 ************************************************/
4450 /* alcLoopbackOpenDeviceSOFT
4452 * Open a loopback device, for manual rendering.
4454 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4456 ALCbackendFactory
*factory
;
4462 /* Make sure the device name, if specified, is us. */
4463 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4465 alcSetError(NULL
, ALC_INVALID_VALUE
);
4469 device
= al_calloc(16, sizeof(ALCdevice
));
4472 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4477 InitRef(&device
->ref
, 1);
4478 device
->Connected
= ALC_TRUE
;
4479 device
->Type
= Loopback
;
4480 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4483 device
->Hrtf
= NULL
;
4484 device
->HrtfHandle
= NULL
;
4485 VECTOR_INIT(device
->HrtfList
);
4486 AL_STRING_INIT(device
->HrtfName
);
4487 device
->Bs2b
= NULL
;
4488 device
->Uhj_Encoder
= NULL
;
4489 device
->Render_Mode
= NormalRender
;
4490 AL_STRING_INIT(device
->DeviceName
);
4491 device
->Dry
.Buffer
= NULL
;
4492 device
->Dry
.NumChannels
= 0;
4493 device
->FOAOut
.Buffer
= NULL
;
4494 device
->FOAOut
.NumChannels
= 0;
4495 device
->RealOut
.Buffer
= NULL
;
4496 device
->RealOut
.NumChannels
= 0;
4497 device
->Limiter
= NULL
;
4498 device
->AvgSpeakerDist
= 0.0f
;
4500 ATOMIC_INIT(&device
->ContextList
, NULL
);
4502 device
->ClockBase
= 0;
4503 device
->SamplesDone
= 0;
4505 device
->SourcesMax
= 256;
4506 device
->AuxiliaryEffectSlotMax
= 64;
4507 device
->NumAuxSends
= DEFAULT_SENDS
;
4509 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4510 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4511 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4513 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4515 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4516 device
->ChannelDelay
[i
].Length
= 0;
4517 device
->ChannelDelay
[i
].Buffer
= NULL
;
4520 factory
= ALCloopbackFactory_getFactory();
4521 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4522 if(!device
->Backend
)
4525 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4528 almtx_init(&device
->BackendLock
, almtx_plain
);
4531 device
->NumUpdates
= 0;
4532 device
->UpdateSize
= 0;
4534 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4535 device
->FmtChans
= DevFmtChannelsDefault
;
4536 device
->FmtType
= DevFmtTypeDefault
;
4537 device
->IsHeadphones
= AL_FALSE
;
4538 device
->AmbiLayout
= AmbiLayout_Default
;
4539 device
->AmbiScale
= AmbiNorm_Default
;
4541 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4542 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4544 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4545 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4547 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4548 device
->NumAuxSends
= clampi(
4549 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4552 device
->NumStereoSources
= 1;
4553 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4555 // Open the "backend"
4556 V(device
->Backend
,open
)("Loopback");
4558 device
->Limiter
= CreateDeviceLimiter(device
);
4561 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4563 device
->next
= head
;
4564 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4567 TRACE("Created device %p\n", device
);
4571 /* alcIsRenderFormatSupportedSOFT
4573 * Determines if the loopback device supports the given format for rendering.
4575 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4577 ALCboolean ret
= ALC_FALSE
;
4579 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4580 alcSetError(device
, ALC_INVALID_DEVICE
);
4582 alcSetError(device
, ALC_INVALID_VALUE
);
4585 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4588 if(device
) ALCdevice_DecRef(device
);
4593 /* alcRenderSamplesSOFT
4595 * Renders some samples into a buffer, using the format last set by the
4596 * attributes given to alcCreateContext.
4598 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4600 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4601 alcSetError(device
, ALC_INVALID_DEVICE
);
4602 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4603 alcSetError(device
, ALC_INVALID_VALUE
);
4606 V0(device
->Backend
,lock
)();
4607 aluMixData(device
, buffer
, samples
);
4608 V0(device
->Backend
,unlock
)();
4610 if(device
) ALCdevice_DecRef(device
);
4614 /************************************************
4615 * ALC DSP pause/resume functions
4616 ************************************************/
4618 /* alcDevicePauseSOFT
4620 * Pause the DSP to stop audio processing.
4622 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4624 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4625 alcSetError(device
, ALC_INVALID_DEVICE
);
4628 almtx_lock(&device
->BackendLock
);
4629 if((device
->Flags
&DEVICE_RUNNING
))
4630 V0(device
->Backend
,stop
)();
4631 device
->Flags
&= ~DEVICE_RUNNING
;
4632 device
->Flags
|= DEVICE_PAUSED
;
4633 almtx_unlock(&device
->BackendLock
);
4635 if(device
) ALCdevice_DecRef(device
);
4638 /* alcDeviceResumeSOFT
4640 * Resume the DSP to restart audio processing.
4642 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4644 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4645 alcSetError(device
, ALC_INVALID_DEVICE
);
4648 almtx_lock(&device
->BackendLock
);
4649 if((device
->Flags
&DEVICE_PAUSED
))
4651 device
->Flags
&= ~DEVICE_PAUSED
;
4652 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4654 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4655 device
->Flags
|= DEVICE_RUNNING
;
4658 alcSetError(device
, ALC_INVALID_DEVICE
);
4659 V0(device
->Backend
,lock
)();
4660 aluHandleDisconnect(device
);
4661 V0(device
->Backend
,unlock
)();
4665 almtx_unlock(&device
->BackendLock
);
4667 if(device
) ALCdevice_DecRef(device
);
4671 /************************************************
4672 * ALC HRTF functions
4673 ************************************************/
4675 /* alcGetStringiSOFT
4677 * Gets a string parameter at the given index.
4679 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4681 const ALCchar
*str
= NULL
;
4683 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4684 alcSetError(device
, ALC_INVALID_DEVICE
);
4685 else switch(paramName
)
4687 case ALC_HRTF_SPECIFIER_SOFT
:
4688 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4689 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4691 alcSetError(device
, ALC_INVALID_VALUE
);
4695 alcSetError(device
, ALC_INVALID_ENUM
);
4698 if(device
) ALCdevice_DecRef(device
);
4703 /* alcResetDeviceSOFT
4705 * Resets the given device output, using the specified attribute list.
4707 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4712 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4715 alcSetError(device
, ALC_INVALID_DEVICE
);
4716 if(device
) ALCdevice_DecRef(device
);
4719 almtx_lock(&device
->BackendLock
);
4722 err
= UpdateDeviceParams(device
, attribs
);
4723 almtx_unlock(&device
->BackendLock
);
4725 if(err
!= ALC_NO_ERROR
)
4727 alcSetError(device
, err
);
4728 if(err
== ALC_INVALID_DEVICE
)
4730 V0(device
->Backend
,lock
)();
4731 aluHandleDisconnect(device
);
4732 V0(device
->Backend
,unlock
)();
4734 ALCdevice_DecRef(device
);
4737 ALCdevice_DecRef(device
);