2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
40 #include "bformatdec.h"
48 #include "backends/base.h"
51 /************************************************
53 ************************************************/
56 ALCbackendFactory
* (*getFactory
)(void);
57 ALCboolean (*Init
)(BackendFuncs
*);
59 void (*Probe
)(enum DevProbe
);
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList
[] = {
66 { "jack", ALCjackBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
72 { "alsa", ALCalsaBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
75 { "core", ALCcoreAudioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
78 { "oss", ALCossBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
81 { "solaris", ALCsolarisBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
84 { "sndio", ALCsndioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
87 { "qsa", NULL
, alc_qsa_init
, alc_qsa_deinit
, alc_qsa_probe
, EmptyFuncs
},
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
93 { "dsound", ALCdsoundBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
96 { "winmm", ALCwinmmBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
99 { "port", ALCportBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
102 { "opensl", ALCopenslBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
105 { "null", ALCnullBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
107 { "wave", ALCwaveBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
110 static ALsizei BackendListSize
= COUNTOF(BackendList
);
113 static struct BackendInfo PlaybackBackend
;
114 static struct BackendInfo CaptureBackend
;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar
*funcName
;
125 DECL(alcCreateContext
),
126 DECL(alcMakeContextCurrent
),
127 DECL(alcProcessContext
),
128 DECL(alcSuspendContext
),
129 DECL(alcDestroyContext
),
130 DECL(alcGetCurrentContext
),
131 DECL(alcGetContextsDevice
),
133 DECL(alcCloseDevice
),
135 DECL(alcIsExtensionPresent
),
136 DECL(alcGetProcAddress
),
137 DECL(alcGetEnumValue
),
139 DECL(alcGetIntegerv
),
140 DECL(alcCaptureOpenDevice
),
141 DECL(alcCaptureCloseDevice
),
142 DECL(alcCaptureStart
),
143 DECL(alcCaptureStop
),
144 DECL(alcCaptureSamples
),
146 DECL(alcSetThreadContext
),
147 DECL(alcGetThreadContext
),
149 DECL(alcLoopbackOpenDeviceSOFT
),
150 DECL(alcIsRenderFormatSupportedSOFT
),
151 DECL(alcRenderSamplesSOFT
),
153 DECL(alcIsAmbisonicFormatSupportedSOFT
),
155 DECL(alcDevicePauseSOFT
),
156 DECL(alcDeviceResumeSOFT
),
158 DECL(alcGetStringiSOFT
),
159 DECL(alcResetDeviceSOFT
),
161 DECL(alcGetInteger64vSOFT
),
176 DECL(alIsExtensionPresent
),
177 DECL(alGetProcAddress
),
178 DECL(alGetEnumValue
),
185 DECL(alGetListenerf
),
186 DECL(alGetListener3f
),
187 DECL(alGetListenerfv
),
188 DECL(alGetListeneri
),
189 DECL(alGetListener3i
),
190 DECL(alGetListeneriv
),
192 DECL(alDeleteSources
),
208 DECL(alSourceRewindv
),
209 DECL(alSourcePausev
),
212 DECL(alSourceRewind
),
214 DECL(alSourceQueueBuffers
),
215 DECL(alSourceUnqueueBuffers
),
217 DECL(alDeleteBuffers
),
232 DECL(alDopplerFactor
),
233 DECL(alDopplerVelocity
),
234 DECL(alSpeedOfSound
),
235 DECL(alDistanceModel
),
238 DECL(alDeleteFilters
),
249 DECL(alDeleteEffects
),
259 DECL(alGenAuxiliaryEffectSlots
),
260 DECL(alDeleteAuxiliaryEffectSlots
),
261 DECL(alIsAuxiliaryEffectSlot
),
262 DECL(alAuxiliaryEffectSloti
),
263 DECL(alAuxiliaryEffectSlotiv
),
264 DECL(alAuxiliaryEffectSlotf
),
265 DECL(alAuxiliaryEffectSlotfv
),
266 DECL(alGetAuxiliaryEffectSloti
),
267 DECL(alGetAuxiliaryEffectSlotiv
),
268 DECL(alGetAuxiliaryEffectSlotf
),
269 DECL(alGetAuxiliaryEffectSlotfv
),
271 DECL(alDeferUpdatesSOFT
),
272 DECL(alProcessUpdatesSOFT
),
275 DECL(alSource3dSOFT
),
276 DECL(alSourcedvSOFT
),
277 DECL(alGetSourcedSOFT
),
278 DECL(alGetSource3dSOFT
),
279 DECL(alGetSourcedvSOFT
),
280 DECL(alSourcei64SOFT
),
281 DECL(alSource3i64SOFT
),
282 DECL(alSourcei64vSOFT
),
283 DECL(alGetSourcei64SOFT
),
284 DECL(alGetSource3i64SOFT
),
285 DECL(alGetSourcei64vSOFT
),
287 DECL(alBufferSamplesSOFT
),
288 DECL(alGetBufferSamplesSOFT
),
289 DECL(alIsBufferFormatSupportedSOFT
),
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar
*enumName
;
297 } alcEnumerations
[] = {
302 DECL(ALC_MAJOR_VERSION
),
303 DECL(ALC_MINOR_VERSION
),
304 DECL(ALC_ATTRIBUTES_SIZE
),
305 DECL(ALC_ALL_ATTRIBUTES
),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
307 DECL(ALC_DEVICE_SPECIFIER
),
308 DECL(ALC_ALL_DEVICES_SPECIFIER
),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
310 DECL(ALC_EXTENSIONS
),
314 DECL(ALC_MONO_SOURCES
),
315 DECL(ALC_STEREO_SOURCES
),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
318 DECL(ALC_CAPTURE_SAMPLES
),
321 DECL(ALC_EFX_MAJOR_VERSION
),
322 DECL(ALC_EFX_MINOR_VERSION
),
323 DECL(ALC_MAX_AUXILIARY_SENDS
),
325 DECL(ALC_FORMAT_CHANNELS_SOFT
),
326 DECL(ALC_FORMAT_TYPE_SOFT
),
329 DECL(ALC_STEREO_SOFT
),
331 DECL(ALC_5POINT1_SOFT
),
332 DECL(ALC_6POINT1_SOFT
),
333 DECL(ALC_7POINT1_SOFT
),
334 DECL(ALC_BFORMAT3D_SOFT
),
337 DECL(ALC_UNSIGNED_BYTE_SOFT
),
338 DECL(ALC_SHORT_SOFT
),
339 DECL(ALC_UNSIGNED_SHORT_SOFT
),
341 DECL(ALC_UNSIGNED_INT_SOFT
),
342 DECL(ALC_FLOAT_SOFT
),
345 DECL(ALC_DONT_CARE_SOFT
),
346 DECL(ALC_HRTF_STATUS_SOFT
),
347 DECL(ALC_HRTF_DISABLED_SOFT
),
348 DECL(ALC_HRTF_ENABLED_SOFT
),
349 DECL(ALC_HRTF_DENIED_SOFT
),
350 DECL(ALC_HRTF_REQUIRED_SOFT
),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
354 DECL(ALC_HRTF_SPECIFIER_SOFT
),
355 DECL(ALC_HRTF_ID_SOFT
),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
358 DECL(ALC_AMBISONIC_SCALING_SOFT
),
359 DECL(ALC_AMBISONIC_ORDER_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
),
698 static const ALCchar alcNoError
[] = "No Error";
699 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
706 /************************************************
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList
;
714 static al_string alcCaptureDeviceList
;
716 /* Default is always the first in the list */
717 static ALCchar
*alcDefaultAllDevicesSpecifier
;
718 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
720 /* Default context extensions */
721 static const ALchar alExtList
[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
732 /* Thread-local current context */
733 static altss_t LocalContext
;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
737 /* Mixing thread piority level */
742 enum LogLevel LogLevel
= LogWarning
;
744 enum LogLevel LogLevel
= LogError
;
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError
= ALC_FALSE
;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect
;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
759 static ALCboolean SuspendDefers
= ALC_TRUE
;
762 /************************************************
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList
[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList
[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion
= 1;
774 static const ALCint alcMinorVersion
= 1;
776 static const ALCint alcEFXMajorVersion
= 1;
777 static const ALCint alcEFXMinorVersion
= 0;
780 /************************************************
782 ************************************************/
783 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
785 static almtx_t ListLock
;
786 static inline void LockLists(void)
788 int ret
= almtx_lock(&ListLock
);
789 assert(ret
== althrd_success
);
791 static inline void UnlockLists(void)
793 int ret
= almtx_unlock(&ListLock
);
794 assert(ret
== althrd_success
);
797 /************************************************
798 * Library initialization
799 ************************************************/
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
810 case DLL_PROCESS_ATTACH
:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
813 (WCHAR
*)hModule
, &hModule
);
817 case DLL_THREAD_DETACH
:
820 case DLL_PROCESS_DETACH
:
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
835 static void alc_constructor(void)
837 atexit(alc_destructor
);
841 static void alc_destructor(void)
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor
));
847 static void alc_deinit(void) __attribute__((destructor
));
849 #error "No static initialization available on this platform!"
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor
));
855 static void alc_deinit(void) __attribute__((destructor
));
858 #error "No global initialization available on this platform!"
861 static void ReleaseThreadCtx(void *ptr
);
862 static void alc_init(void)
869 AL_STRING_INIT(alcAllDevicesList
);
870 AL_STRING_INIT(alcCaptureDeviceList
);
872 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
876 str
= getenv("__ALSOFT_REVERSE_Z");
877 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
880 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
881 assert(ret
== althrd_success
);
883 ret
= almtx_init(&ListLock
, almtx_recursive
);
884 assert(ret
== althrd_success
);
889 static void alc_initconfig(void)
891 const char *devs
, *str
;
896 str
= getenv("ALSOFT_LOGLEVEL");
899 long lvl
= strtol(str
, NULL
, 0);
900 if(lvl
>= NoLog
&& lvl
<= LogRef
)
904 str
= getenv("ALSOFT_LOGFILE");
907 FILE *logfile
= al_fopen(str
, "wt");
908 if(logfile
) LogFile
= logfile
;
909 else ERR("Failed to open log file '%s'\n", str
);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
913 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
918 if(BackendListSize
> 0)
919 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
920 for(i
= 1;i
< BackendListSize
;i
++)
921 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
922 TRACE("Supported backends: %s\n", buf
);
926 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
929 if(strcasecmp(str
, "ignore") == 0)
931 SuspendDefers
= ALC_FALSE
;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
939 #if defined(HAVE_SSE4_1)
940 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
941 #elif defined(HAVE_SSE3)
942 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
943 #elif defined(HAVE_SSE2)
944 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
945 #elif defined(HAVE_SSE)
946 capfilter
|= CPU_CAP_SSE
;
949 capfilter
|= CPU_CAP_NEON
;
951 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
953 if(strcasecmp(str
, "all") == 0)
958 const char *next
= str
;
962 while(isspace(str
[0]))
964 next
= strchr(str
, ',');
966 if(!str
[0] || str
[0] == ',')
969 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
970 while(len
> 0 && isspace(str
[len
-1]))
972 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
973 capfilter
&= ~CPU_CAP_SSE
;
974 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
975 capfilter
&= ~CPU_CAP_SSE2
;
976 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
977 capfilter
&= ~CPU_CAP_SSE3
;
978 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
979 capfilter
&= ~CPU_CAP_SSE4_1
;
980 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
981 capfilter
&= ~CPU_CAP_NEON
;
983 WARN("Invalid CPU extension \"%s\"\n", str
);
987 FillCPUCaps(capfilter
);
994 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
998 str
= getenv("ALSOFT_TRAP_ERROR");
999 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1001 TrapALError
= AL_TRUE
;
1002 TrapALCError
= AL_TRUE
;
1006 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1008 TrapALError
= AL_TRUE
;
1009 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1011 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1013 TrapALCError
= ALC_TRUE
;
1014 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1017 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1018 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1020 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1022 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1023 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1027 const char *next
= devs
;
1028 int endlist
, delitem
;
1033 while(isspace(devs
[0]))
1035 next
= strchr(devs
, ',');
1037 delitem
= (devs
[0] == '-');
1038 if(devs
[0] == '-') devs
++;
1040 if(!devs
[0] || devs
[0] == ',')
1047 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1048 while(len
> 0 && isspace(devs
[len
-1]))
1050 for(n
= i
;n
< BackendListSize
;n
++)
1052 if(len
== strlen(BackendList
[n
].name
) &&
1053 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1057 for(;n
+1 < BackendListSize
;n
++)
1058 BackendList
[n
] = BackendList
[n
+1];
1063 struct BackendInfo Bkp
= BackendList
[n
];
1065 BackendList
[n
] = BackendList
[n
-1];
1066 BackendList
[n
] = Bkp
;
1076 BackendListSize
= i
;
1079 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1081 if(BackendList
[i
].getFactory
)
1083 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1084 if(!V0(factory
,init
)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1090 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1091 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1093 PlaybackBackend
= BackendList
[i
];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1096 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1098 CaptureBackend
= BackendList
[i
];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1105 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1111 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1112 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1114 PlaybackBackend
= BackendList
[i
];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1117 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1119 CaptureBackend
= BackendList
[i
];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1124 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1128 if(!PlaybackBackend
.name
)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend
.name
)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1136 const char *next
= str
;
1140 next
= strchr(str
, ',');
1142 if(!str
[0] || next
== str
)
1145 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1146 for(n
= 0;EffectList
[n
].name
;n
++)
1148 if(len
== strlen(EffectList
[n
].name
) &&
1149 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1150 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect
);
1158 str
= getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1160 LoadReverbPreset(str
, &DefaultEffect
);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1167 static JavaVM
*gJavaVM
;
1168 static pthread_key_t gJVMThreadKey
;
1170 static void CleanupJNIEnv(void* UNUSED(ptr
))
1172 JCALL0(gJavaVM
,DetachCurrentThread
)();
1175 void *Android_GetJNIEnv(void)
1179 WARN("gJavaVM is NULL!\n");
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1196 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1199 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1202 ERR("Failed to attach current thread\n");
1205 pthread_setspecific(gJVMThreadKey
, env
);
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1217 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err
);
1228 pthread_setspecific(gJVMThreadKey
, env
);
1229 return JNI_VERSION_1_4
;
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1242 AL_STRING_DEINIT(alcAllDevicesList
);
1243 AL_STRING_DEINIT(alcCaptureDeviceList
);
1245 free(alcDefaultAllDevicesSpecifier
);
1246 alcDefaultAllDevicesSpecifier
= NULL
;
1247 free(alcCaptureDefaultDeviceSpecifier
);
1248 alcCaptureDefaultDeviceSpecifier
= NULL
;
1250 if((dev
=ATOMIC_EXCHANGE_SEQ(ALCdevice
*, &DeviceList
, NULL
)) != NULL
)
1255 } while((dev
=dev
->next
) != NULL
);
1256 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1259 DeinitEffectFactoryMap();
1262 static void alc_deinit_safe(void)
1270 almtx_destroy(&ListLock
);
1271 altss_delete(LocalContext
);
1273 if(LogFile
!= stderr
)
1278 static void alc_deinit(void)
1284 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1285 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1287 for(i
= 0;i
< BackendListSize
;i
++)
1289 if(!BackendList
[i
].getFactory
)
1290 BackendList
[i
].Deinit();
1293 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1294 V0(factory
,deinit
)();
1298 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1299 V0(factory
,deinit
)();
1306 /************************************************
1307 * Device enumeration
1308 ************************************************/
1309 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1316 if(backendinfo
->Probe
)
1317 backendinfo
->Probe(type
);
1318 else if(backendinfo
->getFactory
)
1320 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1321 V(factory
,probe
)(type
);
1325 static void ProbeAllDevicesList(void)
1326 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1327 static void ProbeCaptureDeviceList(void)
1328 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1330 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1332 size_t len
= strlen(name
);
1334 alstr_append_range(devnames
, name
, name
+len
+1);
1336 void AppendAllDevicesList(const ALCchar
*name
)
1337 { AppendDevice(name
, &alcAllDevicesList
); }
1338 void AppendCaptureDeviceList(const ALCchar
*name
)
1339 { AppendDevice(name
, &alcCaptureDeviceList
); }
1342 /************************************************
1343 * Device format information
1344 ************************************************/
1345 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1349 case DevFmtByte
: return "Signed Byte";
1350 case DevFmtUByte
: return "Unsigned Byte";
1351 case DevFmtShort
: return "Signed Short";
1352 case DevFmtUShort
: return "Unsigned Short";
1353 case DevFmtInt
: return "Signed Int";
1354 case DevFmtUInt
: return "Unsigned Int";
1355 case DevFmtFloat
: return "Float";
1357 return "(unknown type)";
1359 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1363 case DevFmtMono
: return "Mono";
1364 case DevFmtStereo
: return "Stereo";
1365 case DevFmtQuad
: return "Quadraphonic";
1366 case DevFmtX51
: return "5.1 Surround";
1367 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1368 case DevFmtX61
: return "6.1 Surround";
1369 case DevFmtX71
: return "7.1 Surround";
1370 case DevFmtAmbi1
: return "Ambisonic (1st Order)";
1371 case DevFmtAmbi2
: return "Ambisonic (2nd Order)";
1372 case DevFmtAmbi3
: return "Ambisonic (3rd Order)";
1374 return "(unknown channels)";
1377 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
);
1378 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1382 case DevFmtByte
: return sizeof(ALbyte
);
1383 case DevFmtUByte
: return sizeof(ALubyte
);
1384 case DevFmtShort
: return sizeof(ALshort
);
1385 case DevFmtUShort
: return sizeof(ALushort
);
1386 case DevFmtInt
: return sizeof(ALint
);
1387 case DevFmtUInt
: return sizeof(ALuint
);
1388 case DevFmtFloat
: return sizeof(ALfloat
);
1392 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1396 case DevFmtMono
: return 1;
1397 case DevFmtStereo
: return 2;
1398 case DevFmtQuad
: return 4;
1399 case DevFmtX51
: return 6;
1400 case DevFmtX51Rear
: return 6;
1401 case DevFmtX61
: return 7;
1402 case DevFmtX71
: return 8;
1403 case DevFmtAmbi1
: return 4;
1404 case DevFmtAmbi2
: return 9;
1405 case DevFmtAmbi3
: return 16;
1410 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1411 enum DevFmtType
*type
)
1413 static const struct {
1415 enum DevFmtChannels channels
;
1416 enum DevFmtType type
;
1418 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1419 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1420 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1422 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1423 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1424 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1426 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1427 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1428 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1430 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1431 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1432 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1434 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1435 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1436 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1438 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1439 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1440 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1444 for(i
= 0;i
< COUNTOF(list
);i
++)
1446 if(list
[i
].format
== format
)
1448 *chans
= list
[i
].channels
;
1449 *type
= list
[i
].type
;
1457 static ALCboolean
IsValidALCType(ALCenum type
)
1462 case ALC_UNSIGNED_BYTE_SOFT
:
1463 case ALC_SHORT_SOFT
:
1464 case ALC_UNSIGNED_SHORT_SOFT
:
1466 case ALC_UNSIGNED_INT_SOFT
:
1467 case ALC_FLOAT_SOFT
:
1473 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1478 case ALC_STEREO_SOFT
:
1480 case ALC_5POINT1_SOFT
:
1481 case ALC_6POINT1_SOFT
:
1482 case ALC_7POINT1_SOFT
:
1483 case ALC_BFORMAT3D_SOFT
:
1489 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1500 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1512 /************************************************
1513 * Miscellaneous ALC helpers
1514 ************************************************/
1516 void ALCdevice_Lock(ALCdevice
*device
)
1518 V0(device
->Backend
,lock
)();
1521 void ALCdevice_Unlock(ALCdevice
*device
)
1523 V0(device
->Backend
,unlock
)();
1527 /* SetDefaultWFXChannelOrder
1529 * Sets the default channel order used by WaveFormatEx.
1531 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1535 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1536 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1538 switch(device
->FmtChans
)
1541 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1544 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1545 device
->RealOut
.ChannelName
[1] = FrontRight
;
1548 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1549 device
->RealOut
.ChannelName
[1] = FrontRight
;
1550 device
->RealOut
.ChannelName
[2] = BackLeft
;
1551 device
->RealOut
.ChannelName
[3] = BackRight
;
1554 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1555 device
->RealOut
.ChannelName
[1] = FrontRight
;
1556 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1557 device
->RealOut
.ChannelName
[3] = LFE
;
1558 device
->RealOut
.ChannelName
[4] = SideLeft
;
1559 device
->RealOut
.ChannelName
[5] = SideRight
;
1562 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1563 device
->RealOut
.ChannelName
[1] = FrontRight
;
1564 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1565 device
->RealOut
.ChannelName
[3] = LFE
;
1566 device
->RealOut
.ChannelName
[4] = BackLeft
;
1567 device
->RealOut
.ChannelName
[5] = BackRight
;
1570 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1571 device
->RealOut
.ChannelName
[1] = FrontRight
;
1572 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1573 device
->RealOut
.ChannelName
[3] = LFE
;
1574 device
->RealOut
.ChannelName
[4] = BackCenter
;
1575 device
->RealOut
.ChannelName
[5] = SideLeft
;
1576 device
->RealOut
.ChannelName
[6] = SideRight
;
1579 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1580 device
->RealOut
.ChannelName
[1] = FrontRight
;
1581 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1582 device
->RealOut
.ChannelName
[3] = LFE
;
1583 device
->RealOut
.ChannelName
[4] = BackLeft
;
1584 device
->RealOut
.ChannelName
[5] = BackRight
;
1585 device
->RealOut
.ChannelName
[6] = SideLeft
;
1586 device
->RealOut
.ChannelName
[7] = SideRight
;
1589 device
->RealOut
.ChannelName
[0] = Aux0
;
1590 device
->RealOut
.ChannelName
[1] = Aux1
;
1591 device
->RealOut
.ChannelName
[2] = Aux2
;
1592 device
->RealOut
.ChannelName
[3] = Aux3
;
1595 device
->RealOut
.ChannelName
[0] = Aux0
;
1596 device
->RealOut
.ChannelName
[1] = Aux1
;
1597 device
->RealOut
.ChannelName
[2] = Aux2
;
1598 device
->RealOut
.ChannelName
[3] = Aux3
;
1599 device
->RealOut
.ChannelName
[4] = Aux4
;
1600 device
->RealOut
.ChannelName
[5] = Aux5
;
1601 device
->RealOut
.ChannelName
[6] = Aux6
;
1602 device
->RealOut
.ChannelName
[7] = Aux7
;
1603 device
->RealOut
.ChannelName
[8] = Aux8
;
1606 device
->RealOut
.ChannelName
[0] = Aux0
;
1607 device
->RealOut
.ChannelName
[1] = Aux1
;
1608 device
->RealOut
.ChannelName
[2] = Aux2
;
1609 device
->RealOut
.ChannelName
[3] = Aux3
;
1610 device
->RealOut
.ChannelName
[4] = Aux4
;
1611 device
->RealOut
.ChannelName
[5] = Aux5
;
1612 device
->RealOut
.ChannelName
[6] = Aux6
;
1613 device
->RealOut
.ChannelName
[7] = Aux7
;
1614 device
->RealOut
.ChannelName
[8] = Aux8
;
1615 device
->RealOut
.ChannelName
[9] = Aux9
;
1616 device
->RealOut
.ChannelName
[10] = Aux10
;
1617 device
->RealOut
.ChannelName
[11] = Aux11
;
1618 device
->RealOut
.ChannelName
[12] = Aux12
;
1619 device
->RealOut
.ChannelName
[13] = Aux13
;
1620 device
->RealOut
.ChannelName
[14] = Aux14
;
1621 device
->RealOut
.ChannelName
[15] = Aux15
;
1626 /* SetDefaultChannelOrder
1628 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1630 void SetDefaultChannelOrder(ALCdevice
*device
)
1634 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1635 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1637 switch(device
->FmtChans
)
1640 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1641 device
->RealOut
.ChannelName
[1] = FrontRight
;
1642 device
->RealOut
.ChannelName
[2] = BackLeft
;
1643 device
->RealOut
.ChannelName
[3] = BackRight
;
1644 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1645 device
->RealOut
.ChannelName
[5] = LFE
;
1648 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1649 device
->RealOut
.ChannelName
[1] = FrontRight
;
1650 device
->RealOut
.ChannelName
[2] = BackLeft
;
1651 device
->RealOut
.ChannelName
[3] = BackRight
;
1652 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1653 device
->RealOut
.ChannelName
[5] = LFE
;
1654 device
->RealOut
.ChannelName
[6] = SideLeft
;
1655 device
->RealOut
.ChannelName
[7] = SideRight
;
1658 /* Same as WFX order */
1667 SetDefaultWFXChannelOrder(device
);
1672 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1675 /* ALCcontext_DeferUpdates
1677 * Defers/suspends updates for the given context's listener and sources. This
1678 * does *NOT* stop mixing, but rather prevents certain property changes from
1681 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1683 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1686 /* ALCcontext_ProcessUpdates
1688 * Resumes update processing after being deferred.
1690 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1692 ReadLock(&context
->PropLock
);
1693 if(ATOMIC_EXCHANGE_SEQ(ALenum
, &context
->DeferUpdates
, AL_FALSE
))
1695 /* Tell the mixer to stop applying updates, then wait for any active
1696 * updating to finish, before providing updates.
1698 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1699 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1702 UpdateListenerProps(context
);
1703 UpdateAllEffectSlotProps(context
);
1704 UpdateAllSourceProps(context
);
1706 /* Now with all updates declared, let the mixer continue applying them
1707 * so they all happen at once.
1709 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1711 ReadUnlock(&context
->PropLock
);
1717 * Stores the latest ALC device error
1719 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1721 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1725 /* DebugBreak() will cause an exception if there is no debugger */
1726 if(IsDebuggerPresent())
1728 #elif defined(SIGTRAP)
1734 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1736 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1742 * Updates the device's base clock time with however many samples have been
1743 * done. This is used so frequency changes on the device don't cause the time
1744 * to jump forward or back. Must not be called while the device is running/
1747 static inline void UpdateClockBase(ALCdevice
*device
)
1749 IncrementRef(&device
->MixCount
);
1750 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1751 device
->SamplesDone
= 0;
1752 IncrementRef(&device
->MixCount
);
1755 /* UpdateDeviceParams
1757 * Updates device parameters according to the attribute list (caller is
1758 * responsible for holding the list lock).
1760 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1762 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1763 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1764 const ALsizei old_sends
= device
->NumAuxSends
;
1765 ALsizei new_sends
= device
->NumAuxSends
;
1766 enum DevFmtChannels oldChans
;
1767 enum DevFmtType oldType
;
1768 ALboolean update_failed
;
1769 ALCsizei hrtf_id
= -1;
1770 ALCcontext
*context
;
1776 // Check for attributes
1777 if(device
->Type
== Loopback
)
1779 ALCsizei numMono
, numStereo
, numSends
;
1780 ALCenum alayout
= AL_NONE
;
1781 ALCenum ascale
= AL_NONE
;
1782 ALCenum schans
= AL_NONE
;
1783 ALCenum stype
= AL_NONE
;
1784 ALCsizei attrIdx
= 0;
1785 ALCsizei aorder
= 0;
1790 WARN("Missing attributes for loopback device\n");
1791 return ALC_INVALID_VALUE
;
1794 numMono
= device
->NumMonoSources
;
1795 numStereo
= device
->NumStereoSources
;
1796 numSends
= old_sends
;
1798 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1799 while(attrList
[attrIdx
])
1801 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1803 schans
= attrList
[attrIdx
+ 1];
1804 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1805 if(!IsValidALCChannels(schans
))
1806 return ALC_INVALID_VALUE
;
1809 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1811 stype
= attrList
[attrIdx
+ 1];
1812 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1813 if(!IsValidALCType(stype
))
1814 return ALC_INVALID_VALUE
;
1817 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1819 freq
= attrList
[attrIdx
+ 1];
1820 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1821 if(freq
< MIN_OUTPUT_RATE
)
1822 return ALC_INVALID_VALUE
;
1825 if(attrList
[attrIdx
] == ALC_AMBISONIC_LAYOUT_SOFT
)
1827 alayout
= attrList
[attrIdx
+ 1];
1828 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1829 if(!IsValidAmbiLayout(alayout
))
1830 return ALC_INVALID_VALUE
;
1833 if(attrList
[attrIdx
] == ALC_AMBISONIC_SCALING_SOFT
)
1835 ascale
= attrList
[attrIdx
+ 1];
1836 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1837 if(!IsValidAmbiScaling(ascale
))
1838 return ALC_INVALID_VALUE
;
1841 if(attrList
[attrIdx
] == ALC_AMBISONIC_ORDER_SOFT
)
1843 aorder
= attrList
[attrIdx
+ 1];
1844 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1845 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1846 return ALC_INVALID_VALUE
;
1849 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1851 numStereo
= attrList
[attrIdx
+ 1];
1852 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1854 numStereo
= clampi(numStereo
, 0, device
->SourcesMax
);
1855 numMono
= device
->SourcesMax
- numStereo
;
1858 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1860 numSends
= attrList
[attrIdx
+ 1];
1861 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1862 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1865 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1867 ALCint val
= attrList
[attrIdx
+ 1];
1868 TRACE_ATTR(ALC_HRTF_SOFT
, val
);
1869 if(val
== ALC_FALSE
)
1870 hrtf_appreq
= Hrtf_Disable
;
1871 else if(val
== ALC_TRUE
)
1872 hrtf_appreq
= Hrtf_Enable
;
1874 hrtf_appreq
= Hrtf_Default
;
1877 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
1879 hrtf_id
= attrList
[attrIdx
+ 1];
1880 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1887 if(!schans
|| !stype
|| !freq
)
1889 WARN("Missing format for loopback device\n");
1890 return ALC_INVALID_VALUE
;
1892 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1894 WARN("Missing ambisonic info for loopback device\n");
1895 return ALC_INVALID_VALUE
;
1898 if((device
->Flags
&DEVICE_RUNNING
))
1899 V0(device
->Backend
,stop
)();
1900 device
->Flags
&= ~DEVICE_RUNNING
;
1902 UpdateClockBase(device
);
1904 if(schans
== ALC_BFORMAT3D_SOFT
)
1906 device
->FmtChans
= DevFmtAmbi1
+ (aorder
-1);
1907 device
->AmbiLayout
= alayout
;
1908 device
->AmbiScale
= ascale
;
1911 device
->FmtChans
= schans
;
1912 device
->Frequency
= freq
;
1913 device
->FmtType
= stype
;
1914 device
->NumMonoSources
= numMono
;
1915 device
->NumStereoSources
= numStereo
;
1917 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1918 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1920 new_sends
= numSends
;
1922 else if(attrList
&& attrList
[0])
1924 ALCsizei numMono
, numStereo
, numSends
;
1925 ALCsizei attrIdx
= 0;
1928 /* If a context is already running on the device, stop playback so the
1929 * device attributes can be updated. */
1930 if((device
->Flags
&DEVICE_RUNNING
))
1931 V0(device
->Backend
,stop
)();
1932 device
->Flags
&= ~DEVICE_RUNNING
;
1934 UpdateClockBase(device
);
1936 freq
= device
->Frequency
;
1937 numMono
= device
->NumMonoSources
;
1938 numStereo
= device
->NumStereoSources
;
1939 numSends
= old_sends
;
1941 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1942 while(attrList
[attrIdx
])
1944 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1946 freq
= attrList
[attrIdx
+ 1];
1947 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1948 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1951 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1953 numStereo
= attrList
[attrIdx
+ 1];
1954 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1956 numStereo
= clampi(numStereo
, 0, device
->SourcesMax
);
1957 numMono
= device
->SourcesMax
- numStereo
;
1960 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1962 numSends
= attrList
[attrIdx
+ 1];
1963 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1964 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1967 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1969 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1970 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1971 hrtf_appreq
= Hrtf_Disable
;
1972 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1973 hrtf_appreq
= Hrtf_Enable
;
1975 hrtf_appreq
= Hrtf_Default
;
1978 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
1980 hrtf_id
= attrList
[attrIdx
+ 1];
1981 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1988 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
1989 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1991 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1993 /* SSE and Neon do best with the update size being a multiple of 4 */
1994 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1995 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1997 device
->Frequency
= freq
;
1998 device
->NumMonoSources
= numMono
;
1999 device
->NumStereoSources
= numStereo
;
2001 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2002 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2004 new_sends
= numSends
;
2007 if((device
->Flags
&DEVICE_RUNNING
))
2008 return ALC_NO_ERROR
;
2010 al_free(device
->Uhj_Encoder
);
2011 device
->Uhj_Encoder
= NULL
;
2013 al_free(device
->Bs2b
);
2014 device
->Bs2b
= NULL
;
2016 al_free(device
->ChannelDelay
[0].Buffer
);
2017 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2019 device
->ChannelDelay
[i
].Length
= 0;
2020 device
->ChannelDelay
[i
].Buffer
= NULL
;
2023 al_free(device
->Dry
.Buffer
);
2024 device
->Dry
.Buffer
= NULL
;
2025 device
->Dry
.NumChannels
= 0;
2026 device
->FOAOut
.Buffer
= NULL
;
2027 device
->FOAOut
.NumChannels
= 0;
2028 device
->RealOut
.Buffer
= NULL
;
2029 device
->RealOut
.NumChannels
= 0;
2031 UpdateClockBase(device
);
2033 /*************************************************************************
2034 * Update device format request if HRTF is requested
2036 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2037 if(device
->Type
!= Loopback
)
2040 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2042 if(strcasecmp(hrtf
, "true") == 0)
2043 hrtf_userreq
= Hrtf_Enable
;
2044 else if(strcasecmp(hrtf
, "false") == 0)
2045 hrtf_userreq
= Hrtf_Disable
;
2046 else if(strcasecmp(hrtf
, "auto") != 0)
2047 ERR("Unexpected hrtf value: %s\n", hrtf
);
2050 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2052 struct Hrtf
*hrtf
= NULL
;
2053 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2055 VECTOR_DEINIT(device
->HrtfList
);
2056 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2058 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2060 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2061 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2063 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2068 device
->FmtChans
= DevFmtStereo
;
2069 device
->Frequency
= hrtf
->sampleRate
;
2070 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2071 if(device
->HrtfHandle
)
2072 Hrtf_DecRef(device
->HrtfHandle
);
2073 device
->HrtfHandle
= hrtf
;
2077 hrtf_userreq
= Hrtf_Default
;
2078 hrtf_appreq
= Hrtf_Disable
;
2079 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2084 oldFreq
= device
->Frequency
;
2085 oldChans
= device
->FmtChans
;
2086 oldType
= device
->FmtType
;
2088 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2089 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2090 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2091 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2092 device
->UpdateSize
, device
->NumUpdates
2095 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2096 return ALC_INVALID_DEVICE
;
2098 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2100 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2101 DevFmtChannelsString(device
->FmtChans
));
2102 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2104 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2106 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2107 DevFmtTypeString(device
->FmtType
));
2108 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2110 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2112 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2113 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2116 if((device
->UpdateSize
&3) != 0)
2118 if((CPUCapFlags
&CPU_CAP_SSE
))
2119 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2120 if((CPUCapFlags
&CPU_CAP_NEON
))
2121 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2124 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2125 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2126 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2129 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2130 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2131 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2133 /* Allocate extra channels for any post-filter output. */
2134 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2135 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2137 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2138 device
->Dry
.Buffer
= al_calloc(16, size
);
2139 if(!device
->Dry
.Buffer
)
2141 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2142 return ALC_INVALID_DEVICE
;
2145 if(device
->RealOut
.NumChannels
!= 0)
2146 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2147 device
->FOAOut
.NumChannels
;
2150 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2151 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2154 if(device
->FOAOut
.NumChannels
!= 0)
2155 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2158 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2159 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2162 /* Need to delay returning failure until replacement Send arrays have been
2163 * allocated with the appropriate size.
2165 device
->NumAuxSends
= new_sends
;
2166 update_failed
= AL_FALSE
;
2167 SetMixerFPUMode(&oldMode
);
2168 if(device
->DefaultSlot
)
2170 ALeffectslot
*slot
= device
->DefaultSlot
;
2171 ALeffectState
*state
= slot
->Effect
.State
;
2173 state
->OutBuffer
= device
->Dry
.Buffer
;
2174 state
->OutChannels
= device
->Dry
.NumChannels
;
2175 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2176 update_failed
= AL_TRUE
;
2178 UpdateEffectSlotProps(slot
);
2181 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2186 WriteLock(&context
->PropLock
);
2187 LockUIntMapRead(&context
->EffectSlotMap
);
2188 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2190 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2191 ALeffectState
*state
= slot
->Effect
.State
;
2193 state
->OutBuffer
= device
->Dry
.Buffer
;
2194 state
->OutChannels
= device
->Dry
.NumChannels
;
2195 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2196 update_failed
= AL_TRUE
;
2198 UpdateEffectSlotProps(slot
);
2200 UnlockUIntMapRead(&context
->EffectSlotMap
);
2202 LockUIntMapRead(&context
->SourceMap
);
2203 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2205 ALsource
*source
= context
->SourceMap
.values
[pos
];
2206 struct ALsourceProps
*props
;
2208 if(old_sends
!= device
->NumAuxSends
)
2210 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2213 memcpy(sends
, source
->Send
,
2214 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2216 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2218 if(source
->Send
[s
].Slot
)
2219 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2220 source
->Send
[s
].Slot
= NULL
;
2222 al_free(source
->Send
);
2223 source
->Send
= sends
;
2224 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2226 source
->Send
[s
].Slot
= NULL
;
2227 source
->Send
[s
].Gain
= 1.0f
;
2228 source
->Send
[s
].GainHF
= 1.0f
;
2229 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2230 source
->Send
[s
].GainLF
= 1.0f
;
2231 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2235 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2237 /* Clear any pre-existing source property structs, in case the
2238 * number of auxiliary sends changed. Playing (or paused) sources
2239 * will have updates respecified in UpdateAllSourceProps.
2241 props
= ATOMIC_EXCHANGE_SEQ(struct ALsourceProps
*, &source
->Update
, NULL
);
2244 props
= ATOMIC_EXCHANGE(struct ALsourceProps
*, &source
->FreeList
, NULL
,
2245 almemory_order_relaxed
);
2248 struct ALsourceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2253 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2254 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2256 ALvoice
*voice
= context
->Voices
[pos
];
2257 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2260 if(device
->AvgSpeakerDist
> 0.0f
)
2262 /* Reinitialize the NFC filters for new parameters. */
2263 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2264 (device
->AvgSpeakerDist
* device
->Frequency
);
2265 for(i
= 0;i
< voice
->NumChannels
;i
++)
2267 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2268 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2269 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2273 UnlockUIntMapRead(&context
->SourceMap
);
2275 UpdateListenerProps(context
);
2276 UpdateAllSourceProps(context
);
2277 WriteUnlock(&context
->PropLock
);
2279 context
= context
->next
;
2281 RestoreFPUMode(&oldMode
);
2283 return ALC_INVALID_DEVICE
;
2285 if(!(device
->Flags
&DEVICE_PAUSED
))
2287 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2288 return ALC_INVALID_DEVICE
;
2289 device
->Flags
|= DEVICE_RUNNING
;
2292 return ALC_NO_ERROR
;
2297 * Frees the device structure, and destroys any objects the app failed to
2298 * delete. Called once there's no more references on the device.
2300 static ALCvoid
FreeDevice(ALCdevice
*device
)
2304 TRACE("%p\n", device
);
2306 V0(device
->Backend
,close
)();
2307 DELETE_OBJ(device
->Backend
);
2308 device
->Backend
= NULL
;
2310 almtx_destroy(&device
->BackendLock
);
2312 if(device
->DefaultSlot
)
2314 DeinitEffectSlot(device
->DefaultSlot
);
2315 device
->DefaultSlot
= NULL
;
2318 if(device
->BufferMap
.size
> 0)
2320 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2321 (device
->BufferMap
.size
==1)?"":"s");
2322 ReleaseALBuffers(device
);
2324 ResetUIntMap(&device
->BufferMap
);
2326 if(device
->EffectMap
.size
> 0)
2328 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2329 (device
->EffectMap
.size
==1)?"":"s");
2330 ReleaseALEffects(device
);
2332 ResetUIntMap(&device
->EffectMap
);
2334 if(device
->FilterMap
.size
> 0)
2336 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2337 (device
->FilterMap
.size
==1)?"":"s");
2338 ReleaseALFilters(device
);
2340 ResetUIntMap(&device
->FilterMap
);
2342 AL_STRING_DEINIT(device
->HrtfName
);
2343 FreeHrtfList(&device
->HrtfList
);
2344 if(device
->HrtfHandle
)
2345 Hrtf_DecRef(device
->HrtfHandle
);
2346 device
->HrtfHandle
= NULL
;
2347 al_free(device
->Hrtf
);
2348 device
->Hrtf
= NULL
;
2350 al_free(device
->Bs2b
);
2351 device
->Bs2b
= NULL
;
2353 al_free(device
->Uhj_Encoder
);
2354 device
->Uhj_Encoder
= NULL
;
2356 bformatdec_free(device
->AmbiDecoder
);
2357 device
->AmbiDecoder
= NULL
;
2359 ambiup_free(device
->AmbiUp
);
2360 device
->AmbiUp
= NULL
;
2362 al_free(device
->ChannelDelay
[0].Buffer
);
2363 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2365 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2366 device
->ChannelDelay
[i
].Length
= 0;
2367 device
->ChannelDelay
[i
].Buffer
= NULL
;
2370 AL_STRING_DEINIT(device
->DeviceName
);
2372 al_free(device
->Dry
.Buffer
);
2373 device
->Dry
.Buffer
= NULL
;
2374 device
->Dry
.NumChannels
= 0;
2375 device
->FOAOut
.Buffer
= NULL
;
2376 device
->FOAOut
.NumChannels
= 0;
2377 device
->RealOut
.Buffer
= NULL
;
2378 device
->RealOut
.NumChannels
= 0;
2384 void ALCdevice_IncRef(ALCdevice
*device
)
2387 ref
= IncrementRef(&device
->ref
);
2388 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2391 void ALCdevice_DecRef(ALCdevice
*device
)
2394 ref
= DecrementRef(&device
->ref
);
2395 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2396 if(ref
== 0) FreeDevice(device
);
2401 * Checks if the device handle is valid, and increments its ref count if so.
2403 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2405 ALCdevice
*tmpDevice
;
2408 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2411 if(tmpDevice
== *device
)
2413 ALCdevice_IncRef(tmpDevice
);
2417 tmpDevice
= tmpDevice
->next
;
2428 * Initializes context fields
2430 static ALvoid
InitContext(ALCcontext
*Context
)
2432 ALlistener
*listener
= Context
->Listener
;
2433 struct ALeffectslotArray
*auxslots
;
2435 //Initialise listener
2436 listener
->Gain
= 1.0f
;
2437 listener
->MetersPerUnit
= 1.0f
;
2438 listener
->Position
[0] = 0.0f
;
2439 listener
->Position
[1] = 0.0f
;
2440 listener
->Position
[2] = 0.0f
;
2441 listener
->Velocity
[0] = 0.0f
;
2442 listener
->Velocity
[1] = 0.0f
;
2443 listener
->Velocity
[2] = 0.0f
;
2444 listener
->Forward
[0] = 0.0f
;
2445 listener
->Forward
[1] = 0.0f
;
2446 listener
->Forward
[2] = -1.0f
;
2447 listener
->Up
[0] = 0.0f
;
2448 listener
->Up
[1] = 1.0f
;
2449 listener
->Up
[2] = 0.0f
;
2451 aluMatrixfSet(&listener
->Params
.Matrix
,
2452 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2453 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2454 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2455 0.0f
, 0.0f
, 0.0f
, 1.0f
2457 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2458 listener
->Params
.Gain
= 1.0f
;
2459 listener
->Params
.MetersPerUnit
= 1.0f
;
2460 listener
->Params
.DopplerFactor
= 1.0f
;
2461 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2463 ATOMIC_INIT(&listener
->Update
, NULL
);
2464 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2467 InitRef(&Context
->UpdateCount
, 0);
2468 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2469 Context
->GainBoost
= 1.0f
;
2470 RWLockInit(&Context
->PropLock
);
2471 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2472 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2473 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2475 auxslots
= al_calloc(DEF_ALIGN
, offsetof(struct ALeffectslotArray
, slot
[0]));
2476 auxslots
->count
= 0;
2477 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2480 Context
->DistanceModel
= DefaultDistanceModel
;
2481 Context
->SourceDistanceModel
= AL_FALSE
;
2482 Context
->DopplerFactor
= 1.0f
;
2483 Context
->DopplerVelocity
= 1.0f
;
2484 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2485 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2487 Context
->ExtensionList
= alExtList
;
2493 * Cleans up the context, and destroys any remaining objects the app failed to
2494 * delete. Called once there's no more references on the context.
2496 static void FreeContext(ALCcontext
*context
)
2498 ALlistener
*listener
= context
->Listener
;
2499 struct ALeffectslotArray
*auxslots
;
2500 struct ALlistenerProps
*lprops
;
2503 TRACE("%p\n", context
);
2505 auxslots
= ATOMIC_EXCHANGE(struct ALeffectslotArray
*, &context
->ActiveAuxSlots
,
2506 NULL
, almemory_order_relaxed
);
2509 if(context
->SourceMap
.size
> 0)
2511 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2512 (context
->SourceMap
.size
==1)?"":"s");
2513 ReleaseALSources(context
);
2515 ResetUIntMap(&context
->SourceMap
);
2517 if(context
->EffectSlotMap
.size
> 0)
2519 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2520 (context
->EffectSlotMap
.size
==1)?"":"s");
2521 ReleaseALAuxiliaryEffectSlots(context
);
2523 ResetUIntMap(&context
->EffectSlotMap
);
2525 al_free(context
->Voices
);
2526 context
->Voices
= NULL
;
2527 context
->VoiceCount
= 0;
2528 context
->MaxVoices
= 0;
2530 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2532 TRACE("Freed unapplied listener update %p\n", lprops
);
2536 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2539 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2544 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2546 ALCdevice_DecRef(context
->Device
);
2547 context
->Device
= NULL
;
2549 //Invalidate context
2550 memset(context
, 0, sizeof(ALCcontext
));
2556 * Removes the context reference from the given device and removes it from
2557 * being current on the running thread or globally. Returns true if other
2558 * contexts still exist on the device.
2560 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2562 ALCcontext
*origctx
, *newhead
;
2565 if(altss_get(LocalContext
) == context
)
2567 WARN("%p released while current on thread\n", context
);
2568 altss_set(LocalContext
, NULL
);
2569 ALCcontext_DecRef(context
);
2573 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &GlobalContext
, &origctx
, NULL
))
2574 ALCcontext_DecRef(context
);
2576 ALCdevice_Lock(device
);
2578 newhead
= context
->next
;
2579 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &device
->ContextList
, &origctx
, newhead
))
2581 ALCcontext
*volatile*list
= &origctx
->next
;
2584 if(*list
== context
)
2586 *list
= (*list
)->next
;
2589 list
= &(*list
)->next
;
2594 ALCdevice_Unlock(device
);
2596 ALCcontext_DecRef(context
);
2600 void ALCcontext_IncRef(ALCcontext
*context
)
2602 uint ref
= IncrementRef(&context
->ref
);
2603 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2606 void ALCcontext_DecRef(ALCcontext
*context
)
2608 uint ref
= DecrementRef(&context
->ref
);
2609 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2610 if(ref
== 0) FreeContext(context
);
2613 static void ReleaseThreadCtx(void *ptr
)
2615 ALCcontext
*context
= ptr
;
2616 uint ref
= DecrementRef(&context
->ref
);
2617 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2618 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2623 * Checks that the given context is valid, and increments its reference count.
2625 static ALCboolean
VerifyContext(ALCcontext
**context
)
2630 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2633 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2638 ALCcontext_IncRef(ctx
);
2655 * Returns the currently active context for this thread, and adds a reference
2656 * without locking it.
2658 ALCcontext
*GetContextRef(void)
2660 ALCcontext
*context
;
2662 context
= altss_get(LocalContext
);
2664 ALCcontext_IncRef(context
);
2668 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2670 ALCcontext_IncRef(context
);
2678 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2680 ALCdevice
*device
= context
->Device
;
2681 ALsizei num_sends
= device
->NumAuxSends
;
2682 struct ALsourceProps
*props
;
2683 size_t sizeof_props
;
2684 size_t sizeof_voice
;
2690 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2693 /* Allocate the voice pointers, voices, and the voices' stored source
2694 * property set (including the dynamically-sized Send[] array) in one
2697 sizeof_props
= RoundUp(offsetof(struct ALsourceProps
, Send
[num_sends
]), 16);
2698 sizeof_voice
= RoundUp(offsetof(ALvoice
, Send
[num_sends
]), 16);
2699 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2701 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2702 /* The voice and property objects are stored interleaved since they're
2705 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2706 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2710 ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2711 for(;v
< v_count
;v
++)
2713 ALsizei s_count
= mini(old_sends
, num_sends
);
2716 /* Copy the old voice data and source property set to the new
2719 *voice
= *(context
->Voices
[v
]);
2720 for(i
= 0;i
< s_count
;i
++)
2721 voice
->Send
[i
] = context
->Voices
[v
]->Send
[i
];
2722 *props
= *(context
->Voices
[v
]->Props
);
2723 for(i
= 0;i
< s_count
;i
++)
2724 props
->Send
[i
] = context
->Voices
[v
]->Props
->Send
[i
];
2726 /* Set this voice's property set pointer and voice reference. */
2727 voice
->Props
= props
;
2730 /* Increment pointers to the next storage space. */
2731 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2732 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2735 /* Finish setting the voices' property set pointers and references. */
2736 for(;v
< num_voices
;v
++)
2738 voice
->Props
= props
;
2741 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2742 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2745 al_free(context
->Voices
);
2746 context
->Voices
= voices
;
2747 context
->MaxVoices
= num_voices
;
2748 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2752 /************************************************
2753 * Standard ALC functions
2754 ************************************************/
2758 * Return last ALC generated error code for the given device
2760 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2764 if(VerifyDevice(&device
))
2766 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &device
->LastError
, ALC_NO_ERROR
);
2767 ALCdevice_DecRef(device
);
2770 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &LastNullDeviceError
, ALC_NO_ERROR
);
2776 /* alcSuspendContext
2778 * Suspends updates for the given context
2780 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2785 if(!VerifyContext(&context
))
2786 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2789 ALCcontext_DeferUpdates(context
);
2790 ALCcontext_DecRef(context
);
2794 /* alcProcessContext
2796 * Resumes processing updates for the given context
2798 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2803 if(!VerifyContext(&context
))
2804 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2807 ALCcontext_ProcessUpdates(context
);
2808 ALCcontext_DecRef(context
);
2815 * Returns information about the device, and error strings
2817 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2819 const ALCchar
*value
= NULL
;
2827 case ALC_INVALID_ENUM
:
2828 value
= alcErrInvalidEnum
;
2831 case ALC_INVALID_VALUE
:
2832 value
= alcErrInvalidValue
;
2835 case ALC_INVALID_DEVICE
:
2836 value
= alcErrInvalidDevice
;
2839 case ALC_INVALID_CONTEXT
:
2840 value
= alcErrInvalidContext
;
2843 case ALC_OUT_OF_MEMORY
:
2844 value
= alcErrOutOfMemory
;
2847 case ALC_DEVICE_SPECIFIER
:
2848 value
= alcDefaultName
;
2851 case ALC_ALL_DEVICES_SPECIFIER
:
2852 if(VerifyDevice(&Device
))
2854 value
= alstr_get_cstr(Device
->DeviceName
);
2855 ALCdevice_DecRef(Device
);
2859 ProbeAllDevicesList();
2860 value
= alstr_get_cstr(alcAllDevicesList
);
2864 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2865 if(VerifyDevice(&Device
))
2867 value
= alstr_get_cstr(Device
->DeviceName
);
2868 ALCdevice_DecRef(Device
);
2872 ProbeCaptureDeviceList();
2873 value
= alstr_get_cstr(alcCaptureDeviceList
);
2877 /* Default devices are always first in the list */
2878 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2879 value
= alcDefaultName
;
2882 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2883 if(alstr_empty(alcAllDevicesList
))
2884 ProbeAllDevicesList();
2886 VerifyDevice(&Device
);
2888 free(alcDefaultAllDevicesSpecifier
);
2889 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
2890 if(!alcDefaultAllDevicesSpecifier
)
2891 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2893 value
= alcDefaultAllDevicesSpecifier
;
2894 if(Device
) ALCdevice_DecRef(Device
);
2897 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2898 if(alstr_empty(alcCaptureDeviceList
))
2899 ProbeCaptureDeviceList();
2901 VerifyDevice(&Device
);
2903 free(alcCaptureDefaultDeviceSpecifier
);
2904 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
2905 if(!alcCaptureDefaultDeviceSpecifier
)
2906 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2908 value
= alcCaptureDefaultDeviceSpecifier
;
2909 if(Device
) ALCdevice_DecRef(Device
);
2912 case ALC_EXTENSIONS
:
2913 if(!VerifyDevice(&Device
))
2914 value
= alcNoDeviceExtList
;
2917 value
= alcExtensionList
;
2918 ALCdevice_DecRef(Device
);
2922 case ALC_HRTF_SPECIFIER_SOFT
:
2923 if(!VerifyDevice(&Device
))
2924 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2927 almtx_lock(&Device
->BackendLock
);
2928 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
2929 almtx_unlock(&Device
->BackendLock
);
2930 ALCdevice_DecRef(Device
);
2935 VerifyDevice(&Device
);
2936 alcSetError(Device
, ALC_INVALID_ENUM
);
2937 if(Device
) ALCdevice_DecRef(Device
);
2945 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2947 if(device
->Type
== Loopback
&& device
->FmtChans
>= DevFmtAmbi1
&&
2948 device
->FmtChans
<= DevFmtAmbi3
)
2953 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2957 if(size
<= 0 || values
== NULL
)
2959 alcSetError(device
, ALC_INVALID_VALUE
);
2967 case ALC_MAJOR_VERSION
:
2968 values
[0] = alcMajorVersion
;
2970 case ALC_MINOR_VERSION
:
2971 values
[0] = alcMinorVersion
;
2974 case ALC_ATTRIBUTES_SIZE
:
2975 case ALC_ALL_ATTRIBUTES
:
2979 case ALC_MONO_SOURCES
:
2980 case ALC_STEREO_SOURCES
:
2981 case ALC_CAPTURE_SAMPLES
:
2982 case ALC_FORMAT_CHANNELS_SOFT
:
2983 case ALC_FORMAT_TYPE_SOFT
:
2984 case ALC_AMBISONIC_LAYOUT_SOFT
:
2985 case ALC_AMBISONIC_SCALING_SOFT
:
2986 case ALC_AMBISONIC_ORDER_SOFT
:
2987 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2991 alcSetError(NULL
, ALC_INVALID_ENUM
);
2997 if(device
->Type
== Capture
)
3001 case ALC_CAPTURE_SAMPLES
:
3002 almtx_lock(&device
->BackendLock
);
3003 values
[0] = V0(device
->Backend
,availableSamples
)();
3004 almtx_unlock(&device
->BackendLock
);
3008 values
[0] = device
->Connected
;
3012 alcSetError(device
, ALC_INVALID_ENUM
);
3021 case ALC_MAJOR_VERSION
:
3022 values
[0] = alcMajorVersion
;
3025 case ALC_MINOR_VERSION
:
3026 values
[0] = alcMinorVersion
;
3029 case ALC_EFX_MAJOR_VERSION
:
3030 values
[0] = alcEFXMajorVersion
;
3033 case ALC_EFX_MINOR_VERSION
:
3034 values
[0] = alcEFXMinorVersion
;
3037 case ALC_ATTRIBUTES_SIZE
:
3038 values
[0] = NumAttrsForDevice(device
);
3041 case ALC_ALL_ATTRIBUTES
:
3042 if(size
< NumAttrsForDevice(device
))
3044 alcSetError(device
, ALC_INVALID_VALUE
);
3049 almtx_lock(&device
->BackendLock
);
3050 values
[i
++] = ALC_FREQUENCY
;
3051 values
[i
++] = device
->Frequency
;
3053 if(device
->Type
!= Loopback
)
3055 values
[i
++] = ALC_REFRESH
;
3056 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3058 values
[i
++] = ALC_SYNC
;
3059 values
[i
++] = ALC_FALSE
;
3063 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3065 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3066 values
[i
++] = device
->AmbiLayout
;
3068 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3069 values
[i
++] = device
->AmbiScale
;
3071 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3072 values
[i
++] = device
->FmtChans
-DevFmtAmbi1
+1;
3074 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3075 values
[i
++] = ALC_BFORMAT3D_SOFT
;
3079 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3080 values
[i
++] = device
->FmtChans
;
3083 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3084 values
[i
++] = device
->FmtType
;
3087 values
[i
++] = ALC_MONO_SOURCES
;
3088 values
[i
++] = device
->NumMonoSources
;
3090 values
[i
++] = ALC_STEREO_SOURCES
;
3091 values
[i
++] = device
->NumStereoSources
;
3093 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3094 values
[i
++] = device
->NumAuxSends
;
3096 values
[i
++] = ALC_HRTF_SOFT
;
3097 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3099 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3100 values
[i
++] = device
->HrtfStatus
;
3101 almtx_unlock(&device
->BackendLock
);
3107 values
[0] = device
->Frequency
;
3111 if(device
->Type
== Loopback
)
3113 alcSetError(device
, ALC_INVALID_DEVICE
);
3116 almtx_lock(&device
->BackendLock
);
3117 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3118 almtx_unlock(&device
->BackendLock
);
3122 if(device
->Type
== Loopback
)
3124 alcSetError(device
, ALC_INVALID_DEVICE
);
3127 values
[0] = ALC_FALSE
;
3130 case ALC_FORMAT_CHANNELS_SOFT
:
3131 if(device
->Type
!= Loopback
)
3133 alcSetError(device
, ALC_INVALID_DEVICE
);
3136 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3137 values
[0] = ALC_BFORMAT3D_SOFT
;
3139 values
[0] = device
->FmtChans
;
3142 case ALC_FORMAT_TYPE_SOFT
:
3143 if(device
->Type
!= Loopback
)
3145 alcSetError(device
, ALC_INVALID_DEVICE
);
3148 values
[0] = device
->FmtType
;
3151 case ALC_AMBISONIC_LAYOUT_SOFT
:
3152 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3153 device
->FmtChans
<= DevFmtAmbi3
))
3155 alcSetError(device
, ALC_INVALID_DEVICE
);
3158 values
[0] = device
->AmbiLayout
;
3161 case ALC_AMBISONIC_SCALING_SOFT
:
3162 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3163 device
->FmtChans
<= DevFmtAmbi3
))
3165 alcSetError(device
, ALC_INVALID_DEVICE
);
3168 values
[0] = device
->AmbiScale
;
3171 case ALC_AMBISONIC_ORDER_SOFT
:
3172 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3173 device
->FmtChans
<= DevFmtAmbi3
))
3175 alcSetError(device
, ALC_INVALID_DEVICE
);
3178 values
[0] = device
->FmtChans
- DevFmtAmbi1
+ 1;
3181 case ALC_MONO_SOURCES
:
3182 values
[0] = device
->NumMonoSources
;
3185 case ALC_STEREO_SOURCES
:
3186 values
[0] = device
->NumStereoSources
;
3189 case ALC_MAX_AUXILIARY_SENDS
:
3190 values
[0] = device
->NumAuxSends
;
3194 values
[0] = device
->Connected
;
3198 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3201 case ALC_HRTF_STATUS_SOFT
:
3202 values
[0] = device
->HrtfStatus
;
3205 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3206 almtx_lock(&device
->BackendLock
);
3207 FreeHrtfList(&device
->HrtfList
);
3208 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3209 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3210 almtx_unlock(&device
->BackendLock
);
3214 alcSetError(device
, ALC_INVALID_ENUM
);
3222 * Returns information about the device and the version of OpenAL
3224 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3226 VerifyDevice(&device
);
3227 if(size
<= 0 || values
== NULL
)
3228 alcSetError(device
, ALC_INVALID_VALUE
);
3230 GetIntegerv(device
, param
, size
, values
);
3231 if(device
) ALCdevice_DecRef(device
);
3234 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3239 VerifyDevice(&device
);
3240 if(size
<= 0 || values
== NULL
)
3241 alcSetError(device
, ALC_INVALID_VALUE
);
3242 else if(!device
|| device
->Type
== Capture
)
3244 ivals
= malloc(size
* sizeof(ALCint
));
3245 size
= GetIntegerv(device
, pname
, size
, ivals
);
3246 for(i
= 0;i
< size
;i
++)
3247 values
[i
] = ivals
[i
];
3250 else /* render device */
3259 case ALC_ATTRIBUTES_SIZE
:
3260 *values
= NumAttrsForDevice(device
)+2;
3263 case ALC_ALL_ATTRIBUTES
:
3264 if(size
< NumAttrsForDevice(device
)+2)
3265 alcSetError(device
, ALC_INVALID_VALUE
);
3269 almtx_lock(&device
->BackendLock
);
3270 values
[i
++] = ALC_FREQUENCY
;
3271 values
[i
++] = device
->Frequency
;
3273 if(device
->Type
!= Loopback
)
3275 values
[i
++] = ALC_REFRESH
;
3276 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3278 values
[i
++] = ALC_SYNC
;
3279 values
[i
++] = ALC_FALSE
;
3283 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3285 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3286 values
[i
++] = device
->AmbiLayout
;
3288 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3289 values
[i
++] = device
->AmbiScale
;
3291 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3292 values
[i
++] = device
->FmtChans
-DevFmtAmbi1
+1;
3294 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3295 values
[i
++] = ALC_BFORMAT3D_SOFT
;
3299 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3300 values
[i
++] = device
->FmtChans
;
3303 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3304 values
[i
++] = device
->FmtType
;
3307 values
[i
++] = ALC_MONO_SOURCES
;
3308 values
[i
++] = device
->NumMonoSources
;
3310 values
[i
++] = ALC_STEREO_SOURCES
;
3311 values
[i
++] = device
->NumStereoSources
;
3313 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3314 values
[i
++] = device
->NumAuxSends
;
3316 values
[i
++] = ALC_HRTF_SOFT
;
3317 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3319 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3320 values
[i
++] = device
->HrtfStatus
;
3322 clock
= V0(device
->Backend
,getClockLatency
)();
3323 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3324 values
[i
++] = clock
.ClockTime
;
3326 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3327 values
[i
++] = clock
.Latency
;
3328 almtx_unlock(&device
->BackendLock
);
3334 case ALC_DEVICE_CLOCK_SOFT
:
3335 almtx_lock(&device
->BackendLock
);
3337 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3339 basecount
= device
->ClockBase
;
3340 samplecount
= device
->SamplesDone
;
3341 } while(refcount
!= ReadRef(&device
->MixCount
));
3342 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3343 almtx_unlock(&device
->BackendLock
);
3346 case ALC_DEVICE_LATENCY_SOFT
:
3347 almtx_lock(&device
->BackendLock
);
3348 clock
= V0(device
->Backend
,getClockLatency
)();
3349 almtx_unlock(&device
->BackendLock
);
3350 *values
= clock
.Latency
;
3353 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3355 alcSetError(device
, ALC_INVALID_VALUE
);
3358 almtx_lock(&device
->BackendLock
);
3359 clock
= V0(device
->Backend
,getClockLatency
)();
3360 almtx_unlock(&device
->BackendLock
);
3361 values
[0] = clock
.ClockTime
;
3362 values
[1] = clock
.Latency
;
3367 ivals
= malloc(size
* sizeof(ALCint
));
3368 size
= GetIntegerv(device
, pname
, size
, ivals
);
3369 for(i
= 0;i
< size
;i
++)
3370 values
[i
] = ivals
[i
];
3376 ALCdevice_DecRef(device
);
3380 /* alcIsExtensionPresent
3382 * Determines if there is support for a particular extension
3384 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3386 ALCboolean bResult
= ALC_FALSE
;
3388 VerifyDevice(&device
);
3391 alcSetError(device
, ALC_INVALID_VALUE
);
3394 size_t len
= strlen(extName
);
3395 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3398 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3399 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3404 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3408 } while(isspace(*ptr
));
3413 ALCdevice_DecRef(device
);
3418 /* alcGetProcAddress
3420 * Retrieves the function address for a particular extension function
3422 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3424 ALCvoid
*ptr
= NULL
;
3428 VerifyDevice(&device
);
3429 alcSetError(device
, ALC_INVALID_VALUE
);
3430 if(device
) ALCdevice_DecRef(device
);
3435 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3437 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3439 ptr
= alcFunctions
[i
].address
;
3451 * Get the value for a particular ALC enumeration name
3453 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3459 VerifyDevice(&device
);
3460 alcSetError(device
, ALC_INVALID_VALUE
);
3461 if(device
) ALCdevice_DecRef(device
);
3466 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3468 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3470 val
= alcEnumerations
[i
].value
;
3482 * Create and attach a context to the given device.
3484 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3486 ALCcontext
*ALContext
;
3490 /* Explicitly hold the list lock while taking the BackendLock in case the
3491 * device is asynchronously destropyed, to ensure this new context is
3492 * properly cleaned up after being made.
3495 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3498 alcSetError(device
, ALC_INVALID_DEVICE
);
3499 if(device
) ALCdevice_DecRef(device
);
3502 almtx_lock(&device
->BackendLock
);
3505 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3507 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3510 InitRef(&ALContext
->ref
, 1);
3511 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3513 ALContext
->Device
= device
;
3514 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3516 ALContext
->Voices
= NULL
;
3517 ALContext
->MaxVoices
= 0;
3518 ALContext
->VoiceCount
= 0;
3519 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3521 if(!ALContext
|| !ALContext
->Voices
)
3523 almtx_unlock(&device
->BackendLock
);
3527 al_free(ALContext
->Voices
);
3528 ALContext
->Voices
= NULL
;
3534 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3535 ALCdevice_DecRef(device
);
3539 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3541 almtx_unlock(&device
->BackendLock
);
3543 al_free(ALContext
->Voices
);
3544 ALContext
->Voices
= NULL
;
3549 alcSetError(device
, err
);
3550 if(err
== ALC_INVALID_DEVICE
)
3552 V0(device
->Backend
,lock
)();
3553 aluHandleDisconnect(device
);
3554 V0(device
->Backend
,unlock
)();
3556 ALCdevice_DecRef(device
);
3560 ALCdevice_IncRef(ALContext
->Device
);
3561 InitContext(ALContext
);
3563 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3566 ERR("volume-adjust must be finite: %f\n", valf
);
3569 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3571 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3572 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3573 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3576 UpdateListenerProps(ALContext
);
3579 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3581 ALContext
->next
= head
;
3582 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext
*,
3583 &device
->ContextList
, &head
, ALContext
) == 0);
3585 almtx_unlock(&device
->BackendLock
);
3587 ALCdevice_DecRef(device
);
3589 TRACE("Created context %p\n", ALContext
);
3593 /* alcDestroyContext
3595 * Remove a context from its device
3597 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3602 if(!VerifyContext(&context
))
3605 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3609 Device
= context
->Device
;
3612 almtx_lock(&Device
->BackendLock
);
3613 if(!ReleaseContext(context
, Device
))
3615 V0(Device
->Backend
,stop
)();
3616 Device
->Flags
&= ~DEVICE_RUNNING
;
3618 almtx_unlock(&Device
->BackendLock
);
3622 ALCcontext_DecRef(context
);
3626 /* alcGetCurrentContext
3628 * Returns the currently active context on the calling thread
3630 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3632 ALCcontext
*Context
= altss_get(LocalContext
);
3633 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3637 /* alcGetThreadContext
3639 * Returns the currently active thread-local context
3641 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3643 return altss_get(LocalContext
);
3647 /* alcMakeContextCurrent
3649 * Makes the given context the active process-wide context, and removes the
3650 * thread-local context for the calling thread.
3652 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3654 /* context must be valid or NULL */
3655 if(context
&& !VerifyContext(&context
))
3657 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3660 /* context's reference count is already incremented */
3661 context
= ATOMIC_EXCHANGE_SEQ(ALCcontext
*, &GlobalContext
, context
);
3662 if(context
) ALCcontext_DecRef(context
);
3664 if((context
=altss_get(LocalContext
)) != NULL
)
3666 altss_set(LocalContext
, NULL
);
3667 ALCcontext_DecRef(context
);
3673 /* alcSetThreadContext
3675 * Makes the given context the active context for the current thread
3677 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3681 /* context must be valid or NULL */
3682 if(context
&& !VerifyContext(&context
))
3684 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3687 /* context's reference count is already incremented */
3688 old
= altss_get(LocalContext
);
3689 altss_set(LocalContext
, context
);
3690 if(old
) ALCcontext_DecRef(old
);
3696 /* alcGetContextsDevice
3698 * Returns the device that a particular context is attached to
3700 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3704 if(!VerifyContext(&Context
))
3706 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3709 Device
= Context
->Device
;
3710 ALCcontext_DecRef(Context
);
3718 * Opens the named device.
3720 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3729 if(!PlaybackBackend
.name
)
3731 alcSetError(NULL
, ALC_INVALID_VALUE
);
3735 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3737 /* Some old Windows apps hardcode these expecting OpenAL to use a
3738 * specific audio API, even when they're not enumerated. Creative's
3739 * router effectively ignores them too.
3741 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3742 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3747 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3750 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3755 InitRef(&device
->ref
, 1);
3756 device
->Connected
= ALC_TRUE
;
3757 device
->Type
= Playback
;
3758 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3761 device
->Bs2b
= NULL
;
3762 device
->Uhj_Encoder
= NULL
;
3763 device
->Hrtf
= NULL
;
3764 device
->HrtfHandle
= NULL
;
3765 VECTOR_INIT(device
->HrtfList
);
3766 AL_STRING_INIT(device
->HrtfName
);
3767 device
->Render_Mode
= NormalRender
;
3768 AL_STRING_INIT(device
->DeviceName
);
3769 device
->Dry
.Buffer
= NULL
;
3770 device
->Dry
.NumChannels
= 0;
3771 device
->FOAOut
.Buffer
= NULL
;
3772 device
->FOAOut
.NumChannels
= 0;
3773 device
->RealOut
.Buffer
= NULL
;
3774 device
->RealOut
.NumChannels
= 0;
3775 device
->AvgSpeakerDist
= 0.0f
;
3777 ATOMIC_INIT(&device
->ContextList
, NULL
);
3779 device
->ClockBase
= 0;
3780 device
->SamplesDone
= 0;
3782 device
->SourcesMax
= 256;
3783 device
->AuxiliaryEffectSlotMax
= 64;
3784 device
->NumAuxSends
= DEFAULT_SENDS
;
3786 InitUIntMap(&device
->BufferMap
, ~0);
3787 InitUIntMap(&device
->EffectMap
, ~0);
3788 InitUIntMap(&device
->FilterMap
, ~0);
3790 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3792 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3793 device
->ChannelDelay
[i
].Length
= 0;
3794 device
->ChannelDelay
[i
].Buffer
= NULL
;
3798 device
->FmtChans
= DevFmtChannelsDefault
;
3799 device
->FmtType
= DevFmtTypeDefault
;
3800 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3801 device
->IsHeadphones
= AL_FALSE
;
3802 device
->AmbiLayout
= AmbiLayout_Default
;
3803 device
->AmbiScale
= AmbiNorm_Default
;
3804 device
->NumUpdates
= 3;
3805 device
->UpdateSize
= 1024;
3807 if(!PlaybackBackend
.getFactory
)
3808 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3809 ALCbackend_Playback
);
3812 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3813 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3815 if(!device
->Backend
)
3818 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3823 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3825 static const struct {
3826 const char name
[16];
3827 enum DevFmtChannels chans
;
3829 { "mono", DevFmtMono
},
3830 { "stereo", DevFmtStereo
},
3831 { "quad", DevFmtQuad
},
3832 { "surround51", DevFmtX51
},
3833 { "surround61", DevFmtX61
},
3834 { "surround71", DevFmtX71
},
3835 { "surround51rear", DevFmtX51Rear
},
3836 { "ambi1", DevFmtAmbi1
},
3837 { "ambi2", DevFmtAmbi2
},
3838 { "ambi3", DevFmtAmbi3
},
3842 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3844 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3846 device
->FmtChans
= chanlist
[i
].chans
;
3847 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3851 if(i
== COUNTOF(chanlist
))
3852 ERR("Unsupported channels: %s\n", fmt
);
3854 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3856 static const struct {
3857 const char name
[16];
3858 enum DevFmtType type
;
3860 { "int8", DevFmtByte
},
3861 { "uint8", DevFmtUByte
},
3862 { "int16", DevFmtShort
},
3863 { "uint16", DevFmtUShort
},
3864 { "int32", DevFmtInt
},
3865 { "uint32", DevFmtUInt
},
3866 { "float32", DevFmtFloat
},
3870 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3872 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3874 device
->FmtType
= typelist
[i
].type
;
3875 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3879 if(i
== COUNTOF(typelist
))
3880 ERR("Unsupported sample-type: %s\n", fmt
);
3883 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3885 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3886 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3887 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3888 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3891 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3892 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3894 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3895 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3896 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3897 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3899 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3900 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3902 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3903 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3905 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3906 device
->NumAuxSends
= clampi(
3907 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3910 device
->NumStereoSources
= 1;
3911 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3913 // Find a playback device to open
3914 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3916 DELETE_OBJ(device
->Backend
);
3918 alcSetError(NULL
, err
);
3921 almtx_init(&device
->BackendLock
, almtx_plain
);
3923 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3925 if(strcasecmp(fmt
, "fuma") == 0)
3927 device
->AmbiLayout
= AmbiLayout_FuMa
;
3928 device
->AmbiScale
= AmbiNorm_FuMa
;
3930 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3932 device
->AmbiLayout
= AmbiLayout_ACN
;
3933 device
->AmbiScale
= AmbiNorm_SN3D
;
3935 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3937 device
->AmbiLayout
= AmbiLayout_ACN
;
3938 device
->AmbiScale
= AmbiNorm_N3D
;
3941 ERR("Unsupported ambi-format: %s\n", fmt
);
3944 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3946 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3947 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3949 device
->DefaultSlot
= NULL
;
3950 ERR("Failed to initialize the default effect slot\n");
3954 aluInitEffectPanning(device
->DefaultSlot
);
3955 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3957 DeinitEffectSlot(device
->DefaultSlot
);
3958 device
->DefaultSlot
= NULL
;
3959 ERR("Failed to initialize the default effect\n");
3965 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
3967 device
->next
= head
;
3968 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
3971 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
3977 * Closes the given device.
3979 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3981 ALCdevice
*iter
, *origdev
;
3985 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
3989 } while((iter
=iter
->next
) != NULL
);
3990 if(!iter
|| iter
->Type
== Capture
)
3992 alcSetError(iter
, ALC_INVALID_DEVICE
);
3996 almtx_lock(&device
->BackendLock
);
3999 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
4001 ALCdevice
*volatile*list
= &origdev
->next
;
4006 *list
= (*list
)->next
;
4009 list
= &(*list
)->next
;
4014 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4017 ALCcontext
*next
= ctx
->next
;
4018 WARN("Releasing context %p\n", ctx
);
4019 ReleaseContext(ctx
, device
);
4022 if((device
->Flags
&DEVICE_RUNNING
))
4023 V0(device
->Backend
,stop
)();
4024 device
->Flags
&= ~DEVICE_RUNNING
;
4025 almtx_unlock(&device
->BackendLock
);
4027 ALCdevice_DecRef(device
);
4033 /************************************************
4034 * ALC capture functions
4035 ************************************************/
4036 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4038 ALCdevice
*device
= NULL
;
4044 if(!CaptureBackend
.name
)
4046 alcSetError(NULL
, ALC_INVALID_VALUE
);
4052 alcSetError(NULL
, ALC_INVALID_VALUE
);
4056 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4059 device
= al_calloc(16, sizeof(ALCdevice
));
4062 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4067 InitRef(&device
->ref
, 1);
4068 device
->Connected
= ALC_TRUE
;
4069 device
->Type
= Capture
;
4071 device
->Hrtf
= NULL
;
4072 device
->HrtfHandle
= NULL
;
4073 VECTOR_INIT(device
->HrtfList
);
4074 AL_STRING_INIT(device
->HrtfName
);
4076 AL_STRING_INIT(device
->DeviceName
);
4077 device
->Dry
.Buffer
= NULL
;
4078 device
->Dry
.NumChannels
= 0;
4079 device
->FOAOut
.Buffer
= NULL
;
4080 device
->FOAOut
.NumChannels
= 0;
4081 device
->RealOut
.Buffer
= NULL
;
4082 device
->RealOut
.NumChannels
= 0;
4084 InitUIntMap(&device
->BufferMap
, ~0);
4085 InitUIntMap(&device
->EffectMap
, ~0);
4086 InitUIntMap(&device
->FilterMap
, ~0);
4088 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4090 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4091 device
->ChannelDelay
[i
].Length
= 0;
4092 device
->ChannelDelay
[i
].Buffer
= NULL
;
4095 if(!CaptureBackend
.getFactory
)
4096 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4097 ALCbackend_Capture
);
4100 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4101 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4103 if(!device
->Backend
)
4106 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4110 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4111 device
->Frequency
= frequency
;
4113 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4114 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4117 alcSetError(NULL
, ALC_INVALID_ENUM
);
4120 device
->IsHeadphones
= AL_FALSE
;
4121 device
->AmbiLayout
= AmbiLayout_Default
;
4122 device
->AmbiScale
= AmbiNorm_Default
;
4124 device
->UpdateSize
= samples
;
4125 device
->NumUpdates
= 1;
4127 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4128 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4129 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4131 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4134 alcSetError(NULL
, err
);
4137 almtx_init(&device
->BackendLock
, almtx_plain
);
4140 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4142 device
->next
= head
;
4143 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4146 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4150 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4152 ALCdevice
*iter
, *origdev
;
4155 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4159 } while((iter
=iter
->next
) != NULL
);
4160 if(!iter
|| iter
->Type
!= Capture
)
4162 alcSetError(iter
, ALC_INVALID_DEVICE
);
4168 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
4170 ALCdevice
*volatile*list
= &origdev
->next
;
4175 *list
= (*list
)->next
;
4178 list
= &(*list
)->next
;
4183 ALCdevice_DecRef(device
);
4188 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4190 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4191 alcSetError(device
, ALC_INVALID_DEVICE
);
4194 almtx_lock(&device
->BackendLock
);
4195 if(!device
->Connected
)
4196 alcSetError(device
, ALC_INVALID_DEVICE
);
4197 else if(!(device
->Flags
&DEVICE_RUNNING
))
4199 if(V0(device
->Backend
,start
)())
4200 device
->Flags
|= DEVICE_RUNNING
;
4203 aluHandleDisconnect(device
);
4204 alcSetError(device
, ALC_INVALID_DEVICE
);
4207 almtx_unlock(&device
->BackendLock
);
4210 if(device
) ALCdevice_DecRef(device
);
4213 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4215 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4216 alcSetError(device
, ALC_INVALID_DEVICE
);
4219 almtx_lock(&device
->BackendLock
);
4220 if((device
->Flags
&DEVICE_RUNNING
))
4221 V0(device
->Backend
,stop
)();
4222 device
->Flags
&= ~DEVICE_RUNNING
;
4223 almtx_unlock(&device
->BackendLock
);
4226 if(device
) ALCdevice_DecRef(device
);
4229 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4231 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4232 alcSetError(device
, ALC_INVALID_DEVICE
);
4235 ALCenum err
= ALC_INVALID_VALUE
;
4237 almtx_lock(&device
->BackendLock
);
4238 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4239 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4240 almtx_unlock(&device
->BackendLock
);
4242 if(err
!= ALC_NO_ERROR
)
4243 alcSetError(device
, err
);
4245 if(device
) ALCdevice_DecRef(device
);
4249 /************************************************
4250 * ALC loopback functions
4251 ************************************************/
4253 /* alcLoopbackOpenDeviceSOFT
4255 * Open a loopback device, for manual rendering.
4257 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4259 ALCbackendFactory
*factory
;
4265 /* Make sure the device name, if specified, is us. */
4266 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4268 alcSetError(NULL
, ALC_INVALID_VALUE
);
4272 device
= al_calloc(16, sizeof(ALCdevice
));
4275 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4280 InitRef(&device
->ref
, 1);
4281 device
->Connected
= ALC_TRUE
;
4282 device
->Type
= Loopback
;
4283 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4286 device
->Hrtf
= NULL
;
4287 device
->HrtfHandle
= NULL
;
4288 VECTOR_INIT(device
->HrtfList
);
4289 AL_STRING_INIT(device
->HrtfName
);
4290 device
->Bs2b
= NULL
;
4291 device
->Uhj_Encoder
= NULL
;
4292 device
->Render_Mode
= NormalRender
;
4293 AL_STRING_INIT(device
->DeviceName
);
4294 device
->Dry
.Buffer
= NULL
;
4295 device
->Dry
.NumChannels
= 0;
4296 device
->FOAOut
.Buffer
= NULL
;
4297 device
->FOAOut
.NumChannels
= 0;
4298 device
->RealOut
.Buffer
= NULL
;
4299 device
->RealOut
.NumChannels
= 0;
4300 device
->AvgSpeakerDist
= 0.0f
;
4302 ATOMIC_INIT(&device
->ContextList
, NULL
);
4304 device
->ClockBase
= 0;
4305 device
->SamplesDone
= 0;
4307 device
->SourcesMax
= 256;
4308 device
->AuxiliaryEffectSlotMax
= 64;
4309 device
->NumAuxSends
= DEFAULT_SENDS
;
4311 InitUIntMap(&device
->BufferMap
, ~0);
4312 InitUIntMap(&device
->EffectMap
, ~0);
4313 InitUIntMap(&device
->FilterMap
, ~0);
4315 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4317 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4318 device
->ChannelDelay
[i
].Length
= 0;
4319 device
->ChannelDelay
[i
].Buffer
= NULL
;
4322 factory
= ALCloopbackFactory_getFactory();
4323 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4324 if(!device
->Backend
)
4327 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4330 almtx_init(&device
->BackendLock
, almtx_plain
);
4333 device
->NumUpdates
= 0;
4334 device
->UpdateSize
= 0;
4336 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4337 device
->FmtChans
= DevFmtChannelsDefault
;
4338 device
->FmtType
= DevFmtTypeDefault
;
4339 device
->IsHeadphones
= AL_FALSE
;
4340 device
->AmbiLayout
= AmbiLayout_Default
;
4341 device
->AmbiScale
= AmbiNorm_Default
;
4343 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4344 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4346 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4347 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4349 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4350 device
->NumAuxSends
= clampi(
4351 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4354 device
->NumStereoSources
= 1;
4355 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4357 // Open the "backend"
4358 V(device
->Backend
,open
)("Loopback");
4361 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4363 device
->next
= head
;
4364 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4367 TRACE("Created device %p\n", device
);
4371 /* alcIsRenderFormatSupportedSOFT
4373 * Determines if the loopback device supports the given format for rendering.
4375 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4377 ALCboolean ret
= ALC_FALSE
;
4379 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4380 alcSetError(device
, ALC_INVALID_DEVICE
);
4382 alcSetError(device
, ALC_INVALID_VALUE
);
4385 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4388 if(device
) ALCdevice_DecRef(device
);
4393 /* alcRenderSamplesSOFT
4395 * Renders some samples into a buffer, using the format last set by the
4396 * attributes given to alcCreateContext.
4398 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4400 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4401 alcSetError(device
, ALC_INVALID_DEVICE
);
4402 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4403 alcSetError(device
, ALC_INVALID_VALUE
);
4406 V0(device
->Backend
,lock
)();
4407 aluMixData(device
, buffer
, samples
);
4408 V0(device
->Backend
,unlock
)();
4410 if(device
) ALCdevice_DecRef(device
);
4414 /************************************************
4415 * ALC loopback2 functions
4416 ************************************************/
4418 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4420 ALCboolean ret
= ALC_FALSE
;
4422 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4423 alcSetError(device
, ALC_INVALID_DEVICE
);
4425 alcSetError(device
, ALC_INVALID_VALUE
);
4428 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4431 if(device
) ALCdevice_DecRef(device
);
4436 /************************************************
4437 * ALC DSP pause/resume functions
4438 ************************************************/
4440 /* alcDevicePauseSOFT
4442 * Pause the DSP to stop audio processing.
4444 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4446 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4447 alcSetError(device
, ALC_INVALID_DEVICE
);
4450 almtx_lock(&device
->BackendLock
);
4451 if((device
->Flags
&DEVICE_RUNNING
))
4452 V0(device
->Backend
,stop
)();
4453 device
->Flags
&= ~DEVICE_RUNNING
;
4454 device
->Flags
|= DEVICE_PAUSED
;
4455 almtx_unlock(&device
->BackendLock
);
4457 if(device
) ALCdevice_DecRef(device
);
4460 /* alcDeviceResumeSOFT
4462 * Resume the DSP to restart audio processing.
4464 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4466 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4467 alcSetError(device
, ALC_INVALID_DEVICE
);
4470 almtx_lock(&device
->BackendLock
);
4471 if((device
->Flags
&DEVICE_PAUSED
))
4473 device
->Flags
&= ~DEVICE_PAUSED
;
4474 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4476 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4477 device
->Flags
|= DEVICE_RUNNING
;
4480 alcSetError(device
, ALC_INVALID_DEVICE
);
4481 V0(device
->Backend
,lock
)();
4482 aluHandleDisconnect(device
);
4483 V0(device
->Backend
,unlock
)();
4487 almtx_unlock(&device
->BackendLock
);
4489 if(device
) ALCdevice_DecRef(device
);
4493 /************************************************
4494 * ALC HRTF functions
4495 ************************************************/
4497 /* alcGetStringiSOFT
4499 * Gets a string parameter at the given index.
4501 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4503 const ALCchar
*str
= NULL
;
4505 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4506 alcSetError(device
, ALC_INVALID_DEVICE
);
4507 else switch(paramName
)
4509 case ALC_HRTF_SPECIFIER_SOFT
:
4510 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4511 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4513 alcSetError(device
, ALC_INVALID_VALUE
);
4517 alcSetError(device
, ALC_INVALID_ENUM
);
4520 if(device
) ALCdevice_DecRef(device
);
4525 /* alcResetDeviceSOFT
4527 * Resets the given device output, using the specified attribute list.
4529 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4534 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4537 alcSetError(device
, ALC_INVALID_DEVICE
);
4538 if(device
) ALCdevice_DecRef(device
);
4541 almtx_lock(&device
->BackendLock
);
4544 err
= UpdateDeviceParams(device
, attribs
);
4545 almtx_unlock(&device
->BackendLock
);
4547 if(err
!= ALC_NO_ERROR
)
4549 alcSetError(device
, err
);
4550 if(err
== ALC_INVALID_DEVICE
)
4552 V0(device
->Backend
,lock
)();
4553 aluHandleDisconnect(device
);
4554 V0(device
->Backend
,unlock
)();
4556 ALCdevice_DecRef(device
);
4559 ALCdevice_DecRef(device
);