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", NULL
, alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, 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 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2054 VECTOR_DEINIT(device
->HrtfList
);
2055 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2057 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2059 device
->FmtChans
= DevFmtStereo
;
2060 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2061 device
->Frequency
= VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
->sampleRate
;
2063 device
->Frequency
= VECTOR_ELEM(device
->HrtfList
, 0).hrtf
->sampleRate
;
2064 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2068 hrtf_userreq
= Hrtf_Default
;
2069 hrtf_appreq
= Hrtf_Disable
;
2070 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2074 else if(hrtf_appreq
== Hrtf_Enable
)
2076 size_t i
= VECTOR_SIZE(device
->HrtfList
);
2077 /* Loopback device. We don't need to match to a specific HRTF entry
2078 * here. If the requested ID matches, we'll pick that later, if not,
2079 * we'll try to auto-select one anyway. Just make sure one exists
2082 if(device
->FmtChans
== DevFmtStereo
)
2084 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2086 VECTOR_DEINIT(device
->HrtfList
);
2087 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2089 for(i
= 0;i
< VECTOR_SIZE(device
->HrtfList
);i
++)
2091 const struct Hrtf
*hrtf
= VECTOR_ELEM(device
->HrtfList
, i
).hrtf
;
2092 if(hrtf
->sampleRate
== device
->Frequency
)
2096 if(i
== VECTOR_SIZE(device
->HrtfList
))
2098 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2099 DevFmtChannelsString(device
->FmtChans
), device
->Frequency
);
2100 hrtf_appreq
= Hrtf_Disable
;
2101 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2105 oldFreq
= device
->Frequency
;
2106 oldChans
= device
->FmtChans
;
2107 oldType
= device
->FmtType
;
2109 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2110 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2111 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2112 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2113 device
->UpdateSize
, device
->NumUpdates
2116 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2117 return ALC_INVALID_DEVICE
;
2119 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2121 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2122 DevFmtChannelsString(device
->FmtChans
));
2123 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2125 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2128 DevFmtTypeString(device
->FmtType
));
2129 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2131 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2133 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2134 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2137 if((device
->UpdateSize
&3) != 0)
2139 if((CPUCapFlags
&CPU_CAP_SSE
))
2140 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2141 if((CPUCapFlags
&CPU_CAP_NEON
))
2142 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2145 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2146 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2147 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2150 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2151 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2152 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2154 /* Allocate extra channels for any post-filter output. */
2155 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2156 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2158 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2159 device
->Dry
.Buffer
= al_calloc(16, size
);
2160 if(!device
->Dry
.Buffer
)
2162 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2163 return ALC_INVALID_DEVICE
;
2166 if(device
->RealOut
.NumChannels
!= 0)
2167 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2168 device
->FOAOut
.NumChannels
;
2171 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2172 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2175 if(device
->FOAOut
.NumChannels
!= 0)
2176 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2179 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2180 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2183 /* Need to delay returning failure until replacement Send arrays have been
2184 * allocated with the appropriate size.
2186 device
->NumAuxSends
= new_sends
;
2187 update_failed
= AL_FALSE
;
2188 SetMixerFPUMode(&oldMode
);
2189 if(device
->DefaultSlot
)
2191 ALeffectslot
*slot
= device
->DefaultSlot
;
2192 ALeffectState
*state
= slot
->Effect
.State
;
2194 state
->OutBuffer
= device
->Dry
.Buffer
;
2195 state
->OutChannels
= device
->Dry
.NumChannels
;
2196 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2197 update_failed
= AL_TRUE
;
2199 UpdateEffectSlotProps(slot
);
2202 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2207 WriteLock(&context
->PropLock
);
2208 LockUIntMapRead(&context
->EffectSlotMap
);
2209 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2211 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2212 ALeffectState
*state
= slot
->Effect
.State
;
2214 state
->OutBuffer
= device
->Dry
.Buffer
;
2215 state
->OutChannels
= device
->Dry
.NumChannels
;
2216 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2217 update_failed
= AL_TRUE
;
2219 UpdateEffectSlotProps(slot
);
2221 UnlockUIntMapRead(&context
->EffectSlotMap
);
2223 LockUIntMapRead(&context
->SourceMap
);
2224 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2226 ALsource
*source
= context
->SourceMap
.values
[pos
];
2227 struct ALsourceProps
*props
;
2229 if(old_sends
!= device
->NumAuxSends
)
2231 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2234 memcpy(sends
, source
->Send
,
2235 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2237 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2239 if(source
->Send
[s
].Slot
)
2240 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2241 source
->Send
[s
].Slot
= NULL
;
2243 al_free(source
->Send
);
2244 source
->Send
= sends
;
2245 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2247 source
->Send
[s
].Slot
= NULL
;
2248 source
->Send
[s
].Gain
= 1.0f
;
2249 source
->Send
[s
].GainHF
= 1.0f
;
2250 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2251 source
->Send
[s
].GainLF
= 1.0f
;
2252 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2256 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2258 /* Clear any pre-existing source property structs, in case the
2259 * number of auxiliary sends changed. Playing (or paused) sources
2260 * will have updates respecified in UpdateAllSourceProps.
2262 props
= ATOMIC_EXCHANGE_SEQ(struct ALsourceProps
*, &source
->Update
, NULL
);
2265 props
= ATOMIC_EXCHANGE(struct ALsourceProps
*, &source
->FreeList
, NULL
,
2266 almemory_order_relaxed
);
2269 struct ALsourceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2274 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2275 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2277 ALvoice
*voice
= context
->Voices
[pos
];
2278 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2281 if(device
->AvgSpeakerDist
> 0.0f
)
2283 /* Reinitialize the NFC filters for new parameters. */
2284 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2285 (device
->AvgSpeakerDist
* device
->Frequency
);
2286 for(i
= 0;i
< voice
->NumChannels
;i
++)
2288 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2289 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2290 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2294 UnlockUIntMapRead(&context
->SourceMap
);
2296 UpdateListenerProps(context
);
2297 UpdateAllSourceProps(context
);
2298 WriteUnlock(&context
->PropLock
);
2300 context
= context
->next
;
2302 RestoreFPUMode(&oldMode
);
2304 return ALC_INVALID_DEVICE
;
2306 if(!(device
->Flags
&DEVICE_PAUSED
))
2308 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2309 return ALC_INVALID_DEVICE
;
2310 device
->Flags
|= DEVICE_RUNNING
;
2313 return ALC_NO_ERROR
;
2318 * Frees the device structure, and destroys any objects the app failed to
2319 * delete. Called once there's no more references on the device.
2321 static ALCvoid
FreeDevice(ALCdevice
*device
)
2325 TRACE("%p\n", device
);
2327 V0(device
->Backend
,close
)();
2328 DELETE_OBJ(device
->Backend
);
2329 device
->Backend
= NULL
;
2331 almtx_destroy(&device
->BackendLock
);
2333 if(device
->DefaultSlot
)
2335 DeinitEffectSlot(device
->DefaultSlot
);
2336 device
->DefaultSlot
= NULL
;
2339 if(device
->BufferMap
.size
> 0)
2341 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2342 (device
->BufferMap
.size
==1)?"":"s");
2343 ReleaseALBuffers(device
);
2345 ResetUIntMap(&device
->BufferMap
);
2347 if(device
->EffectMap
.size
> 0)
2349 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2350 (device
->EffectMap
.size
==1)?"":"s");
2351 ReleaseALEffects(device
);
2353 ResetUIntMap(&device
->EffectMap
);
2355 if(device
->FilterMap
.size
> 0)
2357 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2358 (device
->FilterMap
.size
==1)?"":"s");
2359 ReleaseALFilters(device
);
2361 ResetUIntMap(&device
->FilterMap
);
2363 AL_STRING_DEINIT(device
->HrtfName
);
2364 FreeHrtfList(&device
->HrtfList
);
2365 al_free(device
->Hrtf
);
2366 device
->Hrtf
= NULL
;
2368 al_free(device
->Bs2b
);
2369 device
->Bs2b
= NULL
;
2371 al_free(device
->Uhj_Encoder
);
2372 device
->Uhj_Encoder
= NULL
;
2374 bformatdec_free(device
->AmbiDecoder
);
2375 device
->AmbiDecoder
= NULL
;
2377 ambiup_free(device
->AmbiUp
);
2378 device
->AmbiUp
= NULL
;
2380 al_free(device
->ChannelDelay
[0].Buffer
);
2381 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2383 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2384 device
->ChannelDelay
[i
].Length
= 0;
2385 device
->ChannelDelay
[i
].Buffer
= NULL
;
2388 AL_STRING_DEINIT(device
->DeviceName
);
2390 al_free(device
->Dry
.Buffer
);
2391 device
->Dry
.Buffer
= NULL
;
2392 device
->Dry
.NumChannels
= 0;
2393 device
->FOAOut
.Buffer
= NULL
;
2394 device
->FOAOut
.NumChannels
= 0;
2395 device
->RealOut
.Buffer
= NULL
;
2396 device
->RealOut
.NumChannels
= 0;
2402 void ALCdevice_IncRef(ALCdevice
*device
)
2405 ref
= IncrementRef(&device
->ref
);
2406 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2409 void ALCdevice_DecRef(ALCdevice
*device
)
2412 ref
= DecrementRef(&device
->ref
);
2413 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2414 if(ref
== 0) FreeDevice(device
);
2419 * Checks if the device handle is valid, and increments its ref count if so.
2421 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2423 ALCdevice
*tmpDevice
;
2426 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2429 if(tmpDevice
== *device
)
2431 ALCdevice_IncRef(tmpDevice
);
2435 tmpDevice
= tmpDevice
->next
;
2446 * Initializes context fields
2448 static ALvoid
InitContext(ALCcontext
*Context
)
2450 ALlistener
*listener
= Context
->Listener
;
2451 struct ALeffectslotArray
*auxslots
;
2453 //Initialise listener
2454 listener
->Gain
= 1.0f
;
2455 listener
->MetersPerUnit
= 1.0f
;
2456 listener
->Position
[0] = 0.0f
;
2457 listener
->Position
[1] = 0.0f
;
2458 listener
->Position
[2] = 0.0f
;
2459 listener
->Velocity
[0] = 0.0f
;
2460 listener
->Velocity
[1] = 0.0f
;
2461 listener
->Velocity
[2] = 0.0f
;
2462 listener
->Forward
[0] = 0.0f
;
2463 listener
->Forward
[1] = 0.0f
;
2464 listener
->Forward
[2] = -1.0f
;
2465 listener
->Up
[0] = 0.0f
;
2466 listener
->Up
[1] = 1.0f
;
2467 listener
->Up
[2] = 0.0f
;
2469 aluMatrixfSet(&listener
->Params
.Matrix
,
2470 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2471 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2472 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2473 0.0f
, 0.0f
, 0.0f
, 1.0f
2475 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2476 listener
->Params
.Gain
= 1.0f
;
2477 listener
->Params
.MetersPerUnit
= 1.0f
;
2478 listener
->Params
.DopplerFactor
= 1.0f
;
2479 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2481 ATOMIC_INIT(&listener
->Update
, NULL
);
2482 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2485 InitRef(&Context
->UpdateCount
, 0);
2486 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2487 Context
->GainBoost
= 1.0f
;
2488 RWLockInit(&Context
->PropLock
);
2489 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2490 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2491 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2493 auxslots
= al_calloc(DEF_ALIGN
, offsetof(struct ALeffectslotArray
, slot
[0]));
2494 auxslots
->count
= 0;
2495 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2498 Context
->DistanceModel
= DefaultDistanceModel
;
2499 Context
->SourceDistanceModel
= AL_FALSE
;
2500 Context
->DopplerFactor
= 1.0f
;
2501 Context
->DopplerVelocity
= 1.0f
;
2502 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2503 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2505 Context
->ExtensionList
= alExtList
;
2511 * Cleans up the context, and destroys any remaining objects the app failed to
2512 * delete. Called once there's no more references on the context.
2514 static void FreeContext(ALCcontext
*context
)
2516 ALlistener
*listener
= context
->Listener
;
2517 struct ALeffectslotArray
*auxslots
;
2518 struct ALlistenerProps
*lprops
;
2521 TRACE("%p\n", context
);
2523 auxslots
= ATOMIC_EXCHANGE(struct ALeffectslotArray
*, &context
->ActiveAuxSlots
,
2524 NULL
, almemory_order_relaxed
);
2527 if(context
->SourceMap
.size
> 0)
2529 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2530 (context
->SourceMap
.size
==1)?"":"s");
2531 ReleaseALSources(context
);
2533 ResetUIntMap(&context
->SourceMap
);
2535 if(context
->EffectSlotMap
.size
> 0)
2537 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2538 (context
->EffectSlotMap
.size
==1)?"":"s");
2539 ReleaseALAuxiliaryEffectSlots(context
);
2541 ResetUIntMap(&context
->EffectSlotMap
);
2543 al_free(context
->Voices
);
2544 context
->Voices
= NULL
;
2545 context
->VoiceCount
= 0;
2546 context
->MaxVoices
= 0;
2548 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2550 TRACE("Freed unapplied listener update %p\n", lprops
);
2554 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2557 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2562 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2564 ALCdevice_DecRef(context
->Device
);
2565 context
->Device
= NULL
;
2567 //Invalidate context
2568 memset(context
, 0, sizeof(ALCcontext
));
2574 * Removes the context reference from the given device and removes it from
2575 * being current on the running thread or globally. Returns true if other
2576 * contexts still exist on the device.
2578 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2580 ALCcontext
*origctx
, *newhead
;
2583 if(altss_get(LocalContext
) == context
)
2585 WARN("%p released while current on thread\n", context
);
2586 altss_set(LocalContext
, NULL
);
2587 ALCcontext_DecRef(context
);
2591 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &GlobalContext
, &origctx
, NULL
))
2592 ALCcontext_DecRef(context
);
2594 ALCdevice_Lock(device
);
2596 newhead
= context
->next
;
2597 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &device
->ContextList
, &origctx
, newhead
))
2599 ALCcontext
*volatile*list
= &origctx
->next
;
2602 if(*list
== context
)
2604 *list
= (*list
)->next
;
2607 list
= &(*list
)->next
;
2612 ALCdevice_Unlock(device
);
2614 ALCcontext_DecRef(context
);
2618 void ALCcontext_IncRef(ALCcontext
*context
)
2620 uint ref
= IncrementRef(&context
->ref
);
2621 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2624 void ALCcontext_DecRef(ALCcontext
*context
)
2626 uint ref
= DecrementRef(&context
->ref
);
2627 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2628 if(ref
== 0) FreeContext(context
);
2631 static void ReleaseThreadCtx(void *ptr
)
2633 ALCcontext
*context
= ptr
;
2634 uint ref
= DecrementRef(&context
->ref
);
2635 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2636 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2641 * Checks that the given context is valid, and increments its reference count.
2643 static ALCboolean
VerifyContext(ALCcontext
**context
)
2648 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2651 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2656 ALCcontext_IncRef(ctx
);
2673 * Returns the currently active context for this thread, and adds a reference
2674 * without locking it.
2676 ALCcontext
*GetContextRef(void)
2678 ALCcontext
*context
;
2680 context
= altss_get(LocalContext
);
2682 ALCcontext_IncRef(context
);
2686 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2688 ALCcontext_IncRef(context
);
2696 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2698 ALCdevice
*device
= context
->Device
;
2699 ALsizei num_sends
= device
->NumAuxSends
;
2700 struct ALsourceProps
*props
;
2701 size_t sizeof_props
;
2702 size_t sizeof_voice
;
2708 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2711 /* Allocate the voice pointers, voices, and the voices' stored source
2712 * property set (including the dynamically-sized Send[] array) in one
2715 sizeof_props
= RoundUp(offsetof(struct ALsourceProps
, Send
[num_sends
]), 16);
2716 sizeof_voice
= RoundUp(offsetof(ALvoice
, Send
[num_sends
]), 16);
2717 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2719 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2720 /* The voice and property objects are stored interleaved since they're
2723 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2724 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2728 ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2729 for(;v
< v_count
;v
++)
2731 ALsizei s_count
= mini(old_sends
, num_sends
);
2734 /* Copy the old voice data and source property set to the new
2737 *voice
= *(context
->Voices
[v
]);
2738 for(i
= 0;i
< s_count
;i
++)
2739 voice
->Send
[i
] = context
->Voices
[v
]->Send
[i
];
2740 *props
= *(context
->Voices
[v
]->Props
);
2741 for(i
= 0;i
< s_count
;i
++)
2742 props
->Send
[i
] = context
->Voices
[v
]->Props
->Send
[i
];
2744 /* Set this voice's property set pointer and voice reference. */
2745 voice
->Props
= props
;
2748 /* Increment pointers to the next storage space. */
2749 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2750 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2753 /* Finish setting the voices' property set pointers and references. */
2754 for(;v
< num_voices
;v
++)
2756 voice
->Props
= props
;
2759 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2760 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2763 al_free(context
->Voices
);
2764 context
->Voices
= voices
;
2765 context
->MaxVoices
= num_voices
;
2766 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2770 /************************************************
2771 * Standard ALC functions
2772 ************************************************/
2776 * Return last ALC generated error code for the given device
2778 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2782 if(VerifyDevice(&device
))
2784 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &device
->LastError
, ALC_NO_ERROR
);
2785 ALCdevice_DecRef(device
);
2788 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &LastNullDeviceError
, ALC_NO_ERROR
);
2794 /* alcSuspendContext
2796 * Suspends updates for the given context
2798 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2803 if(!VerifyContext(&context
))
2804 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2807 ALCcontext_DeferUpdates(context
);
2808 ALCcontext_DecRef(context
);
2812 /* alcProcessContext
2814 * Resumes processing updates for the given context
2816 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2821 if(!VerifyContext(&context
))
2822 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2825 ALCcontext_ProcessUpdates(context
);
2826 ALCcontext_DecRef(context
);
2833 * Returns information about the device, and error strings
2835 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2837 const ALCchar
*value
= NULL
;
2845 case ALC_INVALID_ENUM
:
2846 value
= alcErrInvalidEnum
;
2849 case ALC_INVALID_VALUE
:
2850 value
= alcErrInvalidValue
;
2853 case ALC_INVALID_DEVICE
:
2854 value
= alcErrInvalidDevice
;
2857 case ALC_INVALID_CONTEXT
:
2858 value
= alcErrInvalidContext
;
2861 case ALC_OUT_OF_MEMORY
:
2862 value
= alcErrOutOfMemory
;
2865 case ALC_DEVICE_SPECIFIER
:
2866 value
= alcDefaultName
;
2869 case ALC_ALL_DEVICES_SPECIFIER
:
2870 if(VerifyDevice(&Device
))
2872 value
= alstr_get_cstr(Device
->DeviceName
);
2873 ALCdevice_DecRef(Device
);
2877 ProbeAllDevicesList();
2878 value
= alstr_get_cstr(alcAllDevicesList
);
2882 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2883 if(VerifyDevice(&Device
))
2885 value
= alstr_get_cstr(Device
->DeviceName
);
2886 ALCdevice_DecRef(Device
);
2890 ProbeCaptureDeviceList();
2891 value
= alstr_get_cstr(alcCaptureDeviceList
);
2895 /* Default devices are always first in the list */
2896 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2897 value
= alcDefaultName
;
2900 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2901 if(alstr_empty(alcAllDevicesList
))
2902 ProbeAllDevicesList();
2904 VerifyDevice(&Device
);
2906 free(alcDefaultAllDevicesSpecifier
);
2907 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
2908 if(!alcDefaultAllDevicesSpecifier
)
2909 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2911 value
= alcDefaultAllDevicesSpecifier
;
2912 if(Device
) ALCdevice_DecRef(Device
);
2915 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2916 if(alstr_empty(alcCaptureDeviceList
))
2917 ProbeCaptureDeviceList();
2919 VerifyDevice(&Device
);
2921 free(alcCaptureDefaultDeviceSpecifier
);
2922 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
2923 if(!alcCaptureDefaultDeviceSpecifier
)
2924 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2926 value
= alcCaptureDefaultDeviceSpecifier
;
2927 if(Device
) ALCdevice_DecRef(Device
);
2930 case ALC_EXTENSIONS
:
2931 if(!VerifyDevice(&Device
))
2932 value
= alcNoDeviceExtList
;
2935 value
= alcExtensionList
;
2936 ALCdevice_DecRef(Device
);
2940 case ALC_HRTF_SPECIFIER_SOFT
:
2941 if(!VerifyDevice(&Device
))
2942 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2945 almtx_lock(&Device
->BackendLock
);
2946 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
2947 almtx_unlock(&Device
->BackendLock
);
2948 ALCdevice_DecRef(Device
);
2953 VerifyDevice(&Device
);
2954 alcSetError(Device
, ALC_INVALID_ENUM
);
2955 if(Device
) ALCdevice_DecRef(Device
);
2963 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2965 if(device
->Type
== Loopback
&& device
->FmtChans
>= DevFmtAmbi1
&&
2966 device
->FmtChans
<= DevFmtAmbi3
)
2971 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2975 if(size
<= 0 || values
== NULL
)
2977 alcSetError(device
, ALC_INVALID_VALUE
);
2985 case ALC_MAJOR_VERSION
:
2986 values
[0] = alcMajorVersion
;
2988 case ALC_MINOR_VERSION
:
2989 values
[0] = alcMinorVersion
;
2992 case ALC_ATTRIBUTES_SIZE
:
2993 case ALC_ALL_ATTRIBUTES
:
2997 case ALC_MONO_SOURCES
:
2998 case ALC_STEREO_SOURCES
:
2999 case ALC_CAPTURE_SAMPLES
:
3000 case ALC_FORMAT_CHANNELS_SOFT
:
3001 case ALC_FORMAT_TYPE_SOFT
:
3002 case ALC_AMBISONIC_LAYOUT_SOFT
:
3003 case ALC_AMBISONIC_SCALING_SOFT
:
3004 case ALC_AMBISONIC_ORDER_SOFT
:
3005 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3009 alcSetError(NULL
, ALC_INVALID_ENUM
);
3015 if(device
->Type
== Capture
)
3019 case ALC_CAPTURE_SAMPLES
:
3020 almtx_lock(&device
->BackendLock
);
3021 values
[0] = V0(device
->Backend
,availableSamples
)();
3022 almtx_unlock(&device
->BackendLock
);
3026 values
[0] = device
->Connected
;
3030 alcSetError(device
, ALC_INVALID_ENUM
);
3039 case ALC_MAJOR_VERSION
:
3040 values
[0] = alcMajorVersion
;
3043 case ALC_MINOR_VERSION
:
3044 values
[0] = alcMinorVersion
;
3047 case ALC_EFX_MAJOR_VERSION
:
3048 values
[0] = alcEFXMajorVersion
;
3051 case ALC_EFX_MINOR_VERSION
:
3052 values
[0] = alcEFXMinorVersion
;
3055 case ALC_ATTRIBUTES_SIZE
:
3056 values
[0] = NumAttrsForDevice(device
);
3059 case ALC_ALL_ATTRIBUTES
:
3060 if(size
< NumAttrsForDevice(device
))
3062 alcSetError(device
, ALC_INVALID_VALUE
);
3067 almtx_lock(&device
->BackendLock
);
3068 values
[i
++] = ALC_FREQUENCY
;
3069 values
[i
++] = device
->Frequency
;
3071 if(device
->Type
!= Loopback
)
3073 values
[i
++] = ALC_REFRESH
;
3074 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3076 values
[i
++] = ALC_SYNC
;
3077 values
[i
++] = ALC_FALSE
;
3081 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3083 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3084 values
[i
++] = device
->AmbiLayout
;
3086 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3087 values
[i
++] = device
->AmbiScale
;
3089 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3090 values
[i
++] = device
->FmtChans
-DevFmtAmbi1
+1;
3092 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3093 values
[i
++] = ALC_BFORMAT3D_SOFT
;
3097 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3098 values
[i
++] = device
->FmtChans
;
3101 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3102 values
[i
++] = device
->FmtType
;
3105 values
[i
++] = ALC_MONO_SOURCES
;
3106 values
[i
++] = device
->NumMonoSources
;
3108 values
[i
++] = ALC_STEREO_SOURCES
;
3109 values
[i
++] = device
->NumStereoSources
;
3111 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3112 values
[i
++] = device
->NumAuxSends
;
3114 values
[i
++] = ALC_HRTF_SOFT
;
3115 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3117 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3118 values
[i
++] = device
->HrtfStatus
;
3119 almtx_unlock(&device
->BackendLock
);
3125 values
[0] = device
->Frequency
;
3129 if(device
->Type
== Loopback
)
3131 alcSetError(device
, ALC_INVALID_DEVICE
);
3134 almtx_lock(&device
->BackendLock
);
3135 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3136 almtx_unlock(&device
->BackendLock
);
3140 if(device
->Type
== Loopback
)
3142 alcSetError(device
, ALC_INVALID_DEVICE
);
3145 values
[0] = ALC_FALSE
;
3148 case ALC_FORMAT_CHANNELS_SOFT
:
3149 if(device
->Type
!= Loopback
)
3151 alcSetError(device
, ALC_INVALID_DEVICE
);
3154 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3155 values
[0] = ALC_BFORMAT3D_SOFT
;
3157 values
[0] = device
->FmtChans
;
3160 case ALC_FORMAT_TYPE_SOFT
:
3161 if(device
->Type
!= Loopback
)
3163 alcSetError(device
, ALC_INVALID_DEVICE
);
3166 values
[0] = device
->FmtType
;
3169 case ALC_AMBISONIC_LAYOUT_SOFT
:
3170 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3171 device
->FmtChans
<= DevFmtAmbi3
))
3173 alcSetError(device
, ALC_INVALID_DEVICE
);
3176 values
[0] = device
->AmbiLayout
;
3179 case ALC_AMBISONIC_SCALING_SOFT
:
3180 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3181 device
->FmtChans
<= DevFmtAmbi3
))
3183 alcSetError(device
, ALC_INVALID_DEVICE
);
3186 values
[0] = device
->AmbiScale
;
3189 case ALC_AMBISONIC_ORDER_SOFT
:
3190 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3191 device
->FmtChans
<= DevFmtAmbi3
))
3193 alcSetError(device
, ALC_INVALID_DEVICE
);
3196 values
[0] = device
->FmtChans
- DevFmtAmbi1
+ 1;
3199 case ALC_MONO_SOURCES
:
3200 values
[0] = device
->NumMonoSources
;
3203 case ALC_STEREO_SOURCES
:
3204 values
[0] = device
->NumStereoSources
;
3207 case ALC_MAX_AUXILIARY_SENDS
:
3208 values
[0] = device
->NumAuxSends
;
3212 values
[0] = device
->Connected
;
3216 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3219 case ALC_HRTF_STATUS_SOFT
:
3220 values
[0] = device
->HrtfStatus
;
3223 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3224 almtx_lock(&device
->BackendLock
);
3225 FreeHrtfList(&device
->HrtfList
);
3226 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3227 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3228 almtx_unlock(&device
->BackendLock
);
3232 alcSetError(device
, ALC_INVALID_ENUM
);
3240 * Returns information about the device and the version of OpenAL
3242 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3244 VerifyDevice(&device
);
3245 if(size
<= 0 || values
== NULL
)
3246 alcSetError(device
, ALC_INVALID_VALUE
);
3248 GetIntegerv(device
, param
, size
, values
);
3249 if(device
) ALCdevice_DecRef(device
);
3252 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3257 VerifyDevice(&device
);
3258 if(size
<= 0 || values
== NULL
)
3259 alcSetError(device
, ALC_INVALID_VALUE
);
3260 else if(!device
|| device
->Type
== Capture
)
3262 ivals
= malloc(size
* sizeof(ALCint
));
3263 size
= GetIntegerv(device
, pname
, size
, ivals
);
3264 for(i
= 0;i
< size
;i
++)
3265 values
[i
] = ivals
[i
];
3268 else /* render device */
3277 case ALC_ATTRIBUTES_SIZE
:
3278 *values
= NumAttrsForDevice(device
)+2;
3281 case ALC_ALL_ATTRIBUTES
:
3282 if(size
< NumAttrsForDevice(device
)+2)
3283 alcSetError(device
, ALC_INVALID_VALUE
);
3287 almtx_lock(&device
->BackendLock
);
3288 values
[i
++] = ALC_FREQUENCY
;
3289 values
[i
++] = device
->Frequency
;
3291 if(device
->Type
!= Loopback
)
3293 values
[i
++] = ALC_REFRESH
;
3294 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3296 values
[i
++] = ALC_SYNC
;
3297 values
[i
++] = ALC_FALSE
;
3301 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3303 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3304 values
[i
++] = device
->AmbiLayout
;
3306 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3307 values
[i
++] = device
->AmbiScale
;
3309 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3310 values
[i
++] = device
->FmtChans
-DevFmtAmbi1
+1;
3312 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3313 values
[i
++] = ALC_BFORMAT3D_SOFT
;
3317 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3318 values
[i
++] = device
->FmtChans
;
3321 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3322 values
[i
++] = device
->FmtType
;
3325 values
[i
++] = ALC_MONO_SOURCES
;
3326 values
[i
++] = device
->NumMonoSources
;
3328 values
[i
++] = ALC_STEREO_SOURCES
;
3329 values
[i
++] = device
->NumStereoSources
;
3331 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3332 values
[i
++] = device
->NumAuxSends
;
3334 values
[i
++] = ALC_HRTF_SOFT
;
3335 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3337 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3338 values
[i
++] = device
->HrtfStatus
;
3340 clock
= V0(device
->Backend
,getClockLatency
)();
3341 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3342 values
[i
++] = clock
.ClockTime
;
3344 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3345 values
[i
++] = clock
.Latency
;
3346 almtx_unlock(&device
->BackendLock
);
3352 case ALC_DEVICE_CLOCK_SOFT
:
3353 almtx_lock(&device
->BackendLock
);
3355 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3357 basecount
= device
->ClockBase
;
3358 samplecount
= device
->SamplesDone
;
3359 } while(refcount
!= ReadRef(&device
->MixCount
));
3360 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3361 almtx_unlock(&device
->BackendLock
);
3364 case ALC_DEVICE_LATENCY_SOFT
:
3365 almtx_lock(&device
->BackendLock
);
3366 clock
= V0(device
->Backend
,getClockLatency
)();
3367 almtx_unlock(&device
->BackendLock
);
3368 *values
= clock
.Latency
;
3371 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3373 alcSetError(device
, ALC_INVALID_VALUE
);
3376 almtx_lock(&device
->BackendLock
);
3377 clock
= V0(device
->Backend
,getClockLatency
)();
3378 almtx_unlock(&device
->BackendLock
);
3379 values
[0] = clock
.ClockTime
;
3380 values
[1] = clock
.Latency
;
3385 ivals
= malloc(size
* sizeof(ALCint
));
3386 size
= GetIntegerv(device
, pname
, size
, ivals
);
3387 for(i
= 0;i
< size
;i
++)
3388 values
[i
] = ivals
[i
];
3394 ALCdevice_DecRef(device
);
3398 /* alcIsExtensionPresent
3400 * Determines if there is support for a particular extension
3402 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3404 ALCboolean bResult
= ALC_FALSE
;
3406 VerifyDevice(&device
);
3409 alcSetError(device
, ALC_INVALID_VALUE
);
3412 size_t len
= strlen(extName
);
3413 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3416 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3417 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3422 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3426 } while(isspace(*ptr
));
3431 ALCdevice_DecRef(device
);
3436 /* alcGetProcAddress
3438 * Retrieves the function address for a particular extension function
3440 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3442 ALCvoid
*ptr
= NULL
;
3446 VerifyDevice(&device
);
3447 alcSetError(device
, ALC_INVALID_VALUE
);
3448 if(device
) ALCdevice_DecRef(device
);
3453 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3455 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3457 ptr
= alcFunctions
[i
].address
;
3469 * Get the value for a particular ALC enumeration name
3471 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3477 VerifyDevice(&device
);
3478 alcSetError(device
, ALC_INVALID_VALUE
);
3479 if(device
) ALCdevice_DecRef(device
);
3484 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3486 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3488 val
= alcEnumerations
[i
].value
;
3500 * Create and attach a context to the given device.
3502 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3504 ALCcontext
*ALContext
;
3508 /* Explicitly hold the list lock while taking the BackendLock in case the
3509 * device is asynchronously destropyed, to ensure this new context is
3510 * properly cleaned up after being made.
3513 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3516 alcSetError(device
, ALC_INVALID_DEVICE
);
3517 if(device
) ALCdevice_DecRef(device
);
3520 almtx_lock(&device
->BackendLock
);
3523 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3525 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3528 InitRef(&ALContext
->ref
, 1);
3529 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3531 ALContext
->Device
= device
;
3532 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3534 ALContext
->Voices
= NULL
;
3535 ALContext
->MaxVoices
= 0;
3536 ALContext
->VoiceCount
= 0;
3537 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3539 if(!ALContext
|| !ALContext
->Voices
)
3541 almtx_unlock(&device
->BackendLock
);
3545 al_free(ALContext
->Voices
);
3546 ALContext
->Voices
= NULL
;
3552 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3553 ALCdevice_DecRef(device
);
3557 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3559 almtx_unlock(&device
->BackendLock
);
3561 al_free(ALContext
->Voices
);
3562 ALContext
->Voices
= NULL
;
3567 alcSetError(device
, err
);
3568 if(err
== ALC_INVALID_DEVICE
)
3570 V0(device
->Backend
,lock
)();
3571 aluHandleDisconnect(device
);
3572 V0(device
->Backend
,unlock
)();
3574 ALCdevice_DecRef(device
);
3578 ALCdevice_IncRef(ALContext
->Device
);
3579 InitContext(ALContext
);
3581 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3584 ERR("volume-adjust must be finite: %f\n", valf
);
3587 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3589 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3590 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3591 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3594 UpdateListenerProps(ALContext
);
3597 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3599 ALContext
->next
= head
;
3600 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext
*,
3601 &device
->ContextList
, &head
, ALContext
) == 0);
3603 almtx_unlock(&device
->BackendLock
);
3605 ALCdevice_DecRef(device
);
3607 TRACE("Created context %p\n", ALContext
);
3611 /* alcDestroyContext
3613 * Remove a context from its device
3615 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3620 if(!VerifyContext(&context
))
3623 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3627 Device
= context
->Device
;
3630 almtx_lock(&Device
->BackendLock
);
3631 if(!ReleaseContext(context
, Device
))
3633 V0(Device
->Backend
,stop
)();
3634 Device
->Flags
&= ~DEVICE_RUNNING
;
3636 almtx_unlock(&Device
->BackendLock
);
3640 ALCcontext_DecRef(context
);
3644 /* alcGetCurrentContext
3646 * Returns the currently active context on the calling thread
3648 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3650 ALCcontext
*Context
= altss_get(LocalContext
);
3651 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3655 /* alcGetThreadContext
3657 * Returns the currently active thread-local context
3659 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3661 return altss_get(LocalContext
);
3665 /* alcMakeContextCurrent
3667 * Makes the given context the active process-wide context, and removes the
3668 * thread-local context for the calling thread.
3670 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3672 /* context must be valid or NULL */
3673 if(context
&& !VerifyContext(&context
))
3675 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3678 /* context's reference count is already incremented */
3679 context
= ATOMIC_EXCHANGE_SEQ(ALCcontext
*, &GlobalContext
, context
);
3680 if(context
) ALCcontext_DecRef(context
);
3682 if((context
=altss_get(LocalContext
)) != NULL
)
3684 altss_set(LocalContext
, NULL
);
3685 ALCcontext_DecRef(context
);
3691 /* alcSetThreadContext
3693 * Makes the given context the active context for the current thread
3695 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3699 /* context must be valid or NULL */
3700 if(context
&& !VerifyContext(&context
))
3702 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3705 /* context's reference count is already incremented */
3706 old
= altss_get(LocalContext
);
3707 altss_set(LocalContext
, context
);
3708 if(old
) ALCcontext_DecRef(old
);
3714 /* alcGetContextsDevice
3716 * Returns the device that a particular context is attached to
3718 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3722 if(!VerifyContext(&Context
))
3724 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3727 Device
= Context
->Device
;
3728 ALCcontext_DecRef(Context
);
3736 * Opens the named device.
3738 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3747 if(!PlaybackBackend
.name
)
3749 alcSetError(NULL
, ALC_INVALID_VALUE
);
3753 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3755 /* Some old Windows apps hardcode these expecting OpenAL to use a
3756 * specific audio API, even when they're not enumerated. Creative's
3757 * router effectively ignores them too.
3759 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3760 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3765 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3768 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3773 InitRef(&device
->ref
, 1);
3774 device
->Connected
= ALC_TRUE
;
3775 device
->Type
= Playback
;
3776 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3779 device
->Bs2b
= NULL
;
3780 device
->Uhj_Encoder
= NULL
;
3781 device
->Hrtf
= NULL
;
3782 VECTOR_INIT(device
->HrtfList
);
3783 AL_STRING_INIT(device
->HrtfName
);
3784 device
->Render_Mode
= NormalRender
;
3785 AL_STRING_INIT(device
->DeviceName
);
3786 device
->Dry
.Buffer
= NULL
;
3787 device
->Dry
.NumChannels
= 0;
3788 device
->FOAOut
.Buffer
= NULL
;
3789 device
->FOAOut
.NumChannels
= 0;
3790 device
->RealOut
.Buffer
= NULL
;
3791 device
->RealOut
.NumChannels
= 0;
3792 device
->AvgSpeakerDist
= 0.0f
;
3794 ATOMIC_INIT(&device
->ContextList
, NULL
);
3796 device
->ClockBase
= 0;
3797 device
->SamplesDone
= 0;
3799 device
->SourcesMax
= 256;
3800 device
->AuxiliaryEffectSlotMax
= 64;
3801 device
->NumAuxSends
= DEFAULT_SENDS
;
3803 InitUIntMap(&device
->BufferMap
, ~0);
3804 InitUIntMap(&device
->EffectMap
, ~0);
3805 InitUIntMap(&device
->FilterMap
, ~0);
3807 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3809 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3810 device
->ChannelDelay
[i
].Length
= 0;
3811 device
->ChannelDelay
[i
].Buffer
= NULL
;
3815 device
->FmtChans
= DevFmtChannelsDefault
;
3816 device
->FmtType
= DevFmtTypeDefault
;
3817 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3818 device
->IsHeadphones
= AL_FALSE
;
3819 device
->AmbiLayout
= AmbiLayout_Default
;
3820 device
->AmbiScale
= AmbiNorm_Default
;
3821 device
->NumUpdates
= 3;
3822 device
->UpdateSize
= 1024;
3824 if(!PlaybackBackend
.getFactory
)
3825 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3826 ALCbackend_Playback
);
3829 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3830 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3832 if(!device
->Backend
)
3835 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3840 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3842 static const struct {
3843 const char name
[16];
3844 enum DevFmtChannels chans
;
3846 { "mono", DevFmtMono
},
3847 { "stereo", DevFmtStereo
},
3848 { "quad", DevFmtQuad
},
3849 { "surround51", DevFmtX51
},
3850 { "surround61", DevFmtX61
},
3851 { "surround71", DevFmtX71
},
3852 { "surround51rear", DevFmtX51Rear
},
3853 { "ambi1", DevFmtAmbi1
},
3854 { "ambi2", DevFmtAmbi2
},
3855 { "ambi3", DevFmtAmbi3
},
3859 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3861 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3863 device
->FmtChans
= chanlist
[i
].chans
;
3864 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3868 if(i
== COUNTOF(chanlist
))
3869 ERR("Unsupported channels: %s\n", fmt
);
3871 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3873 static const struct {
3874 const char name
[16];
3875 enum DevFmtType type
;
3877 { "int8", DevFmtByte
},
3878 { "uint8", DevFmtUByte
},
3879 { "int16", DevFmtShort
},
3880 { "uint16", DevFmtUShort
},
3881 { "int32", DevFmtInt
},
3882 { "uint32", DevFmtUInt
},
3883 { "float32", DevFmtFloat
},
3887 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3889 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3891 device
->FmtType
= typelist
[i
].type
;
3892 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3896 if(i
== COUNTOF(typelist
))
3897 ERR("Unsupported sample-type: %s\n", fmt
);
3900 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3902 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3903 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3904 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3905 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3908 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3909 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3911 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3912 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3913 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3914 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3916 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3917 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3919 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3920 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3922 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3923 device
->NumAuxSends
= clampi(
3924 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3927 device
->NumStereoSources
= 1;
3928 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3930 // Find a playback device to open
3931 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3933 DELETE_OBJ(device
->Backend
);
3935 alcSetError(NULL
, err
);
3938 almtx_init(&device
->BackendLock
, almtx_plain
);
3940 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3942 if(strcasecmp(fmt
, "fuma") == 0)
3944 device
->AmbiLayout
= AmbiLayout_FuMa
;
3945 device
->AmbiScale
= AmbiNorm_FuMa
;
3947 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3949 device
->AmbiLayout
= AmbiLayout_ACN
;
3950 device
->AmbiScale
= AmbiNorm_SN3D
;
3952 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3954 device
->AmbiLayout
= AmbiLayout_ACN
;
3955 device
->AmbiScale
= AmbiNorm_N3D
;
3958 ERR("Unsupported ambi-format: %s\n", fmt
);
3961 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3963 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3964 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3966 device
->DefaultSlot
= NULL
;
3967 ERR("Failed to initialize the default effect slot\n");
3971 aluInitEffectPanning(device
->DefaultSlot
);
3972 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3974 DeinitEffectSlot(device
->DefaultSlot
);
3975 device
->DefaultSlot
= NULL
;
3976 ERR("Failed to initialize the default effect\n");
3982 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
3984 device
->next
= head
;
3985 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
3988 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
3994 * Closes the given device.
3996 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3998 ALCdevice
*iter
, *origdev
;
4002 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4006 } while((iter
=iter
->next
) != NULL
);
4007 if(!iter
|| iter
->Type
== Capture
)
4009 alcSetError(iter
, ALC_INVALID_DEVICE
);
4013 almtx_lock(&device
->BackendLock
);
4016 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
4018 ALCdevice
*volatile*list
= &origdev
->next
;
4023 *list
= (*list
)->next
;
4026 list
= &(*list
)->next
;
4031 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4034 ALCcontext
*next
= ctx
->next
;
4035 WARN("Releasing context %p\n", ctx
);
4036 ReleaseContext(ctx
, device
);
4039 if((device
->Flags
&DEVICE_RUNNING
))
4040 V0(device
->Backend
,stop
)();
4041 device
->Flags
&= ~DEVICE_RUNNING
;
4042 almtx_unlock(&device
->BackendLock
);
4044 ALCdevice_DecRef(device
);
4050 /************************************************
4051 * ALC capture functions
4052 ************************************************/
4053 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4055 ALCdevice
*device
= NULL
;
4061 if(!CaptureBackend
.name
)
4063 alcSetError(NULL
, ALC_INVALID_VALUE
);
4069 alcSetError(NULL
, ALC_INVALID_VALUE
);
4073 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4076 device
= al_calloc(16, sizeof(ALCdevice
));
4079 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4084 InitRef(&device
->ref
, 1);
4085 device
->Connected
= ALC_TRUE
;
4086 device
->Type
= Capture
;
4088 device
->Hrtf
= NULL
;
4089 VECTOR_INIT(device
->HrtfList
);
4090 AL_STRING_INIT(device
->HrtfName
);
4092 AL_STRING_INIT(device
->DeviceName
);
4093 device
->Dry
.Buffer
= NULL
;
4094 device
->Dry
.NumChannels
= 0;
4095 device
->FOAOut
.Buffer
= NULL
;
4096 device
->FOAOut
.NumChannels
= 0;
4097 device
->RealOut
.Buffer
= NULL
;
4098 device
->RealOut
.NumChannels
= 0;
4100 InitUIntMap(&device
->BufferMap
, ~0);
4101 InitUIntMap(&device
->EffectMap
, ~0);
4102 InitUIntMap(&device
->FilterMap
, ~0);
4104 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4106 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4107 device
->ChannelDelay
[i
].Length
= 0;
4108 device
->ChannelDelay
[i
].Buffer
= NULL
;
4111 if(!CaptureBackend
.getFactory
)
4112 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4113 ALCbackend_Capture
);
4116 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4117 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4119 if(!device
->Backend
)
4122 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4126 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4127 device
->Frequency
= frequency
;
4129 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4130 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4133 alcSetError(NULL
, ALC_INVALID_ENUM
);
4136 device
->IsHeadphones
= AL_FALSE
;
4137 device
->AmbiLayout
= AmbiLayout_Default
;
4138 device
->AmbiScale
= AmbiNorm_Default
;
4140 device
->UpdateSize
= samples
;
4141 device
->NumUpdates
= 1;
4143 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4146 alcSetError(NULL
, err
);
4149 almtx_init(&device
->BackendLock
, almtx_plain
);
4152 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4154 device
->next
= head
;
4155 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4158 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4162 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4164 ALCdevice
*iter
, *origdev
;
4167 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4171 } while((iter
=iter
->next
) != NULL
);
4172 if(!iter
|| iter
->Type
!= Capture
)
4174 alcSetError(iter
, ALC_INVALID_DEVICE
);
4180 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
4182 ALCdevice
*volatile*list
= &origdev
->next
;
4187 *list
= (*list
)->next
;
4190 list
= &(*list
)->next
;
4195 ALCdevice_DecRef(device
);
4200 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4202 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4203 alcSetError(device
, ALC_INVALID_DEVICE
);
4206 almtx_lock(&device
->BackendLock
);
4207 if(!device
->Connected
)
4208 alcSetError(device
, ALC_INVALID_DEVICE
);
4209 else if(!(device
->Flags
&DEVICE_RUNNING
))
4211 if(V0(device
->Backend
,start
)())
4212 device
->Flags
|= DEVICE_RUNNING
;
4215 aluHandleDisconnect(device
);
4216 alcSetError(device
, ALC_INVALID_DEVICE
);
4219 almtx_unlock(&device
->BackendLock
);
4222 if(device
) ALCdevice_DecRef(device
);
4225 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4227 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4228 alcSetError(device
, ALC_INVALID_DEVICE
);
4231 almtx_lock(&device
->BackendLock
);
4232 if((device
->Flags
&DEVICE_RUNNING
))
4233 V0(device
->Backend
,stop
)();
4234 device
->Flags
&= ~DEVICE_RUNNING
;
4235 almtx_unlock(&device
->BackendLock
);
4238 if(device
) ALCdevice_DecRef(device
);
4241 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4243 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4244 alcSetError(device
, ALC_INVALID_DEVICE
);
4247 ALCenum err
= ALC_INVALID_VALUE
;
4249 almtx_lock(&device
->BackendLock
);
4250 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4251 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4252 almtx_unlock(&device
->BackendLock
);
4254 if(err
!= ALC_NO_ERROR
)
4255 alcSetError(device
, err
);
4257 if(device
) ALCdevice_DecRef(device
);
4261 /************************************************
4262 * ALC loopback functions
4263 ************************************************/
4265 /* alcLoopbackOpenDeviceSOFT
4267 * Open a loopback device, for manual rendering.
4269 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4271 ALCbackendFactory
*factory
;
4277 /* Make sure the device name, if specified, is us. */
4278 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4280 alcSetError(NULL
, ALC_INVALID_VALUE
);
4284 device
= al_calloc(16, sizeof(ALCdevice
));
4287 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4292 InitRef(&device
->ref
, 1);
4293 device
->Connected
= ALC_TRUE
;
4294 device
->Type
= Loopback
;
4295 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4298 device
->Hrtf
= NULL
;
4299 VECTOR_INIT(device
->HrtfList
);
4300 AL_STRING_INIT(device
->HrtfName
);
4301 device
->Bs2b
= NULL
;
4302 device
->Uhj_Encoder
= NULL
;
4303 device
->Render_Mode
= NormalRender
;
4304 AL_STRING_INIT(device
->DeviceName
);
4305 device
->Dry
.Buffer
= NULL
;
4306 device
->Dry
.NumChannels
= 0;
4307 device
->FOAOut
.Buffer
= NULL
;
4308 device
->FOAOut
.NumChannels
= 0;
4309 device
->RealOut
.Buffer
= NULL
;
4310 device
->RealOut
.NumChannels
= 0;
4311 device
->AvgSpeakerDist
= 0.0f
;
4313 ATOMIC_INIT(&device
->ContextList
, NULL
);
4315 device
->ClockBase
= 0;
4316 device
->SamplesDone
= 0;
4318 device
->SourcesMax
= 256;
4319 device
->AuxiliaryEffectSlotMax
= 64;
4320 device
->NumAuxSends
= DEFAULT_SENDS
;
4322 InitUIntMap(&device
->BufferMap
, ~0);
4323 InitUIntMap(&device
->EffectMap
, ~0);
4324 InitUIntMap(&device
->FilterMap
, ~0);
4326 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4328 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4329 device
->ChannelDelay
[i
].Length
= 0;
4330 device
->ChannelDelay
[i
].Buffer
= NULL
;
4333 factory
= ALCloopbackFactory_getFactory();
4334 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4335 if(!device
->Backend
)
4338 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4341 almtx_init(&device
->BackendLock
, almtx_plain
);
4344 device
->NumUpdates
= 0;
4345 device
->UpdateSize
= 0;
4347 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4348 device
->FmtChans
= DevFmtChannelsDefault
;
4349 device
->FmtType
= DevFmtTypeDefault
;
4350 device
->IsHeadphones
= AL_FALSE
;
4351 device
->AmbiLayout
= AmbiLayout_Default
;
4352 device
->AmbiScale
= AmbiNorm_Default
;
4354 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4355 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4357 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4358 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4360 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4361 device
->NumAuxSends
= clampi(
4362 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4365 device
->NumStereoSources
= 1;
4366 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4368 // Open the "backend"
4369 V(device
->Backend
,open
)("Loopback");
4372 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4374 device
->next
= head
;
4375 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4378 TRACE("Created device %p\n", device
);
4382 /* alcIsRenderFormatSupportedSOFT
4384 * Determines if the loopback device supports the given format for rendering.
4386 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4388 ALCboolean ret
= ALC_FALSE
;
4390 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4391 alcSetError(device
, ALC_INVALID_DEVICE
);
4393 alcSetError(device
, ALC_INVALID_VALUE
);
4396 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4399 if(device
) ALCdevice_DecRef(device
);
4404 /* alcRenderSamplesSOFT
4406 * Renders some samples into a buffer, using the format last set by the
4407 * attributes given to alcCreateContext.
4409 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4411 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4412 alcSetError(device
, ALC_INVALID_DEVICE
);
4413 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4414 alcSetError(device
, ALC_INVALID_VALUE
);
4417 V0(device
->Backend
,lock
)();
4418 aluMixData(device
, buffer
, samples
);
4419 V0(device
->Backend
,unlock
)();
4421 if(device
) ALCdevice_DecRef(device
);
4425 /************************************************
4426 * ALC loopback2 functions
4427 ************************************************/
4429 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4431 ALCboolean ret
= ALC_FALSE
;
4433 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4434 alcSetError(device
, ALC_INVALID_DEVICE
);
4436 alcSetError(device
, ALC_INVALID_VALUE
);
4439 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4442 if(device
) ALCdevice_DecRef(device
);
4447 /************************************************
4448 * ALC DSP pause/resume functions
4449 ************************************************/
4451 /* alcDevicePauseSOFT
4453 * Pause the DSP to stop audio processing.
4455 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4457 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4458 alcSetError(device
, ALC_INVALID_DEVICE
);
4461 almtx_lock(&device
->BackendLock
);
4462 if((device
->Flags
&DEVICE_RUNNING
))
4463 V0(device
->Backend
,stop
)();
4464 device
->Flags
&= ~DEVICE_RUNNING
;
4465 device
->Flags
|= DEVICE_PAUSED
;
4466 almtx_unlock(&device
->BackendLock
);
4468 if(device
) ALCdevice_DecRef(device
);
4471 /* alcDeviceResumeSOFT
4473 * Resume the DSP to restart audio processing.
4475 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4477 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4478 alcSetError(device
, ALC_INVALID_DEVICE
);
4481 almtx_lock(&device
->BackendLock
);
4482 if((device
->Flags
&DEVICE_PAUSED
))
4484 device
->Flags
&= ~DEVICE_PAUSED
;
4485 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4487 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4488 device
->Flags
|= DEVICE_RUNNING
;
4491 alcSetError(device
, ALC_INVALID_DEVICE
);
4492 V0(device
->Backend
,lock
)();
4493 aluHandleDisconnect(device
);
4494 V0(device
->Backend
,unlock
)();
4498 almtx_unlock(&device
->BackendLock
);
4500 if(device
) ALCdevice_DecRef(device
);
4504 /************************************************
4505 * ALC HRTF functions
4506 ************************************************/
4508 /* alcGetStringiSOFT
4510 * Gets a string parameter at the given index.
4512 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4514 const ALCchar
*str
= NULL
;
4516 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4517 alcSetError(device
, ALC_INVALID_DEVICE
);
4518 else switch(paramName
)
4520 case ALC_HRTF_SPECIFIER_SOFT
:
4521 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4522 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4524 alcSetError(device
, ALC_INVALID_VALUE
);
4528 alcSetError(device
, ALC_INVALID_ENUM
);
4531 if(device
) ALCdevice_DecRef(device
);
4536 /* alcResetDeviceSOFT
4538 * Resets the given device output, using the specified attribute list.
4540 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4545 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4548 alcSetError(device
, ALC_INVALID_DEVICE
);
4549 if(device
) ALCdevice_DecRef(device
);
4552 almtx_lock(&device
->BackendLock
);
4555 err
= UpdateDeviceParams(device
, attribs
);
4556 almtx_unlock(&device
->BackendLock
);
4558 if(err
!= ALC_NO_ERROR
)
4560 alcSetError(device
, err
);
4561 if(err
== ALC_INVALID_DEVICE
)
4563 V0(device
->Backend
,lock
)();
4564 aluHandleDisconnect(device
);
4565 V0(device
->Backend
,unlock
)();
4567 ALCdevice_DecRef(device
);
4570 ALCdevice_DecRef(device
);