2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
40 #include "bformatdec.h"
48 #include "backends/base.h"
51 /************************************************
53 ************************************************/
56 ALCbackendFactory
* (*getFactory
)(void);
57 ALCboolean (*Init
)(BackendFuncs
*);
59 void (*Probe
)(enum DevProbe
);
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList
[] = {
66 { "jack", ALCjackBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
72 { "alsa", ALCalsaBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
75 { "core", ALCcoreAudioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
78 { "oss", ALCossBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
81 { "solaris", ALCsolarisBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
84 { "sndio", ALCsndioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
87 { "qsa", NULL
, alc_qsa_init
, alc_qsa_deinit
, alc_qsa_probe
, EmptyFuncs
},
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
93 { "dsound", ALCdsoundBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
96 { "winmm", ALCwinmmBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
99 { "port", ALCportBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
102 { "opensl", ALCopenslBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
105 { "null", ALCnullBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
107 { "wave", ALCwaveBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
110 static ALsizei BackendListSize
= COUNTOF(BackendList
);
113 static struct BackendInfo PlaybackBackend
;
114 static struct BackendInfo CaptureBackend
;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar
*funcName
;
125 DECL(alcCreateContext
),
126 DECL(alcMakeContextCurrent
),
127 DECL(alcProcessContext
),
128 DECL(alcSuspendContext
),
129 DECL(alcDestroyContext
),
130 DECL(alcGetCurrentContext
),
131 DECL(alcGetContextsDevice
),
133 DECL(alcCloseDevice
),
135 DECL(alcIsExtensionPresent
),
136 DECL(alcGetProcAddress
),
137 DECL(alcGetEnumValue
),
139 DECL(alcGetIntegerv
),
140 DECL(alcCaptureOpenDevice
),
141 DECL(alcCaptureCloseDevice
),
142 DECL(alcCaptureStart
),
143 DECL(alcCaptureStop
),
144 DECL(alcCaptureSamples
),
146 DECL(alcSetThreadContext
),
147 DECL(alcGetThreadContext
),
149 DECL(alcLoopbackOpenDeviceSOFT
),
150 DECL(alcIsRenderFormatSupportedSOFT
),
151 DECL(alcRenderSamplesSOFT
),
153 DECL(alcIsAmbisonicFormatSupportedSOFT
),
155 DECL(alcDevicePauseSOFT
),
156 DECL(alcDeviceResumeSOFT
),
158 DECL(alcGetStringiSOFT
),
159 DECL(alcResetDeviceSOFT
),
161 DECL(alcGetInteger64vSOFT
),
176 DECL(alIsExtensionPresent
),
177 DECL(alGetProcAddress
),
178 DECL(alGetEnumValue
),
185 DECL(alGetListenerf
),
186 DECL(alGetListener3f
),
187 DECL(alGetListenerfv
),
188 DECL(alGetListeneri
),
189 DECL(alGetListener3i
),
190 DECL(alGetListeneriv
),
192 DECL(alDeleteSources
),
208 DECL(alSourceRewindv
),
209 DECL(alSourcePausev
),
212 DECL(alSourceRewind
),
214 DECL(alSourceQueueBuffers
),
215 DECL(alSourceUnqueueBuffers
),
217 DECL(alDeleteBuffers
),
232 DECL(alDopplerFactor
),
233 DECL(alDopplerVelocity
),
234 DECL(alSpeedOfSound
),
235 DECL(alDistanceModel
),
238 DECL(alDeleteFilters
),
249 DECL(alDeleteEffects
),
259 DECL(alGenAuxiliaryEffectSlots
),
260 DECL(alDeleteAuxiliaryEffectSlots
),
261 DECL(alIsAuxiliaryEffectSlot
),
262 DECL(alAuxiliaryEffectSloti
),
263 DECL(alAuxiliaryEffectSlotiv
),
264 DECL(alAuxiliaryEffectSlotf
),
265 DECL(alAuxiliaryEffectSlotfv
),
266 DECL(alGetAuxiliaryEffectSloti
),
267 DECL(alGetAuxiliaryEffectSlotiv
),
268 DECL(alGetAuxiliaryEffectSlotf
),
269 DECL(alGetAuxiliaryEffectSlotfv
),
271 DECL(alDeferUpdatesSOFT
),
272 DECL(alProcessUpdatesSOFT
),
275 DECL(alSource3dSOFT
),
276 DECL(alSourcedvSOFT
),
277 DECL(alGetSourcedSOFT
),
278 DECL(alGetSource3dSOFT
),
279 DECL(alGetSourcedvSOFT
),
280 DECL(alSourcei64SOFT
),
281 DECL(alSource3i64SOFT
),
282 DECL(alSourcei64vSOFT
),
283 DECL(alGetSourcei64SOFT
),
284 DECL(alGetSource3i64SOFT
),
285 DECL(alGetSourcei64vSOFT
),
287 DECL(alBufferSamplesSOFT
),
288 DECL(alGetBufferSamplesSOFT
),
289 DECL(alIsBufferFormatSupportedSOFT
),
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar
*enumName
;
297 } alcEnumerations
[] = {
302 DECL(ALC_MAJOR_VERSION
),
303 DECL(ALC_MINOR_VERSION
),
304 DECL(ALC_ATTRIBUTES_SIZE
),
305 DECL(ALC_ALL_ATTRIBUTES
),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
307 DECL(ALC_DEVICE_SPECIFIER
),
308 DECL(ALC_ALL_DEVICES_SPECIFIER
),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
310 DECL(ALC_EXTENSIONS
),
314 DECL(ALC_MONO_SOURCES
),
315 DECL(ALC_STEREO_SOURCES
),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
318 DECL(ALC_CAPTURE_SAMPLES
),
321 DECL(ALC_EFX_MAJOR_VERSION
),
322 DECL(ALC_EFX_MINOR_VERSION
),
323 DECL(ALC_MAX_AUXILIARY_SENDS
),
325 DECL(ALC_FORMAT_CHANNELS_SOFT
),
326 DECL(ALC_FORMAT_TYPE_SOFT
),
329 DECL(ALC_STEREO_SOFT
),
331 DECL(ALC_5POINT1_SOFT
),
332 DECL(ALC_6POINT1_SOFT
),
333 DECL(ALC_7POINT1_SOFT
),
334 DECL(ALC_BFORMAT3D_SOFT
),
337 DECL(ALC_UNSIGNED_BYTE_SOFT
),
338 DECL(ALC_SHORT_SOFT
),
339 DECL(ALC_UNSIGNED_SHORT_SOFT
),
341 DECL(ALC_UNSIGNED_INT_SOFT
),
342 DECL(ALC_FLOAT_SOFT
),
345 DECL(ALC_DONT_CARE_SOFT
),
346 DECL(ALC_HRTF_STATUS_SOFT
),
347 DECL(ALC_HRTF_DISABLED_SOFT
),
348 DECL(ALC_HRTF_ENABLED_SOFT
),
349 DECL(ALC_HRTF_DENIED_SOFT
),
350 DECL(ALC_HRTF_REQUIRED_SOFT
),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
354 DECL(ALC_HRTF_SPECIFIER_SOFT
),
355 DECL(ALC_HRTF_ID_SOFT
),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
358 DECL(ALC_AMBISONIC_SCALING_SOFT
),
359 DECL(ALC_AMBISONIC_ORDER_SOFT
),
366 DECL(ALC_INVALID_DEVICE
),
367 DECL(ALC_INVALID_CONTEXT
),
368 DECL(ALC_INVALID_ENUM
),
369 DECL(ALC_INVALID_VALUE
),
370 DECL(ALC_OUT_OF_MEMORY
),
378 DECL(AL_SOURCE_RELATIVE
),
379 DECL(AL_CONE_INNER_ANGLE
),
380 DECL(AL_CONE_OUTER_ANGLE
),
390 DECL(AL_ORIENTATION
),
391 DECL(AL_REFERENCE_DISTANCE
),
392 DECL(AL_ROLLOFF_FACTOR
),
393 DECL(AL_CONE_OUTER_GAIN
),
394 DECL(AL_MAX_DISTANCE
),
396 DECL(AL_SAMPLE_OFFSET
),
397 DECL(AL_BYTE_OFFSET
),
398 DECL(AL_SOURCE_TYPE
),
401 DECL(AL_UNDETERMINED
),
402 DECL(AL_METERS_PER_UNIT
),
403 DECL(AL_LOOP_POINTS_SOFT
),
404 DECL(AL_DIRECT_CHANNELS_SOFT
),
406 DECL(AL_DIRECT_FILTER
),
407 DECL(AL_AUXILIARY_SEND_FILTER
),
408 DECL(AL_AIR_ABSORPTION_FACTOR
),
409 DECL(AL_ROOM_ROLLOFF_FACTOR
),
410 DECL(AL_CONE_OUTER_GAINHF
),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
415 DECL(AL_SOURCE_STATE
),
421 DECL(AL_BUFFERS_QUEUED
),
422 DECL(AL_BUFFERS_PROCESSED
),
424 DECL(AL_FORMAT_MONO8
),
425 DECL(AL_FORMAT_MONO16
),
426 DECL(AL_FORMAT_MONO_FLOAT32
),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
428 DECL(AL_FORMAT_STEREO8
),
429 DECL(AL_FORMAT_STEREO16
),
430 DECL(AL_FORMAT_STEREO_FLOAT32
),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
432 DECL(AL_FORMAT_MONO_IMA4
),
433 DECL(AL_FORMAT_STEREO_IMA4
),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
436 DECL(AL_FORMAT_QUAD8_LOKI
),
437 DECL(AL_FORMAT_QUAD16_LOKI
),
438 DECL(AL_FORMAT_QUAD8
),
439 DECL(AL_FORMAT_QUAD16
),
440 DECL(AL_FORMAT_QUAD32
),
441 DECL(AL_FORMAT_51CHN8
),
442 DECL(AL_FORMAT_51CHN16
),
443 DECL(AL_FORMAT_51CHN32
),
444 DECL(AL_FORMAT_61CHN8
),
445 DECL(AL_FORMAT_61CHN16
),
446 DECL(AL_FORMAT_61CHN32
),
447 DECL(AL_FORMAT_71CHN8
),
448 DECL(AL_FORMAT_71CHN16
),
449 DECL(AL_FORMAT_71CHN32
),
450 DECL(AL_FORMAT_REAR8
),
451 DECL(AL_FORMAT_REAR16
),
452 DECL(AL_FORMAT_REAR32
),
453 DECL(AL_FORMAT_MONO_MULAW
),
454 DECL(AL_FORMAT_MONO_MULAW_EXT
),
455 DECL(AL_FORMAT_STEREO_MULAW
),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
457 DECL(AL_FORMAT_QUAD_MULAW
),
458 DECL(AL_FORMAT_51CHN_MULAW
),
459 DECL(AL_FORMAT_61CHN_MULAW
),
460 DECL(AL_FORMAT_71CHN_MULAW
),
461 DECL(AL_FORMAT_REAR_MULAW
),
462 DECL(AL_FORMAT_MONO_ALAW_EXT
),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
465 DECL(AL_FORMAT_BFORMAT2D_8
),
466 DECL(AL_FORMAT_BFORMAT2D_16
),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
469 DECL(AL_FORMAT_BFORMAT3D_8
),
470 DECL(AL_FORMAT_BFORMAT3D_16
),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
475 DECL(AL_MONO16_SOFT
),
476 DECL(AL_MONO32F_SOFT
),
477 DECL(AL_STEREO8_SOFT
),
478 DECL(AL_STEREO16_SOFT
),
479 DECL(AL_STEREO32F_SOFT
),
481 DECL(AL_QUAD16_SOFT
),
482 DECL(AL_QUAD32F_SOFT
),
484 DECL(AL_REAR16_SOFT
),
485 DECL(AL_REAR32F_SOFT
),
486 DECL(AL_5POINT1_8_SOFT
),
487 DECL(AL_5POINT1_16_SOFT
),
488 DECL(AL_5POINT1_32F_SOFT
),
489 DECL(AL_6POINT1_8_SOFT
),
490 DECL(AL_6POINT1_16_SOFT
),
491 DECL(AL_6POINT1_32F_SOFT
),
492 DECL(AL_7POINT1_8_SOFT
),
493 DECL(AL_7POINT1_16_SOFT
),
494 DECL(AL_7POINT1_32F_SOFT
),
495 DECL(AL_BFORMAT2D_8_SOFT
),
496 DECL(AL_BFORMAT2D_16_SOFT
),
497 DECL(AL_BFORMAT2D_32F_SOFT
),
498 DECL(AL_BFORMAT3D_8_SOFT
),
499 DECL(AL_BFORMAT3D_16_SOFT
),
500 DECL(AL_BFORMAT3D_32F_SOFT
),
503 DECL(AL_STEREO_SOFT
),
506 DECL(AL_5POINT1_SOFT
),
507 DECL(AL_6POINT1_SOFT
),
508 DECL(AL_7POINT1_SOFT
),
509 DECL(AL_BFORMAT2D_SOFT
),
510 DECL(AL_BFORMAT3D_SOFT
),
513 DECL(AL_UNSIGNED_BYTE_SOFT
),
515 DECL(AL_UNSIGNED_SHORT_SOFT
),
517 DECL(AL_UNSIGNED_INT_SOFT
),
519 DECL(AL_DOUBLE_SOFT
),
521 DECL(AL_UNSIGNED_BYTE3_SOFT
),
528 DECL(AL_INTERNAL_FORMAT_SOFT
),
529 DECL(AL_BYTE_LENGTH_SOFT
),
530 DECL(AL_SAMPLE_LENGTH_SOFT
),
531 DECL(AL_SEC_LENGTH_SOFT
),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
535 DECL(AL_SOURCE_RADIUS
),
537 DECL(AL_STEREO_ANGLES
),
544 DECL(AL_INVALID_NAME
),
545 DECL(AL_INVALID_ENUM
),
546 DECL(AL_INVALID_VALUE
),
547 DECL(AL_INVALID_OPERATION
),
548 DECL(AL_OUT_OF_MEMORY
),
555 DECL(AL_DOPPLER_FACTOR
),
556 DECL(AL_DOPPLER_VELOCITY
),
557 DECL(AL_DISTANCE_MODEL
),
558 DECL(AL_SPEED_OF_SOUND
),
559 DECL(AL_SOURCE_DISTANCE_MODEL
),
560 DECL(AL_DEFERRED_UPDATES_SOFT
),
561 DECL(AL_GAIN_LIMIT_SOFT
),
563 DECL(AL_INVERSE_DISTANCE
),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
565 DECL(AL_LINEAR_DISTANCE
),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
567 DECL(AL_EXPONENT_DISTANCE
),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
570 DECL(AL_FILTER_TYPE
),
571 DECL(AL_FILTER_NULL
),
572 DECL(AL_FILTER_LOWPASS
),
573 DECL(AL_FILTER_HIGHPASS
),
574 DECL(AL_FILTER_BANDPASS
),
576 DECL(AL_LOWPASS_GAIN
),
577 DECL(AL_LOWPASS_GAINHF
),
579 DECL(AL_HIGHPASS_GAIN
),
580 DECL(AL_HIGHPASS_GAINLF
),
582 DECL(AL_BANDPASS_GAIN
),
583 DECL(AL_BANDPASS_GAINHF
),
584 DECL(AL_BANDPASS_GAINLF
),
586 DECL(AL_EFFECT_TYPE
),
587 DECL(AL_EFFECT_NULL
),
588 DECL(AL_EFFECT_REVERB
),
589 DECL(AL_EFFECT_EAXREVERB
),
590 DECL(AL_EFFECT_CHORUS
),
591 DECL(AL_EFFECT_DISTORTION
),
592 DECL(AL_EFFECT_ECHO
),
593 DECL(AL_EFFECT_FLANGER
),
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
596 DECL(AL_EFFECT_VOCAL_MORPHER
),
597 DECL(AL_EFFECT_PITCH_SHIFTER
),
599 DECL(AL_EFFECT_RING_MODULATOR
),
601 DECL(AL_EFFECT_AUTOWAH
),
603 DECL(AL_EFFECT_COMPRESSOR
),
604 DECL(AL_EFFECT_EQUALIZER
),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
608 DECL(AL_EFFECTSLOT_EFFECT
),
609 DECL(AL_EFFECTSLOT_GAIN
),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
611 DECL(AL_EFFECTSLOT_NULL
),
613 DECL(AL_EAXREVERB_DENSITY
),
614 DECL(AL_EAXREVERB_DIFFUSION
),
615 DECL(AL_EAXREVERB_GAIN
),
616 DECL(AL_EAXREVERB_GAINHF
),
617 DECL(AL_EAXREVERB_GAINLF
),
618 DECL(AL_EAXREVERB_DECAY_TIME
),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
627 DECL(AL_EAXREVERB_ECHO_TIME
),
628 DECL(AL_EAXREVERB_ECHO_DEPTH
),
629 DECL(AL_EAXREVERB_MODULATION_TIME
),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
632 DECL(AL_EAXREVERB_HFREFERENCE
),
633 DECL(AL_EAXREVERB_LFREFERENCE
),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
637 DECL(AL_REVERB_DENSITY
),
638 DECL(AL_REVERB_DIFFUSION
),
639 DECL(AL_REVERB_GAIN
),
640 DECL(AL_REVERB_GAINHF
),
641 DECL(AL_REVERB_DECAY_TIME
),
642 DECL(AL_REVERB_DECAY_HFRATIO
),
643 DECL(AL_REVERB_REFLECTIONS_GAIN
),
644 DECL(AL_REVERB_REFLECTIONS_DELAY
),
645 DECL(AL_REVERB_LATE_REVERB_GAIN
),
646 DECL(AL_REVERB_LATE_REVERB_DELAY
),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
649 DECL(AL_REVERB_DECAY_HFLIMIT
),
651 DECL(AL_CHORUS_WAVEFORM
),
652 DECL(AL_CHORUS_PHASE
),
653 DECL(AL_CHORUS_RATE
),
654 DECL(AL_CHORUS_DEPTH
),
655 DECL(AL_CHORUS_FEEDBACK
),
656 DECL(AL_CHORUS_DELAY
),
658 DECL(AL_DISTORTION_EDGE
),
659 DECL(AL_DISTORTION_GAIN
),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
661 DECL(AL_DISTORTION_EQCENTER
),
662 DECL(AL_DISTORTION_EQBANDWIDTH
),
665 DECL(AL_ECHO_LRDELAY
),
666 DECL(AL_ECHO_DAMPING
),
667 DECL(AL_ECHO_FEEDBACK
),
668 DECL(AL_ECHO_SPREAD
),
670 DECL(AL_FLANGER_WAVEFORM
),
671 DECL(AL_FLANGER_PHASE
),
672 DECL(AL_FLANGER_RATE
),
673 DECL(AL_FLANGER_DEPTH
),
674 DECL(AL_FLANGER_FEEDBACK
),
675 DECL(AL_FLANGER_DELAY
),
677 DECL(AL_RING_MODULATOR_FREQUENCY
),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
679 DECL(AL_RING_MODULATOR_WAVEFORM
),
681 DECL(AL_COMPRESSOR_ONOFF
),
683 DECL(AL_EQUALIZER_LOW_GAIN
),
684 DECL(AL_EQUALIZER_LOW_CUTOFF
),
685 DECL(AL_EQUALIZER_MID1_GAIN
),
686 DECL(AL_EQUALIZER_MID1_CENTER
),
687 DECL(AL_EQUALIZER_MID1_WIDTH
),
688 DECL(AL_EQUALIZER_MID2_GAIN
),
689 DECL(AL_EQUALIZER_MID2_CENTER
),
690 DECL(AL_EQUALIZER_MID2_WIDTH
),
691 DECL(AL_EQUALIZER_HIGH_GAIN
),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
694 DECL(AL_DEDICATED_GAIN
),
698 static const ALCchar alcNoError
[] = "No Error";
699 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
706 /************************************************
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList
;
714 static al_string alcCaptureDeviceList
;
716 /* Default is always the first in the list */
717 static ALCchar
*alcDefaultAllDevicesSpecifier
;
718 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
720 /* Default context extensions */
721 static const ALchar alExtList
[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
732 /* Thread-local current context */
733 static altss_t LocalContext
;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
737 /* Mixing thread piority level */
742 enum LogLevel LogLevel
= LogWarning
;
744 enum LogLevel LogLevel
= LogError
;
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError
= ALC_FALSE
;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect
;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
759 static ALCboolean SuspendDefers
= ALC_TRUE
;
762 /************************************************
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList
[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList
[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion
= 1;
774 static const ALCint alcMinorVersion
= 1;
776 static const ALCint alcEFXMajorVersion
= 1;
777 static const ALCint alcEFXMinorVersion
= 0;
780 /************************************************
782 ************************************************/
783 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
785 static almtx_t ListLock
;
786 static inline void LockLists(void)
788 int ret
= almtx_lock(&ListLock
);
789 assert(ret
== althrd_success
);
791 static inline void UnlockLists(void)
793 int ret
= almtx_unlock(&ListLock
);
794 assert(ret
== althrd_success
);
797 /************************************************
798 * Library initialization
799 ************************************************/
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
810 case DLL_PROCESS_ATTACH
:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
813 (WCHAR
*)hModule
, &hModule
);
817 case DLL_THREAD_DETACH
:
820 case DLL_PROCESS_DETACH
:
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
835 static void alc_constructor(void)
837 atexit(alc_destructor
);
841 static void alc_destructor(void)
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor
));
847 static void alc_deinit(void) __attribute__((destructor
));
849 #error "No static initialization available on this platform!"
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor
));
855 static void alc_deinit(void) __attribute__((destructor
));
858 #error "No global initialization available on this platform!"
861 static void ReleaseThreadCtx(void *ptr
);
862 static void alc_init(void)
869 AL_STRING_INIT(alcAllDevicesList
);
870 AL_STRING_INIT(alcCaptureDeviceList
);
872 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
876 str
= getenv("__ALSOFT_REVERSE_Z");
877 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
880 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
881 assert(ret
== althrd_success
);
883 ret
= almtx_init(&ListLock
, almtx_recursive
);
884 assert(ret
== althrd_success
);
889 static void alc_initconfig(void)
891 const char *devs
, *str
;
896 str
= getenv("ALSOFT_LOGLEVEL");
899 long lvl
= strtol(str
, NULL
, 0);
900 if(lvl
>= NoLog
&& lvl
<= LogRef
)
904 str
= getenv("ALSOFT_LOGFILE");
907 FILE *logfile
= al_fopen(str
, "wt");
908 if(logfile
) LogFile
= logfile
;
909 else ERR("Failed to open log file '%s'\n", str
);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
913 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
918 if(BackendListSize
> 0)
919 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
920 for(i
= 1;i
< BackendListSize
;i
++)
921 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
922 TRACE("Supported backends: %s\n", buf
);
926 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
929 if(strcasecmp(str
, "ignore") == 0)
931 SuspendDefers
= ALC_FALSE
;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
939 #if defined(HAVE_SSE4_1)
940 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
941 #elif defined(HAVE_SSE3)
942 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
943 #elif defined(HAVE_SSE2)
944 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
945 #elif defined(HAVE_SSE)
946 capfilter
|= CPU_CAP_SSE
;
949 capfilter
|= CPU_CAP_NEON
;
951 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
953 if(strcasecmp(str
, "all") == 0)
958 const char *next
= str
;
962 while(isspace(str
[0]))
964 next
= strchr(str
, ',');
966 if(!str
[0] || str
[0] == ',')
969 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
970 while(len
> 0 && isspace(str
[len
-1]))
972 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
973 capfilter
&= ~CPU_CAP_SSE
;
974 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
975 capfilter
&= ~CPU_CAP_SSE2
;
976 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
977 capfilter
&= ~CPU_CAP_SSE3
;
978 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
979 capfilter
&= ~CPU_CAP_SSE4_1
;
980 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
981 capfilter
&= ~CPU_CAP_NEON
;
983 WARN("Invalid CPU extension \"%s\"\n", str
);
987 FillCPUCaps(capfilter
);
994 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
998 str
= getenv("ALSOFT_TRAP_ERROR");
999 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1001 TrapALError
= AL_TRUE
;
1002 TrapALCError
= AL_TRUE
;
1006 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1008 TrapALError
= AL_TRUE
;
1009 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1011 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1013 TrapALCError
= ALC_TRUE
;
1014 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1017 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1018 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1020 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1022 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1023 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1027 const char *next
= devs
;
1028 int endlist
, delitem
;
1033 while(isspace(devs
[0]))
1035 next
= strchr(devs
, ',');
1037 delitem
= (devs
[0] == '-');
1038 if(devs
[0] == '-') devs
++;
1040 if(!devs
[0] || devs
[0] == ',')
1047 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1048 while(len
> 0 && isspace(devs
[len
-1]))
1050 for(n
= i
;n
< BackendListSize
;n
++)
1052 if(len
== strlen(BackendList
[n
].name
) &&
1053 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1057 for(;n
+1 < BackendListSize
;n
++)
1058 BackendList
[n
] = BackendList
[n
+1];
1063 struct BackendInfo Bkp
= BackendList
[n
];
1065 BackendList
[n
] = BackendList
[n
-1];
1066 BackendList
[n
] = Bkp
;
1076 BackendListSize
= i
;
1079 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1081 if(BackendList
[i
].getFactory
)
1083 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1084 if(!V0(factory
,init
)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1090 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1091 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1093 PlaybackBackend
= BackendList
[i
];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1096 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1098 CaptureBackend
= BackendList
[i
];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1105 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1111 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1112 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1114 PlaybackBackend
= BackendList
[i
];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1117 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1119 CaptureBackend
= BackendList
[i
];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1124 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1128 if(!PlaybackBackend
.name
)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend
.name
)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1136 const char *next
= str
;
1140 next
= strchr(str
, ',');
1142 if(!str
[0] || next
== str
)
1145 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1146 for(n
= 0;EffectList
[n
].name
;n
++)
1148 if(len
== strlen(EffectList
[n
].name
) &&
1149 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1150 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect
);
1158 str
= getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1160 LoadReverbPreset(str
, &DefaultEffect
);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1167 static JavaVM
*gJavaVM
;
1168 static pthread_key_t gJVMThreadKey
;
1170 static void CleanupJNIEnv(void* UNUSED(ptr
))
1172 JCALL0(gJavaVM
,DetachCurrentThread
)();
1175 void *Android_GetJNIEnv(void)
1179 WARN("gJavaVM is NULL!\n");
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1196 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1199 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1202 ERR("Failed to attach current thread\n");
1205 pthread_setspecific(gJVMThreadKey
, env
);
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1217 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err
);
1228 pthread_setspecific(gJVMThreadKey
, env
);
1229 return JNI_VERSION_1_4
;
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1242 AL_STRING_DEINIT(alcAllDevicesList
);
1243 AL_STRING_DEINIT(alcCaptureDeviceList
);
1245 free(alcDefaultAllDevicesSpecifier
);
1246 alcDefaultAllDevicesSpecifier
= NULL
;
1247 free(alcCaptureDefaultDeviceSpecifier
);
1248 alcCaptureDefaultDeviceSpecifier
= NULL
;
1250 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&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 DevFmtAmbi3D
: return "Ambisonic 3D";
1372 return "(unknown channels)";
1375 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1376 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1380 case DevFmtByte
: return sizeof(ALbyte
);
1381 case DevFmtUByte
: return sizeof(ALubyte
);
1382 case DevFmtShort
: return sizeof(ALshort
);
1383 case DevFmtUShort
: return sizeof(ALushort
);
1384 case DevFmtInt
: return sizeof(ALint
);
1385 case DevFmtUInt
: return sizeof(ALuint
);
1386 case DevFmtFloat
: return sizeof(ALfloat
);
1390 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1394 case DevFmtMono
: return 1;
1395 case DevFmtStereo
: return 2;
1396 case DevFmtQuad
: return 4;
1397 case DevFmtX51
: return 6;
1398 case DevFmtX51Rear
: return 6;
1399 case DevFmtX61
: return 7;
1400 case DevFmtX71
: return 8;
1401 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1402 (ambiorder
== 2) ? 9 :
1403 (ambiorder
== 1) ? 4 : 1;
1408 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1409 enum DevFmtType
*type
)
1411 static const struct {
1413 enum DevFmtChannels channels
;
1414 enum DevFmtType type
;
1416 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1417 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1418 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1420 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1421 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1422 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1424 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1425 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1426 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1428 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1429 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1430 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1432 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1433 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1434 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1436 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1437 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1438 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1442 for(i
= 0;i
< COUNTOF(list
);i
++)
1444 if(list
[i
].format
== format
)
1446 *chans
= list
[i
].channels
;
1447 *type
= list
[i
].type
;
1455 static ALCboolean
IsValidALCType(ALCenum type
)
1460 case ALC_UNSIGNED_BYTE_SOFT
:
1461 case ALC_SHORT_SOFT
:
1462 case ALC_UNSIGNED_SHORT_SOFT
:
1464 case ALC_UNSIGNED_INT_SOFT
:
1465 case ALC_FLOAT_SOFT
:
1471 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1476 case ALC_STEREO_SOFT
:
1478 case ALC_5POINT1_SOFT
:
1479 case ALC_6POINT1_SOFT
:
1480 case ALC_7POINT1_SOFT
:
1481 case ALC_BFORMAT3D_SOFT
:
1487 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1498 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1510 /************************************************
1511 * Miscellaneous ALC helpers
1512 ************************************************/
1514 void ALCdevice_Lock(ALCdevice
*device
)
1516 V0(device
->Backend
,lock
)();
1519 void ALCdevice_Unlock(ALCdevice
*device
)
1521 V0(device
->Backend
,unlock
)();
1525 /* SetDefaultWFXChannelOrder
1527 * Sets the default channel order used by WaveFormatEx.
1529 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1533 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1534 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1536 switch(device
->FmtChans
)
1539 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1542 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1543 device
->RealOut
.ChannelName
[1] = FrontRight
;
1546 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1547 device
->RealOut
.ChannelName
[1] = FrontRight
;
1548 device
->RealOut
.ChannelName
[2] = BackLeft
;
1549 device
->RealOut
.ChannelName
[3] = BackRight
;
1552 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1553 device
->RealOut
.ChannelName
[1] = FrontRight
;
1554 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1555 device
->RealOut
.ChannelName
[3] = LFE
;
1556 device
->RealOut
.ChannelName
[4] = SideLeft
;
1557 device
->RealOut
.ChannelName
[5] = SideRight
;
1560 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1561 device
->RealOut
.ChannelName
[1] = FrontRight
;
1562 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1563 device
->RealOut
.ChannelName
[3] = LFE
;
1564 device
->RealOut
.ChannelName
[4] = BackLeft
;
1565 device
->RealOut
.ChannelName
[5] = BackRight
;
1568 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1569 device
->RealOut
.ChannelName
[1] = FrontRight
;
1570 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1571 device
->RealOut
.ChannelName
[3] = LFE
;
1572 device
->RealOut
.ChannelName
[4] = BackCenter
;
1573 device
->RealOut
.ChannelName
[5] = SideLeft
;
1574 device
->RealOut
.ChannelName
[6] = SideRight
;
1577 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1578 device
->RealOut
.ChannelName
[1] = FrontRight
;
1579 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1580 device
->RealOut
.ChannelName
[3] = LFE
;
1581 device
->RealOut
.ChannelName
[4] = BackLeft
;
1582 device
->RealOut
.ChannelName
[5] = BackRight
;
1583 device
->RealOut
.ChannelName
[6] = SideLeft
;
1584 device
->RealOut
.ChannelName
[7] = SideRight
;
1587 device
->RealOut
.ChannelName
[0] = Aux0
;
1588 if(device
->AmbiOrder
> 0)
1590 device
->RealOut
.ChannelName
[1] = Aux1
;
1591 device
->RealOut
.ChannelName
[2] = Aux2
;
1592 device
->RealOut
.ChannelName
[3] = Aux3
;
1594 if(device
->AmbiOrder
> 1)
1596 device
->RealOut
.ChannelName
[4] = Aux4
;
1597 device
->RealOut
.ChannelName
[5] = Aux5
;
1598 device
->RealOut
.ChannelName
[6] = Aux6
;
1599 device
->RealOut
.ChannelName
[7] = Aux7
;
1600 device
->RealOut
.ChannelName
[8] = Aux8
;
1602 if(device
->AmbiOrder
> 2)
1604 device
->RealOut
.ChannelName
[9] = Aux9
;
1605 device
->RealOut
.ChannelName
[10] = Aux10
;
1606 device
->RealOut
.ChannelName
[11] = Aux11
;
1607 device
->RealOut
.ChannelName
[12] = Aux12
;
1608 device
->RealOut
.ChannelName
[13] = Aux13
;
1609 device
->RealOut
.ChannelName
[14] = Aux14
;
1610 device
->RealOut
.ChannelName
[15] = Aux15
;
1616 /* SetDefaultChannelOrder
1618 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1620 void SetDefaultChannelOrder(ALCdevice
*device
)
1624 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1625 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1627 switch(device
->FmtChans
)
1630 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1631 device
->RealOut
.ChannelName
[1] = FrontRight
;
1632 device
->RealOut
.ChannelName
[2] = BackLeft
;
1633 device
->RealOut
.ChannelName
[3] = BackRight
;
1634 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1635 device
->RealOut
.ChannelName
[5] = LFE
;
1638 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1639 device
->RealOut
.ChannelName
[1] = FrontRight
;
1640 device
->RealOut
.ChannelName
[2] = BackLeft
;
1641 device
->RealOut
.ChannelName
[3] = BackRight
;
1642 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1643 device
->RealOut
.ChannelName
[5] = LFE
;
1644 device
->RealOut
.ChannelName
[6] = SideLeft
;
1645 device
->RealOut
.ChannelName
[7] = SideRight
;
1648 /* Same as WFX order */
1655 SetDefaultWFXChannelOrder(device
);
1660 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1663 /* ALCcontext_DeferUpdates
1665 * Defers/suspends updates for the given context's listener and sources. This
1666 * does *NOT* stop mixing, but rather prevents certain property changes from
1669 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1671 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1674 /* ALCcontext_ProcessUpdates
1676 * Resumes update processing after being deferred.
1678 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1680 ReadLock(&context
->PropLock
);
1681 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1683 /* Tell the mixer to stop applying updates, then wait for any active
1684 * updating to finish, before providing updates.
1686 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1687 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1690 UpdateListenerProps(context
);
1691 UpdateAllEffectSlotProps(context
);
1692 UpdateAllSourceProps(context
);
1694 /* Now with all updates declared, let the mixer continue applying them
1695 * so they all happen at once.
1697 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1699 ReadUnlock(&context
->PropLock
);
1705 * Stores the latest ALC device error
1707 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1709 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1713 /* DebugBreak() will cause an exception if there is no debugger */
1714 if(IsDebuggerPresent())
1716 #elif defined(SIGTRAP)
1722 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1724 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1730 * Updates the device's base clock time with however many samples have been
1731 * done. This is used so frequency changes on the device don't cause the time
1732 * to jump forward or back. Must not be called while the device is running/
1735 static inline void UpdateClockBase(ALCdevice
*device
)
1737 IncrementRef(&device
->MixCount
);
1738 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1739 device
->SamplesDone
= 0;
1740 IncrementRef(&device
->MixCount
);
1743 /* UpdateDeviceParams
1745 * Updates device parameters according to the attribute list (caller is
1746 * responsible for holding the list lock).
1748 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1750 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1751 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1752 const ALsizei old_sends
= device
->NumAuxSends
;
1753 ALsizei new_sends
= device
->NumAuxSends
;
1754 enum DevFmtChannels oldChans
;
1755 enum DevFmtType oldType
;
1756 ALboolean update_failed
;
1757 ALCsizei hrtf_id
= -1;
1758 ALCcontext
*context
;
1764 // Check for attributes
1765 if(device
->Type
== Loopback
)
1767 ALCsizei numMono
, numStereo
, numSends
;
1768 ALCenum alayout
= AL_NONE
;
1769 ALCenum ascale
= AL_NONE
;
1770 ALCenum schans
= AL_NONE
;
1771 ALCenum stype
= AL_NONE
;
1772 ALCsizei attrIdx
= 0;
1773 ALCsizei aorder
= 0;
1778 WARN("Missing attributes for loopback device\n");
1779 return ALC_INVALID_VALUE
;
1782 numMono
= device
->NumMonoSources
;
1783 numStereo
= device
->NumStereoSources
;
1784 numSends
= old_sends
;
1786 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1787 while(attrList
[attrIdx
])
1789 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1791 schans
= attrList
[attrIdx
+ 1];
1792 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1793 if(!IsValidALCChannels(schans
))
1794 return ALC_INVALID_VALUE
;
1797 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1799 stype
= attrList
[attrIdx
+ 1];
1800 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1801 if(!IsValidALCType(stype
))
1802 return ALC_INVALID_VALUE
;
1805 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1807 freq
= attrList
[attrIdx
+ 1];
1808 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1809 if(freq
< MIN_OUTPUT_RATE
)
1810 return ALC_INVALID_VALUE
;
1813 if(attrList
[attrIdx
] == ALC_AMBISONIC_LAYOUT_SOFT
)
1815 alayout
= attrList
[attrIdx
+ 1];
1816 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1817 if(!IsValidAmbiLayout(alayout
))
1818 return ALC_INVALID_VALUE
;
1821 if(attrList
[attrIdx
] == ALC_AMBISONIC_SCALING_SOFT
)
1823 ascale
= attrList
[attrIdx
+ 1];
1824 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1825 if(!IsValidAmbiScaling(ascale
))
1826 return ALC_INVALID_VALUE
;
1829 if(attrList
[attrIdx
] == ALC_AMBISONIC_ORDER_SOFT
)
1831 aorder
= attrList
[attrIdx
+ 1];
1832 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1833 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1834 return ALC_INVALID_VALUE
;
1837 if(attrList
[attrIdx
] == ALC_MONO_SOURCES
)
1839 numMono
= attrList
[attrIdx
+ 1];
1840 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1841 numMono
= maxi(numMono
, 0);
1844 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1846 numStereo
= attrList
[attrIdx
+ 1];
1847 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1848 numStereo
= maxi(numStereo
, 0);
1851 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1853 numSends
= attrList
[attrIdx
+ 1];
1854 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1855 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1858 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1860 ALCint val
= attrList
[attrIdx
+ 1];
1861 TRACE_ATTR(ALC_HRTF_SOFT
, val
);
1862 if(val
== ALC_FALSE
)
1863 hrtf_appreq
= Hrtf_Disable
;
1864 else if(val
== ALC_TRUE
)
1865 hrtf_appreq
= Hrtf_Enable
;
1867 hrtf_appreq
= Hrtf_Default
;
1870 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
1872 hrtf_id
= attrList
[attrIdx
+ 1];
1873 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1880 if(!schans
|| !stype
|| !freq
)
1882 WARN("Missing format for loopback device\n");
1883 return ALC_INVALID_VALUE
;
1885 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1887 WARN("Missing ambisonic info for loopback device\n");
1888 return ALC_INVALID_VALUE
;
1891 if((device
->Flags
&DEVICE_RUNNING
))
1892 V0(device
->Backend
,stop
)();
1893 device
->Flags
&= ~DEVICE_RUNNING
;
1895 UpdateClockBase(device
);
1897 device
->Frequency
= freq
;
1898 device
->FmtChans
= schans
;
1899 device
->FmtType
= stype
;
1900 if(schans
== ALC_BFORMAT3D_SOFT
)
1902 device
->AmbiOrder
= aorder
;
1903 device
->AmbiLayout
= alayout
;
1904 device
->AmbiScale
= ascale
;
1907 if(numMono
> INT_MAX
-numStereo
)
1908 numMono
= INT_MAX
-numStereo
;
1909 numMono
+= numStereo
;
1910 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1916 numMono
= maxi(numMono
, 256);
1917 numStereo
= mini(numStereo
, numMono
);
1918 numMono
-= numStereo
;
1919 device
->SourcesMax
= numMono
+ numStereo
;
1921 device
->NumMonoSources
= numMono
;
1922 device
->NumStereoSources
= numStereo
;
1924 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1925 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1927 new_sends
= numSends
;
1929 else if(attrList
&& attrList
[0])
1931 ALCsizei numMono
, numStereo
, numSends
;
1932 ALCsizei attrIdx
= 0;
1935 /* If a context is already running on the device, stop playback so the
1936 * device attributes can be updated. */
1937 if((device
->Flags
&DEVICE_RUNNING
))
1938 V0(device
->Backend
,stop
)();
1939 device
->Flags
&= ~DEVICE_RUNNING
;
1941 UpdateClockBase(device
);
1943 freq
= device
->Frequency
;
1944 numMono
= device
->NumMonoSources
;
1945 numStereo
= device
->NumStereoSources
;
1946 numSends
= old_sends
;
1948 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1949 while(attrList
[attrIdx
])
1951 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1953 freq
= attrList
[attrIdx
+ 1];
1954 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1955 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1958 if(attrList
[attrIdx
] == ALC_MONO_SOURCES
)
1960 numMono
= attrList
[attrIdx
+ 1];
1961 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1962 numMono
= maxi(numMono
, 0);
1965 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1967 numStereo
= attrList
[attrIdx
+ 1];
1968 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1969 numStereo
= maxi(numStereo
, 0);
1972 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1974 numSends
= attrList
[attrIdx
+ 1];
1975 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1976 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1979 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1981 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1982 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1983 hrtf_appreq
= Hrtf_Disable
;
1984 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1985 hrtf_appreq
= Hrtf_Enable
;
1987 hrtf_appreq
= Hrtf_Default
;
1990 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
1992 hrtf_id
= attrList
[attrIdx
+ 1];
1993 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
2000 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2001 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2003 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2005 /* SSE and Neon do best with the update size being a multiple of 4 */
2006 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2007 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2009 device
->Frequency
= freq
;
2011 if(numMono
> INT_MAX
-numStereo
)
2012 numMono
= INT_MAX
-numStereo
;
2013 numMono
+= numStereo
;
2014 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2020 numMono
= maxi(numMono
, 256);
2021 numStereo
= mini(numStereo
, numMono
);
2022 numMono
-= numStereo
;
2023 device
->SourcesMax
= numMono
+ numStereo
;
2025 device
->NumMonoSources
= numMono
;
2026 device
->NumStereoSources
= numStereo
;
2028 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2029 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2031 new_sends
= numSends
;
2034 if((device
->Flags
&DEVICE_RUNNING
))
2035 return ALC_NO_ERROR
;
2037 al_free(device
->Uhj_Encoder
);
2038 device
->Uhj_Encoder
= NULL
;
2040 al_free(device
->Bs2b
);
2041 device
->Bs2b
= NULL
;
2043 al_free(device
->ChannelDelay
[0].Buffer
);
2044 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2046 device
->ChannelDelay
[i
].Length
= 0;
2047 device
->ChannelDelay
[i
].Buffer
= NULL
;
2050 al_free(device
->Dry
.Buffer
);
2051 device
->Dry
.Buffer
= NULL
;
2052 device
->Dry
.NumChannels
= 0;
2053 device
->FOAOut
.Buffer
= NULL
;
2054 device
->FOAOut
.NumChannels
= 0;
2055 device
->RealOut
.Buffer
= NULL
;
2056 device
->RealOut
.NumChannels
= 0;
2058 UpdateClockBase(device
);
2060 /*************************************************************************
2061 * Update device format request if HRTF is requested
2063 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2064 if(device
->Type
!= Loopback
)
2067 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2069 if(strcasecmp(hrtf
, "true") == 0)
2070 hrtf_userreq
= Hrtf_Enable
;
2071 else if(strcasecmp(hrtf
, "false") == 0)
2072 hrtf_userreq
= Hrtf_Disable
;
2073 else if(strcasecmp(hrtf
, "auto") != 0)
2074 ERR("Unexpected hrtf value: %s\n", hrtf
);
2077 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2079 struct Hrtf
*hrtf
= NULL
;
2080 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2082 VECTOR_DEINIT(device
->HrtfList
);
2083 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2085 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2087 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2088 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2090 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2095 device
->FmtChans
= DevFmtStereo
;
2096 device
->Frequency
= hrtf
->sampleRate
;
2097 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2098 if(device
->HrtfHandle
)
2099 Hrtf_DecRef(device
->HrtfHandle
);
2100 device
->HrtfHandle
= hrtf
;
2104 hrtf_userreq
= Hrtf_Default
;
2105 hrtf_appreq
= Hrtf_Disable
;
2106 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2111 oldFreq
= device
->Frequency
;
2112 oldChans
= device
->FmtChans
;
2113 oldType
= device
->FmtType
;
2115 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2116 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2117 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2118 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2119 device
->UpdateSize
, device
->NumUpdates
2122 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2123 return ALC_INVALID_DEVICE
;
2125 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2127 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2128 DevFmtChannelsString(device
->FmtChans
));
2129 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2131 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2133 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2134 DevFmtTypeString(device
->FmtType
));
2135 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2137 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2139 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2140 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2143 if((device
->UpdateSize
&3) != 0)
2145 if((CPUCapFlags
&CPU_CAP_SSE
))
2146 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2147 if((CPUCapFlags
&CPU_CAP_NEON
))
2148 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2151 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2152 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2153 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2156 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2157 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2158 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2160 /* Allocate extra channels for any post-filter output. */
2161 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2162 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2164 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2165 device
->Dry
.Buffer
= al_calloc(16, size
);
2166 if(!device
->Dry
.Buffer
)
2168 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2169 return ALC_INVALID_DEVICE
;
2172 if(device
->RealOut
.NumChannels
!= 0)
2173 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2174 device
->FOAOut
.NumChannels
;
2177 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2178 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2181 if(device
->FOAOut
.NumChannels
!= 0)
2182 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2185 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2186 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2189 /* Need to delay returning failure until replacement Send arrays have been
2190 * allocated with the appropriate size.
2192 device
->NumAuxSends
= new_sends
;
2193 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2194 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2195 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2196 update_failed
= AL_FALSE
;
2197 SetMixerFPUMode(&oldMode
);
2198 if(device
->DefaultSlot
)
2200 ALeffectslot
*slot
= device
->DefaultSlot
;
2201 ALeffectState
*state
= slot
->Effect
.State
;
2203 state
->OutBuffer
= device
->Dry
.Buffer
;
2204 state
->OutChannels
= device
->Dry
.NumChannels
;
2205 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2206 update_failed
= AL_TRUE
;
2208 UpdateEffectSlotProps(slot
);
2211 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2216 WriteLock(&context
->PropLock
);
2217 LockUIntMapRead(&context
->EffectSlotMap
);
2218 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2220 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2221 ALeffectState
*state
= slot
->Effect
.State
;
2223 state
->OutBuffer
= device
->Dry
.Buffer
;
2224 state
->OutChannels
= device
->Dry
.NumChannels
;
2225 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2226 update_failed
= AL_TRUE
;
2228 UpdateEffectSlotProps(slot
);
2230 UnlockUIntMapRead(&context
->EffectSlotMap
);
2232 LockUIntMapRead(&context
->SourceMap
);
2233 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2234 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2236 ALsource
*source
= context
->SourceMap
.values
[pos
];
2237 struct ALsourceProps
*props
;
2239 if(old_sends
!= device
->NumAuxSends
)
2241 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2244 memcpy(sends
, source
->Send
,
2245 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2247 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2249 if(source
->Send
[s
].Slot
)
2250 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2251 source
->Send
[s
].Slot
= NULL
;
2253 al_free(source
->Send
);
2254 source
->Send
= sends
;
2255 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2257 source
->Send
[s
].Slot
= NULL
;
2258 source
->Send
[s
].Gain
= 1.0f
;
2259 source
->Send
[s
].GainHF
= 1.0f
;
2260 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2261 source
->Send
[s
].GainLF
= 1.0f
;
2262 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2266 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2268 /* Clear any pre-existing source property structs, in case the
2269 * number of auxiliary sends changed. Playing (or paused) sources
2270 * will have updates respecified in UpdateAllSourceProps.
2272 props
= ATOMIC_EXCHANGE_PTR_SEQ(&source
->Update
, NULL
);
2275 props
= ATOMIC_EXCHANGE_PTR(&source
->FreeList
, NULL
, almemory_order_relaxed
);
2278 struct ALsourceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2283 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2284 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2286 ALvoice
*voice
= context
->Voices
[pos
];
2287 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2290 if(device
->AvgSpeakerDist
> 0.0f
)
2292 /* Reinitialize the NFC filters for new parameters. */
2293 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2294 (device
->AvgSpeakerDist
* device
->Frequency
);
2295 for(i
= 0;i
< voice
->NumChannels
;i
++)
2297 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2298 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2299 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2303 UnlockUIntMapRead(&context
->SourceMap
);
2305 UpdateListenerProps(context
);
2306 UpdateAllSourceProps(context
);
2307 WriteUnlock(&context
->PropLock
);
2309 context
= context
->next
;
2311 RestoreFPUMode(&oldMode
);
2313 return ALC_INVALID_DEVICE
;
2315 if(!(device
->Flags
&DEVICE_PAUSED
))
2317 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2318 return ALC_INVALID_DEVICE
;
2319 device
->Flags
|= DEVICE_RUNNING
;
2322 return ALC_NO_ERROR
;
2327 * Frees the device structure, and destroys any objects the app failed to
2328 * delete. Called once there's no more references on the device.
2330 static ALCvoid
FreeDevice(ALCdevice
*device
)
2334 TRACE("%p\n", device
);
2336 V0(device
->Backend
,close
)();
2337 DELETE_OBJ(device
->Backend
);
2338 device
->Backend
= NULL
;
2340 almtx_destroy(&device
->BackendLock
);
2342 if(device
->DefaultSlot
)
2344 DeinitEffectSlot(device
->DefaultSlot
);
2345 device
->DefaultSlot
= NULL
;
2348 if(device
->BufferMap
.size
> 0)
2350 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2351 (device
->BufferMap
.size
==1)?"":"s");
2352 ReleaseALBuffers(device
);
2354 ResetUIntMap(&device
->BufferMap
);
2356 if(device
->EffectMap
.size
> 0)
2358 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2359 (device
->EffectMap
.size
==1)?"":"s");
2360 ReleaseALEffects(device
);
2362 ResetUIntMap(&device
->EffectMap
);
2364 if(device
->FilterMap
.size
> 0)
2366 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2367 (device
->FilterMap
.size
==1)?"":"s");
2368 ReleaseALFilters(device
);
2370 ResetUIntMap(&device
->FilterMap
);
2372 AL_STRING_DEINIT(device
->HrtfName
);
2373 FreeHrtfList(&device
->HrtfList
);
2374 if(device
->HrtfHandle
)
2375 Hrtf_DecRef(device
->HrtfHandle
);
2376 device
->HrtfHandle
= NULL
;
2377 al_free(device
->Hrtf
);
2378 device
->Hrtf
= NULL
;
2380 al_free(device
->Bs2b
);
2381 device
->Bs2b
= NULL
;
2383 al_free(device
->Uhj_Encoder
);
2384 device
->Uhj_Encoder
= NULL
;
2386 bformatdec_free(device
->AmbiDecoder
);
2387 device
->AmbiDecoder
= NULL
;
2389 ambiup_free(device
->AmbiUp
);
2390 device
->AmbiUp
= NULL
;
2392 al_free(device
->ChannelDelay
[0].Buffer
);
2393 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2395 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2396 device
->ChannelDelay
[i
].Length
= 0;
2397 device
->ChannelDelay
[i
].Buffer
= NULL
;
2400 AL_STRING_DEINIT(device
->DeviceName
);
2402 al_free(device
->Dry
.Buffer
);
2403 device
->Dry
.Buffer
= NULL
;
2404 device
->Dry
.NumChannels
= 0;
2405 device
->FOAOut
.Buffer
= NULL
;
2406 device
->FOAOut
.NumChannels
= 0;
2407 device
->RealOut
.Buffer
= NULL
;
2408 device
->RealOut
.NumChannels
= 0;
2414 void ALCdevice_IncRef(ALCdevice
*device
)
2417 ref
= IncrementRef(&device
->ref
);
2418 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2421 void ALCdevice_DecRef(ALCdevice
*device
)
2424 ref
= DecrementRef(&device
->ref
);
2425 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2426 if(ref
== 0) FreeDevice(device
);
2431 * Checks if the device handle is valid, and increments its ref count if so.
2433 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2435 ALCdevice
*tmpDevice
;
2438 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2441 if(tmpDevice
== *device
)
2443 ALCdevice_IncRef(tmpDevice
);
2447 tmpDevice
= tmpDevice
->next
;
2458 * Initializes context fields
2460 static ALvoid
InitContext(ALCcontext
*Context
)
2462 ALlistener
*listener
= Context
->Listener
;
2463 struct ALeffectslotArray
*auxslots
;
2465 //Initialise listener
2466 listener
->Gain
= 1.0f
;
2467 listener
->MetersPerUnit
= 1.0f
;
2468 listener
->Position
[0] = 0.0f
;
2469 listener
->Position
[1] = 0.0f
;
2470 listener
->Position
[2] = 0.0f
;
2471 listener
->Velocity
[0] = 0.0f
;
2472 listener
->Velocity
[1] = 0.0f
;
2473 listener
->Velocity
[2] = 0.0f
;
2474 listener
->Forward
[0] = 0.0f
;
2475 listener
->Forward
[1] = 0.0f
;
2476 listener
->Forward
[2] = -1.0f
;
2477 listener
->Up
[0] = 0.0f
;
2478 listener
->Up
[1] = 1.0f
;
2479 listener
->Up
[2] = 0.0f
;
2481 aluMatrixfSet(&listener
->Params
.Matrix
,
2482 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2483 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2484 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2485 0.0f
, 0.0f
, 0.0f
, 1.0f
2487 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2488 listener
->Params
.Gain
= 1.0f
;
2489 listener
->Params
.MetersPerUnit
= 1.0f
;
2490 listener
->Params
.DopplerFactor
= 1.0f
;
2491 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2493 ATOMIC_INIT(&listener
->Update
, NULL
);
2494 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2497 InitRef(&Context
->UpdateCount
, 0);
2498 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2499 Context
->GainBoost
= 1.0f
;
2500 RWLockInit(&Context
->PropLock
);
2501 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2502 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2503 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2505 auxslots
= al_calloc(DEF_ALIGN
, offsetof(struct ALeffectslotArray
, slot
[0]));
2506 auxslots
->count
= 0;
2507 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2510 Context
->DistanceModel
= DefaultDistanceModel
;
2511 Context
->SourceDistanceModel
= AL_FALSE
;
2512 Context
->DopplerFactor
= 1.0f
;
2513 Context
->DopplerVelocity
= 1.0f
;
2514 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2515 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2517 Context
->ExtensionList
= alExtList
;
2523 * Cleans up the context, and destroys any remaining objects the app failed to
2524 * delete. Called once there's no more references on the context.
2526 static void FreeContext(ALCcontext
*context
)
2528 ALlistener
*listener
= context
->Listener
;
2529 struct ALeffectslotArray
*auxslots
;
2530 struct ALlistenerProps
*lprops
;
2533 TRACE("%p\n", context
);
2535 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2538 if(context
->SourceMap
.size
> 0)
2540 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2541 (context
->SourceMap
.size
==1)?"":"s");
2542 ReleaseALSources(context
);
2544 ResetUIntMap(&context
->SourceMap
);
2546 if(context
->EffectSlotMap
.size
> 0)
2548 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2549 (context
->EffectSlotMap
.size
==1)?"":"s");
2550 ReleaseALAuxiliaryEffectSlots(context
);
2552 ResetUIntMap(&context
->EffectSlotMap
);
2554 al_free(context
->Voices
);
2555 context
->Voices
= NULL
;
2556 context
->VoiceCount
= 0;
2557 context
->MaxVoices
= 0;
2559 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2561 TRACE("Freed unapplied listener update %p\n", lprops
);
2565 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2568 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2573 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2575 ALCdevice_DecRef(context
->Device
);
2576 context
->Device
= NULL
;
2578 //Invalidate context
2579 memset(context
, 0, sizeof(ALCcontext
));
2585 * Removes the context reference from the given device and removes it from
2586 * being current on the running thread or globally. Returns true if other
2587 * contexts still exist on the device.
2589 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2591 ALCcontext
*origctx
, *newhead
;
2594 if(altss_get(LocalContext
) == context
)
2596 WARN("%p released while current on thread\n", context
);
2597 altss_set(LocalContext
, NULL
);
2598 ALCcontext_DecRef(context
);
2602 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2603 ALCcontext_DecRef(context
);
2605 ALCdevice_Lock(device
);
2607 newhead
= context
->next
;
2608 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2610 ALCcontext
*volatile*list
= &origctx
->next
;
2613 if(*list
== context
)
2615 *list
= (*list
)->next
;
2618 list
= &(*list
)->next
;
2623 ALCdevice_Unlock(device
);
2625 ALCcontext_DecRef(context
);
2629 void ALCcontext_IncRef(ALCcontext
*context
)
2631 uint ref
= IncrementRef(&context
->ref
);
2632 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2635 void ALCcontext_DecRef(ALCcontext
*context
)
2637 uint ref
= DecrementRef(&context
->ref
);
2638 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2639 if(ref
== 0) FreeContext(context
);
2642 static void ReleaseThreadCtx(void *ptr
)
2644 ALCcontext
*context
= ptr
;
2645 uint ref
= DecrementRef(&context
->ref
);
2646 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2647 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2652 * Checks that the given context is valid, and increments its reference count.
2654 static ALCboolean
VerifyContext(ALCcontext
**context
)
2659 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2662 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2667 ALCcontext_IncRef(ctx
);
2684 * Returns the currently active context for this thread, and adds a reference
2685 * without locking it.
2687 ALCcontext
*GetContextRef(void)
2689 ALCcontext
*context
;
2691 context
= altss_get(LocalContext
);
2693 ALCcontext_IncRef(context
);
2697 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2699 ALCcontext_IncRef(context
);
2707 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2709 ALCdevice
*device
= context
->Device
;
2710 ALsizei num_sends
= device
->NumAuxSends
;
2711 struct ALsourceProps
*props
;
2712 size_t sizeof_props
;
2713 size_t sizeof_voice
;
2719 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2722 /* Allocate the voice pointers, voices, and the voices' stored source
2723 * property set (including the dynamically-sized Send[] array) in one
2726 sizeof_props
= RoundUp(offsetof(struct ALsourceProps
, Send
[num_sends
]), 16);
2727 sizeof_voice
= RoundUp(offsetof(ALvoice
, Send
[num_sends
]), 16);
2728 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2730 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2731 /* The voice and property objects are stored interleaved since they're
2734 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2735 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2739 ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2740 for(;v
< v_count
;v
++)
2742 ALsizei s_count
= mini(old_sends
, num_sends
);
2745 /* Copy the old voice data and source property set to the new
2748 *voice
= *(context
->Voices
[v
]);
2749 for(i
= 0;i
< s_count
;i
++)
2750 voice
->Send
[i
] = context
->Voices
[v
]->Send
[i
];
2751 *props
= *(context
->Voices
[v
]->Props
);
2752 for(i
= 0;i
< s_count
;i
++)
2753 props
->Send
[i
] = context
->Voices
[v
]->Props
->Send
[i
];
2755 /* Set this voice's property set pointer and voice reference. */
2756 voice
->Props
= props
;
2759 /* Increment pointers to the next storage space. */
2760 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2761 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2764 /* Finish setting the voices' property set pointers and references. */
2765 for(;v
< num_voices
;v
++)
2767 voice
->Props
= props
;
2770 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2771 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2774 al_free(context
->Voices
);
2775 context
->Voices
= voices
;
2776 context
->MaxVoices
= num_voices
;
2777 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2781 /************************************************
2782 * Standard ALC functions
2783 ************************************************/
2787 * Return last ALC generated error code for the given device
2789 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2793 if(VerifyDevice(&device
))
2795 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2796 ALCdevice_DecRef(device
);
2799 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2805 /* alcSuspendContext
2807 * Suspends updates for the given context
2809 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2814 if(!VerifyContext(&context
))
2815 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2818 ALCcontext_DeferUpdates(context
);
2819 ALCcontext_DecRef(context
);
2823 /* alcProcessContext
2825 * Resumes processing updates for the given context
2827 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2832 if(!VerifyContext(&context
))
2833 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2836 ALCcontext_ProcessUpdates(context
);
2837 ALCcontext_DecRef(context
);
2844 * Returns information about the device, and error strings
2846 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2848 const ALCchar
*value
= NULL
;
2856 case ALC_INVALID_ENUM
:
2857 value
= alcErrInvalidEnum
;
2860 case ALC_INVALID_VALUE
:
2861 value
= alcErrInvalidValue
;
2864 case ALC_INVALID_DEVICE
:
2865 value
= alcErrInvalidDevice
;
2868 case ALC_INVALID_CONTEXT
:
2869 value
= alcErrInvalidContext
;
2872 case ALC_OUT_OF_MEMORY
:
2873 value
= alcErrOutOfMemory
;
2876 case ALC_DEVICE_SPECIFIER
:
2877 value
= alcDefaultName
;
2880 case ALC_ALL_DEVICES_SPECIFIER
:
2881 if(VerifyDevice(&Device
))
2883 value
= alstr_get_cstr(Device
->DeviceName
);
2884 ALCdevice_DecRef(Device
);
2888 ProbeAllDevicesList();
2889 value
= alstr_get_cstr(alcAllDevicesList
);
2893 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2894 if(VerifyDevice(&Device
))
2896 value
= alstr_get_cstr(Device
->DeviceName
);
2897 ALCdevice_DecRef(Device
);
2901 ProbeCaptureDeviceList();
2902 value
= alstr_get_cstr(alcCaptureDeviceList
);
2906 /* Default devices are always first in the list */
2907 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2908 value
= alcDefaultName
;
2911 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2912 if(alstr_empty(alcAllDevicesList
))
2913 ProbeAllDevicesList();
2915 VerifyDevice(&Device
);
2917 free(alcDefaultAllDevicesSpecifier
);
2918 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
2919 if(!alcDefaultAllDevicesSpecifier
)
2920 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2922 value
= alcDefaultAllDevicesSpecifier
;
2923 if(Device
) ALCdevice_DecRef(Device
);
2926 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2927 if(alstr_empty(alcCaptureDeviceList
))
2928 ProbeCaptureDeviceList();
2930 VerifyDevice(&Device
);
2932 free(alcCaptureDefaultDeviceSpecifier
);
2933 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
2934 if(!alcCaptureDefaultDeviceSpecifier
)
2935 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2937 value
= alcCaptureDefaultDeviceSpecifier
;
2938 if(Device
) ALCdevice_DecRef(Device
);
2941 case ALC_EXTENSIONS
:
2942 if(!VerifyDevice(&Device
))
2943 value
= alcNoDeviceExtList
;
2946 value
= alcExtensionList
;
2947 ALCdevice_DecRef(Device
);
2951 case ALC_HRTF_SPECIFIER_SOFT
:
2952 if(!VerifyDevice(&Device
))
2953 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2956 almtx_lock(&Device
->BackendLock
);
2957 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
2958 almtx_unlock(&Device
->BackendLock
);
2959 ALCdevice_DecRef(Device
);
2964 VerifyDevice(&Device
);
2965 alcSetError(Device
, ALC_INVALID_ENUM
);
2966 if(Device
) ALCdevice_DecRef(Device
);
2974 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2976 if(device
->Type
== Loopback
&& device
->FmtChans
== DevFmtAmbi3D
)
2981 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2985 if(size
<= 0 || values
== NULL
)
2987 alcSetError(device
, ALC_INVALID_VALUE
);
2995 case ALC_MAJOR_VERSION
:
2996 values
[0] = alcMajorVersion
;
2998 case ALC_MINOR_VERSION
:
2999 values
[0] = alcMinorVersion
;
3002 case ALC_ATTRIBUTES_SIZE
:
3003 case ALC_ALL_ATTRIBUTES
:
3007 case ALC_MONO_SOURCES
:
3008 case ALC_STEREO_SOURCES
:
3009 case ALC_CAPTURE_SAMPLES
:
3010 case ALC_FORMAT_CHANNELS_SOFT
:
3011 case ALC_FORMAT_TYPE_SOFT
:
3012 case ALC_AMBISONIC_LAYOUT_SOFT
:
3013 case ALC_AMBISONIC_SCALING_SOFT
:
3014 case ALC_AMBISONIC_ORDER_SOFT
:
3015 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3019 alcSetError(NULL
, ALC_INVALID_ENUM
);
3025 if(device
->Type
== Capture
)
3029 case ALC_CAPTURE_SAMPLES
:
3030 almtx_lock(&device
->BackendLock
);
3031 values
[0] = V0(device
->Backend
,availableSamples
)();
3032 almtx_unlock(&device
->BackendLock
);
3036 values
[0] = device
->Connected
;
3040 alcSetError(device
, ALC_INVALID_ENUM
);
3049 case ALC_MAJOR_VERSION
:
3050 values
[0] = alcMajorVersion
;
3053 case ALC_MINOR_VERSION
:
3054 values
[0] = alcMinorVersion
;
3057 case ALC_EFX_MAJOR_VERSION
:
3058 values
[0] = alcEFXMajorVersion
;
3061 case ALC_EFX_MINOR_VERSION
:
3062 values
[0] = alcEFXMinorVersion
;
3065 case ALC_ATTRIBUTES_SIZE
:
3066 values
[0] = NumAttrsForDevice(device
);
3069 case ALC_ALL_ATTRIBUTES
:
3070 if(size
< NumAttrsForDevice(device
))
3072 alcSetError(device
, ALC_INVALID_VALUE
);
3077 almtx_lock(&device
->BackendLock
);
3078 values
[i
++] = ALC_FREQUENCY
;
3079 values
[i
++] = device
->Frequency
;
3081 if(device
->Type
!= Loopback
)
3083 values
[i
++] = ALC_REFRESH
;
3084 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3086 values
[i
++] = ALC_SYNC
;
3087 values
[i
++] = ALC_FALSE
;
3091 if(device
->FmtChans
== DevFmtAmbi3D
)
3093 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3094 values
[i
++] = device
->AmbiLayout
;
3096 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3097 values
[i
++] = device
->AmbiScale
;
3099 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3100 values
[i
++] = device
->AmbiOrder
;
3103 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3104 values
[i
++] = device
->FmtChans
;
3106 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3107 values
[i
++] = device
->FmtType
;
3110 values
[i
++] = ALC_MONO_SOURCES
;
3111 values
[i
++] = device
->NumMonoSources
;
3113 values
[i
++] = ALC_STEREO_SOURCES
;
3114 values
[i
++] = device
->NumStereoSources
;
3116 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3117 values
[i
++] = device
->NumAuxSends
;
3119 values
[i
++] = ALC_HRTF_SOFT
;
3120 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3122 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3123 values
[i
++] = device
->HrtfStatus
;
3124 almtx_unlock(&device
->BackendLock
);
3130 values
[0] = device
->Frequency
;
3134 if(device
->Type
== Loopback
)
3136 alcSetError(device
, ALC_INVALID_DEVICE
);
3139 almtx_lock(&device
->BackendLock
);
3140 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3141 almtx_unlock(&device
->BackendLock
);
3145 if(device
->Type
== Loopback
)
3147 alcSetError(device
, ALC_INVALID_DEVICE
);
3150 values
[0] = ALC_FALSE
;
3153 case ALC_FORMAT_CHANNELS_SOFT
:
3154 if(device
->Type
!= Loopback
)
3156 alcSetError(device
, ALC_INVALID_DEVICE
);
3159 values
[0] = device
->FmtChans
;
3162 case ALC_FORMAT_TYPE_SOFT
:
3163 if(device
->Type
!= Loopback
)
3165 alcSetError(device
, ALC_INVALID_DEVICE
);
3168 values
[0] = device
->FmtType
;
3171 case ALC_AMBISONIC_LAYOUT_SOFT
:
3172 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3174 alcSetError(device
, ALC_INVALID_DEVICE
);
3177 values
[0] = device
->AmbiLayout
;
3180 case ALC_AMBISONIC_SCALING_SOFT
:
3181 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3183 alcSetError(device
, ALC_INVALID_DEVICE
);
3186 values
[0] = device
->AmbiScale
;
3189 case ALC_AMBISONIC_ORDER_SOFT
:
3190 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3192 alcSetError(device
, ALC_INVALID_DEVICE
);
3195 values
[0] = device
->AmbiOrder
;
3198 case ALC_MONO_SOURCES
:
3199 values
[0] = device
->NumMonoSources
;
3202 case ALC_STEREO_SOURCES
:
3203 values
[0] = device
->NumStereoSources
;
3206 case ALC_MAX_AUXILIARY_SENDS
:
3207 values
[0] = device
->NumAuxSends
;
3211 values
[0] = device
->Connected
;
3215 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3218 case ALC_HRTF_STATUS_SOFT
:
3219 values
[0] = device
->HrtfStatus
;
3222 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3223 almtx_lock(&device
->BackendLock
);
3224 FreeHrtfList(&device
->HrtfList
);
3225 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3226 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3227 almtx_unlock(&device
->BackendLock
);
3231 alcSetError(device
, ALC_INVALID_ENUM
);
3239 * Returns information about the device and the version of OpenAL
3241 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3243 VerifyDevice(&device
);
3244 if(size
<= 0 || values
== NULL
)
3245 alcSetError(device
, ALC_INVALID_VALUE
);
3247 GetIntegerv(device
, param
, size
, values
);
3248 if(device
) ALCdevice_DecRef(device
);
3251 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3256 VerifyDevice(&device
);
3257 if(size
<= 0 || values
== NULL
)
3258 alcSetError(device
, ALC_INVALID_VALUE
);
3259 else if(!device
|| device
->Type
== Capture
)
3261 ivals
= malloc(size
* sizeof(ALCint
));
3262 size
= GetIntegerv(device
, pname
, size
, ivals
);
3263 for(i
= 0;i
< size
;i
++)
3264 values
[i
] = ivals
[i
];
3267 else /* render device */
3276 case ALC_ATTRIBUTES_SIZE
:
3277 *values
= NumAttrsForDevice(device
)+4;
3280 case ALC_ALL_ATTRIBUTES
:
3281 if(size
< NumAttrsForDevice(device
)+4)
3282 alcSetError(device
, ALC_INVALID_VALUE
);
3286 almtx_lock(&device
->BackendLock
);
3287 values
[i
++] = ALC_FREQUENCY
;
3288 values
[i
++] = device
->Frequency
;
3290 if(device
->Type
!= Loopback
)
3292 values
[i
++] = ALC_REFRESH
;
3293 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3295 values
[i
++] = ALC_SYNC
;
3296 values
[i
++] = ALC_FALSE
;
3300 if(device
->FmtChans
== DevFmtAmbi3D
)
3302 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3303 values
[i
++] = device
->AmbiLayout
;
3305 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3306 values
[i
++] = device
->AmbiScale
;
3308 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3309 values
[i
++] = device
->AmbiOrder
;
3312 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3313 values
[i
++] = device
->FmtChans
;
3315 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3316 values
[i
++] = device
->FmtType
;
3319 values
[i
++] = ALC_MONO_SOURCES
;
3320 values
[i
++] = device
->NumMonoSources
;
3322 values
[i
++] = ALC_STEREO_SOURCES
;
3323 values
[i
++] = device
->NumStereoSources
;
3325 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3326 values
[i
++] = device
->NumAuxSends
;
3328 values
[i
++] = ALC_HRTF_SOFT
;
3329 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3331 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3332 values
[i
++] = device
->HrtfStatus
;
3334 clock
= V0(device
->Backend
,getClockLatency
)();
3335 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3336 values
[i
++] = clock
.ClockTime
;
3338 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3339 values
[i
++] = clock
.Latency
;
3340 almtx_unlock(&device
->BackendLock
);
3346 case ALC_DEVICE_CLOCK_SOFT
:
3347 almtx_lock(&device
->BackendLock
);
3349 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3351 basecount
= device
->ClockBase
;
3352 samplecount
= device
->SamplesDone
;
3353 } while(refcount
!= ReadRef(&device
->MixCount
));
3354 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3355 almtx_unlock(&device
->BackendLock
);
3358 case ALC_DEVICE_LATENCY_SOFT
:
3359 almtx_lock(&device
->BackendLock
);
3360 clock
= V0(device
->Backend
,getClockLatency
)();
3361 almtx_unlock(&device
->BackendLock
);
3362 *values
= clock
.Latency
;
3365 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3367 alcSetError(device
, ALC_INVALID_VALUE
);
3370 almtx_lock(&device
->BackendLock
);
3371 clock
= V0(device
->Backend
,getClockLatency
)();
3372 almtx_unlock(&device
->BackendLock
);
3373 values
[0] = clock
.ClockTime
;
3374 values
[1] = clock
.Latency
;
3379 ivals
= malloc(size
* sizeof(ALCint
));
3380 size
= GetIntegerv(device
, pname
, size
, ivals
);
3381 for(i
= 0;i
< size
;i
++)
3382 values
[i
] = ivals
[i
];
3388 ALCdevice_DecRef(device
);
3392 /* alcIsExtensionPresent
3394 * Determines if there is support for a particular extension
3396 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3398 ALCboolean bResult
= ALC_FALSE
;
3400 VerifyDevice(&device
);
3403 alcSetError(device
, ALC_INVALID_VALUE
);
3406 size_t len
= strlen(extName
);
3407 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3410 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3411 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3416 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3420 } while(isspace(*ptr
));
3425 ALCdevice_DecRef(device
);
3430 /* alcGetProcAddress
3432 * Retrieves the function address for a particular extension function
3434 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3436 ALCvoid
*ptr
= NULL
;
3440 VerifyDevice(&device
);
3441 alcSetError(device
, ALC_INVALID_VALUE
);
3442 if(device
) ALCdevice_DecRef(device
);
3447 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3449 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3451 ptr
= alcFunctions
[i
].address
;
3463 * Get the value for a particular ALC enumeration name
3465 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3471 VerifyDevice(&device
);
3472 alcSetError(device
, ALC_INVALID_VALUE
);
3473 if(device
) ALCdevice_DecRef(device
);
3478 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3480 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3482 val
= alcEnumerations
[i
].value
;
3494 * Create and attach a context to the given device.
3496 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3498 ALCcontext
*ALContext
;
3502 /* Explicitly hold the list lock while taking the BackendLock in case the
3503 * device is asynchronously destropyed, to ensure this new context is
3504 * properly cleaned up after being made.
3507 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3510 alcSetError(device
, ALC_INVALID_DEVICE
);
3511 if(device
) ALCdevice_DecRef(device
);
3514 almtx_lock(&device
->BackendLock
);
3517 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3519 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3522 InitRef(&ALContext
->ref
, 1);
3523 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3525 ALContext
->Device
= device
;
3526 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3528 ALContext
->Voices
= NULL
;
3529 ALContext
->MaxVoices
= 0;
3530 ALContext
->VoiceCount
= 0;
3531 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3533 if(!ALContext
|| !ALContext
->Voices
)
3535 almtx_unlock(&device
->BackendLock
);
3539 al_free(ALContext
->Voices
);
3540 ALContext
->Voices
= NULL
;
3546 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3547 ALCdevice_DecRef(device
);
3551 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3553 almtx_unlock(&device
->BackendLock
);
3555 al_free(ALContext
->Voices
);
3556 ALContext
->Voices
= NULL
;
3561 alcSetError(device
, err
);
3562 if(err
== ALC_INVALID_DEVICE
)
3564 V0(device
->Backend
,lock
)();
3565 aluHandleDisconnect(device
);
3566 V0(device
->Backend
,unlock
)();
3568 ALCdevice_DecRef(device
);
3572 ALCdevice_IncRef(ALContext
->Device
);
3573 InitContext(ALContext
);
3575 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3578 ERR("volume-adjust must be finite: %f\n", valf
);
3581 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3583 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3584 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3585 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3588 UpdateListenerProps(ALContext
);
3591 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3593 ALContext
->next
= head
;
3594 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3597 almtx_unlock(&device
->BackendLock
);
3599 ALCdevice_DecRef(device
);
3601 TRACE("Created context %p\n", ALContext
);
3605 /* alcDestroyContext
3607 * Remove a context from its device
3609 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3614 if(!VerifyContext(&context
))
3617 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3621 Device
= context
->Device
;
3624 almtx_lock(&Device
->BackendLock
);
3625 if(!ReleaseContext(context
, Device
))
3627 V0(Device
->Backend
,stop
)();
3628 Device
->Flags
&= ~DEVICE_RUNNING
;
3630 almtx_unlock(&Device
->BackendLock
);
3634 ALCcontext_DecRef(context
);
3638 /* alcGetCurrentContext
3640 * Returns the currently active context on the calling thread
3642 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3644 ALCcontext
*Context
= altss_get(LocalContext
);
3645 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3649 /* alcGetThreadContext
3651 * Returns the currently active thread-local context
3653 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3655 return altss_get(LocalContext
);
3659 /* alcMakeContextCurrent
3661 * Makes the given context the active process-wide context, and removes the
3662 * thread-local context for the calling thread.
3664 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3666 /* context must be valid or NULL */
3667 if(context
&& !VerifyContext(&context
))
3669 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3672 /* context's reference count is already incremented */
3673 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3674 if(context
) ALCcontext_DecRef(context
);
3676 if((context
=altss_get(LocalContext
)) != NULL
)
3678 altss_set(LocalContext
, NULL
);
3679 ALCcontext_DecRef(context
);
3685 /* alcSetThreadContext
3687 * Makes the given context the active context for the current thread
3689 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3693 /* context must be valid or NULL */
3694 if(context
&& !VerifyContext(&context
))
3696 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3699 /* context's reference count is already incremented */
3700 old
= altss_get(LocalContext
);
3701 altss_set(LocalContext
, context
);
3702 if(old
) ALCcontext_DecRef(old
);
3708 /* alcGetContextsDevice
3710 * Returns the device that a particular context is attached to
3712 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3716 if(!VerifyContext(&Context
))
3718 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3721 Device
= Context
->Device
;
3722 ALCcontext_DecRef(Context
);
3730 * Opens the named device.
3732 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3741 if(!PlaybackBackend
.name
)
3743 alcSetError(NULL
, ALC_INVALID_VALUE
);
3747 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3749 /* Some old Windows apps hardcode these expecting OpenAL to use a
3750 * specific audio API, even when they're not enumerated. Creative's
3751 * router effectively ignores them too.
3753 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3754 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3759 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3762 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3767 InitRef(&device
->ref
, 1);
3768 device
->Connected
= ALC_TRUE
;
3769 device
->Type
= Playback
;
3770 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3773 device
->Bs2b
= NULL
;
3774 device
->Uhj_Encoder
= NULL
;
3775 device
->Hrtf
= NULL
;
3776 device
->HrtfHandle
= NULL
;
3777 VECTOR_INIT(device
->HrtfList
);
3778 AL_STRING_INIT(device
->HrtfName
);
3779 device
->Render_Mode
= NormalRender
;
3780 AL_STRING_INIT(device
->DeviceName
);
3781 device
->Dry
.Buffer
= NULL
;
3782 device
->Dry
.NumChannels
= 0;
3783 device
->FOAOut
.Buffer
= NULL
;
3784 device
->FOAOut
.NumChannels
= 0;
3785 device
->RealOut
.Buffer
= NULL
;
3786 device
->RealOut
.NumChannels
= 0;
3787 device
->AvgSpeakerDist
= 0.0f
;
3789 ATOMIC_INIT(&device
->ContextList
, NULL
);
3791 device
->ClockBase
= 0;
3792 device
->SamplesDone
= 0;
3794 device
->SourcesMax
= 256;
3795 device
->AuxiliaryEffectSlotMax
= 64;
3796 device
->NumAuxSends
= DEFAULT_SENDS
;
3798 InitUIntMap(&device
->BufferMap
, INT_MAX
);
3799 InitUIntMap(&device
->EffectMap
, INT_MAX
);
3800 InitUIntMap(&device
->FilterMap
, INT_MAX
);
3802 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3804 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3805 device
->ChannelDelay
[i
].Length
= 0;
3806 device
->ChannelDelay
[i
].Buffer
= NULL
;
3810 device
->FmtChans
= DevFmtChannelsDefault
;
3811 device
->FmtType
= DevFmtTypeDefault
;
3812 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3813 device
->IsHeadphones
= AL_FALSE
;
3814 device
->AmbiLayout
= AmbiLayout_Default
;
3815 device
->AmbiScale
= AmbiNorm_Default
;
3816 device
->NumUpdates
= 3;
3817 device
->UpdateSize
= 1024;
3819 if(!PlaybackBackend
.getFactory
)
3820 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3821 ALCbackend_Playback
);
3824 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3825 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3827 if(!device
->Backend
)
3830 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3835 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3837 static const struct {
3838 const char name
[16];
3839 enum DevFmtChannels chans
;
3842 { "mono", DevFmtMono
, 0 },
3843 { "stereo", DevFmtStereo
, 0 },
3844 { "quad", DevFmtQuad
, 0 },
3845 { "surround51", DevFmtX51
, 0 },
3846 { "surround61", DevFmtX61
, 0 },
3847 { "surround71", DevFmtX71
, 0 },
3848 { "surround51rear", DevFmtX51Rear
, 0 },
3849 { "ambi1", DevFmtAmbi3D
, 1 },
3850 { "ambi2", DevFmtAmbi3D
, 2 },
3851 { "ambi3", DevFmtAmbi3D
, 3 },
3855 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3857 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3859 device
->FmtChans
= chanlist
[i
].chans
;
3860 device
->AmbiOrder
= chanlist
[i
].order
;
3861 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3865 if(i
== COUNTOF(chanlist
))
3866 ERR("Unsupported channels: %s\n", fmt
);
3868 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3870 static const struct {
3871 const char name
[16];
3872 enum DevFmtType type
;
3874 { "int8", DevFmtByte
},
3875 { "uint8", DevFmtUByte
},
3876 { "int16", DevFmtShort
},
3877 { "uint16", DevFmtUShort
},
3878 { "int32", DevFmtInt
},
3879 { "uint32", DevFmtUInt
},
3880 { "float32", DevFmtFloat
},
3884 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3886 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3888 device
->FmtType
= typelist
[i
].type
;
3889 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3893 if(i
== COUNTOF(typelist
))
3894 ERR("Unsupported sample-type: %s\n", fmt
);
3897 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3899 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3900 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3901 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3902 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3905 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3906 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3908 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3909 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3910 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3911 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3913 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3914 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3916 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3917 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3919 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3920 device
->NumAuxSends
= clampi(
3921 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3924 device
->NumStereoSources
= 1;
3925 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3927 // Find a playback device to open
3928 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3930 DELETE_OBJ(device
->Backend
);
3932 alcSetError(NULL
, err
);
3935 almtx_init(&device
->BackendLock
, almtx_plain
);
3937 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3939 if(strcasecmp(fmt
, "fuma") == 0)
3941 device
->AmbiLayout
= AmbiLayout_FuMa
;
3942 device
->AmbiScale
= AmbiNorm_FuMa
;
3944 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3946 device
->AmbiLayout
= AmbiLayout_ACN
;
3947 device
->AmbiScale
= AmbiNorm_SN3D
;
3949 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3951 device
->AmbiLayout
= AmbiLayout_ACN
;
3952 device
->AmbiScale
= AmbiNorm_N3D
;
3955 ERR("Unsupported ambi-format: %s\n", fmt
);
3958 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3960 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3961 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3963 device
->DefaultSlot
= NULL
;
3964 ERR("Failed to initialize the default effect slot\n");
3968 aluInitEffectPanning(device
->DefaultSlot
);
3969 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3971 DeinitEffectSlot(device
->DefaultSlot
);
3972 device
->DefaultSlot
= NULL
;
3973 ERR("Failed to initialize the default effect\n");
3979 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
3981 device
->next
= head
;
3982 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
3985 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
3991 * Closes the given device.
3993 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3995 ALCdevice
*iter
, *origdev
;
3999 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4003 } while((iter
=iter
->next
) != NULL
);
4004 if(!iter
|| iter
->Type
== Capture
)
4006 alcSetError(iter
, ALC_INVALID_DEVICE
);
4010 almtx_lock(&device
->BackendLock
);
4013 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4015 ALCdevice
*volatile*list
= &origdev
->next
;
4020 *list
= (*list
)->next
;
4023 list
= &(*list
)->next
;
4028 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4031 ALCcontext
*next
= ctx
->next
;
4032 WARN("Releasing context %p\n", ctx
);
4033 ReleaseContext(ctx
, device
);
4036 if((device
->Flags
&DEVICE_RUNNING
))
4037 V0(device
->Backend
,stop
)();
4038 device
->Flags
&= ~DEVICE_RUNNING
;
4039 almtx_unlock(&device
->BackendLock
);
4041 ALCdevice_DecRef(device
);
4047 /************************************************
4048 * ALC capture functions
4049 ************************************************/
4050 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4052 ALCdevice
*device
= NULL
;
4058 if(!CaptureBackend
.name
)
4060 alcSetError(NULL
, ALC_INVALID_VALUE
);
4066 alcSetError(NULL
, ALC_INVALID_VALUE
);
4070 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4073 device
= al_calloc(16, sizeof(ALCdevice
));
4076 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4081 InitRef(&device
->ref
, 1);
4082 device
->Connected
= ALC_TRUE
;
4083 device
->Type
= Capture
;
4085 device
->Hrtf
= NULL
;
4086 device
->HrtfHandle
= NULL
;
4087 VECTOR_INIT(device
->HrtfList
);
4088 AL_STRING_INIT(device
->HrtfName
);
4090 AL_STRING_INIT(device
->DeviceName
);
4091 device
->Dry
.Buffer
= NULL
;
4092 device
->Dry
.NumChannels
= 0;
4093 device
->FOAOut
.Buffer
= NULL
;
4094 device
->FOAOut
.NumChannels
= 0;
4095 device
->RealOut
.Buffer
= NULL
;
4096 device
->RealOut
.NumChannels
= 0;
4098 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4099 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4100 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4102 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4104 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4105 device
->ChannelDelay
[i
].Length
= 0;
4106 device
->ChannelDelay
[i
].Buffer
= NULL
;
4109 if(!CaptureBackend
.getFactory
)
4110 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4111 ALCbackend_Capture
);
4114 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4115 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4117 if(!device
->Backend
)
4120 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4124 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4125 device
->Frequency
= frequency
;
4127 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4128 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4131 alcSetError(NULL
, ALC_INVALID_ENUM
);
4134 device
->IsHeadphones
= AL_FALSE
;
4135 device
->AmbiOrder
= 0;
4136 device
->AmbiLayout
= AmbiLayout_Default
;
4137 device
->AmbiScale
= AmbiNorm_Default
;
4139 device
->UpdateSize
= samples
;
4140 device
->NumUpdates
= 1;
4142 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4143 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4144 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4146 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4149 alcSetError(NULL
, err
);
4152 almtx_init(&device
->BackendLock
, almtx_plain
);
4155 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4157 device
->next
= head
;
4158 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4161 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4165 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4167 ALCdevice
*iter
, *origdev
;
4170 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4174 } while((iter
=iter
->next
) != NULL
);
4175 if(!iter
|| iter
->Type
!= Capture
)
4177 alcSetError(iter
, ALC_INVALID_DEVICE
);
4183 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4185 ALCdevice
*volatile*list
= &origdev
->next
;
4190 *list
= (*list
)->next
;
4193 list
= &(*list
)->next
;
4198 ALCdevice_DecRef(device
);
4203 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4205 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4206 alcSetError(device
, ALC_INVALID_DEVICE
);
4209 almtx_lock(&device
->BackendLock
);
4210 if(!device
->Connected
)
4211 alcSetError(device
, ALC_INVALID_DEVICE
);
4212 else if(!(device
->Flags
&DEVICE_RUNNING
))
4214 if(V0(device
->Backend
,start
)())
4215 device
->Flags
|= DEVICE_RUNNING
;
4218 aluHandleDisconnect(device
);
4219 alcSetError(device
, ALC_INVALID_DEVICE
);
4222 almtx_unlock(&device
->BackendLock
);
4225 if(device
) ALCdevice_DecRef(device
);
4228 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4230 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4231 alcSetError(device
, ALC_INVALID_DEVICE
);
4234 almtx_lock(&device
->BackendLock
);
4235 if((device
->Flags
&DEVICE_RUNNING
))
4236 V0(device
->Backend
,stop
)();
4237 device
->Flags
&= ~DEVICE_RUNNING
;
4238 almtx_unlock(&device
->BackendLock
);
4241 if(device
) ALCdevice_DecRef(device
);
4244 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4246 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4247 alcSetError(device
, ALC_INVALID_DEVICE
);
4250 ALCenum err
= ALC_INVALID_VALUE
;
4252 almtx_lock(&device
->BackendLock
);
4253 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4254 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4255 almtx_unlock(&device
->BackendLock
);
4257 if(err
!= ALC_NO_ERROR
)
4258 alcSetError(device
, err
);
4260 if(device
) ALCdevice_DecRef(device
);
4264 /************************************************
4265 * ALC loopback functions
4266 ************************************************/
4268 /* alcLoopbackOpenDeviceSOFT
4270 * Open a loopback device, for manual rendering.
4272 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4274 ALCbackendFactory
*factory
;
4280 /* Make sure the device name, if specified, is us. */
4281 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4283 alcSetError(NULL
, ALC_INVALID_VALUE
);
4287 device
= al_calloc(16, sizeof(ALCdevice
));
4290 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4295 InitRef(&device
->ref
, 1);
4296 device
->Connected
= ALC_TRUE
;
4297 device
->Type
= Loopback
;
4298 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4301 device
->Hrtf
= NULL
;
4302 device
->HrtfHandle
= NULL
;
4303 VECTOR_INIT(device
->HrtfList
);
4304 AL_STRING_INIT(device
->HrtfName
);
4305 device
->Bs2b
= NULL
;
4306 device
->Uhj_Encoder
= NULL
;
4307 device
->Render_Mode
= NormalRender
;
4308 AL_STRING_INIT(device
->DeviceName
);
4309 device
->Dry
.Buffer
= NULL
;
4310 device
->Dry
.NumChannels
= 0;
4311 device
->FOAOut
.Buffer
= NULL
;
4312 device
->FOAOut
.NumChannels
= 0;
4313 device
->RealOut
.Buffer
= NULL
;
4314 device
->RealOut
.NumChannels
= 0;
4315 device
->AvgSpeakerDist
= 0.0f
;
4317 ATOMIC_INIT(&device
->ContextList
, NULL
);
4319 device
->ClockBase
= 0;
4320 device
->SamplesDone
= 0;
4322 device
->SourcesMax
= 256;
4323 device
->AuxiliaryEffectSlotMax
= 64;
4324 device
->NumAuxSends
= DEFAULT_SENDS
;
4326 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4327 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4328 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4330 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4332 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4333 device
->ChannelDelay
[i
].Length
= 0;
4334 device
->ChannelDelay
[i
].Buffer
= NULL
;
4337 factory
= ALCloopbackFactory_getFactory();
4338 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4339 if(!device
->Backend
)
4342 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4345 almtx_init(&device
->BackendLock
, almtx_plain
);
4348 device
->NumUpdates
= 0;
4349 device
->UpdateSize
= 0;
4351 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4352 device
->FmtChans
= DevFmtChannelsDefault
;
4353 device
->FmtType
= DevFmtTypeDefault
;
4354 device
->IsHeadphones
= AL_FALSE
;
4355 device
->AmbiLayout
= AmbiLayout_Default
;
4356 device
->AmbiScale
= AmbiNorm_Default
;
4358 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4359 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4361 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4362 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4364 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4365 device
->NumAuxSends
= clampi(
4366 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4369 device
->NumStereoSources
= 1;
4370 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4372 // Open the "backend"
4373 V(device
->Backend
,open
)("Loopback");
4376 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4378 device
->next
= head
;
4379 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4382 TRACE("Created device %p\n", device
);
4386 /* alcIsRenderFormatSupportedSOFT
4388 * Determines if the loopback device supports the given format for rendering.
4390 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4392 ALCboolean ret
= ALC_FALSE
;
4394 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4395 alcSetError(device
, ALC_INVALID_DEVICE
);
4397 alcSetError(device
, ALC_INVALID_VALUE
);
4400 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4403 if(device
) ALCdevice_DecRef(device
);
4408 /* alcRenderSamplesSOFT
4410 * Renders some samples into a buffer, using the format last set by the
4411 * attributes given to alcCreateContext.
4413 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4415 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4416 alcSetError(device
, ALC_INVALID_DEVICE
);
4417 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4418 alcSetError(device
, ALC_INVALID_VALUE
);
4421 V0(device
->Backend
,lock
)();
4422 aluMixData(device
, buffer
, samples
);
4423 V0(device
->Backend
,unlock
)();
4425 if(device
) ALCdevice_DecRef(device
);
4429 /************************************************
4430 * ALC loopback2 functions
4431 ************************************************/
4433 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4435 ALCboolean ret
= ALC_FALSE
;
4437 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4438 alcSetError(device
, ALC_INVALID_DEVICE
);
4440 alcSetError(device
, ALC_INVALID_VALUE
);
4443 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4446 if(device
) ALCdevice_DecRef(device
);
4451 /************************************************
4452 * ALC DSP pause/resume functions
4453 ************************************************/
4455 /* alcDevicePauseSOFT
4457 * Pause the DSP to stop audio processing.
4459 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4461 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4462 alcSetError(device
, ALC_INVALID_DEVICE
);
4465 almtx_lock(&device
->BackendLock
);
4466 if((device
->Flags
&DEVICE_RUNNING
))
4467 V0(device
->Backend
,stop
)();
4468 device
->Flags
&= ~DEVICE_RUNNING
;
4469 device
->Flags
|= DEVICE_PAUSED
;
4470 almtx_unlock(&device
->BackendLock
);
4472 if(device
) ALCdevice_DecRef(device
);
4475 /* alcDeviceResumeSOFT
4477 * Resume the DSP to restart audio processing.
4479 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4481 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4482 alcSetError(device
, ALC_INVALID_DEVICE
);
4485 almtx_lock(&device
->BackendLock
);
4486 if((device
->Flags
&DEVICE_PAUSED
))
4488 device
->Flags
&= ~DEVICE_PAUSED
;
4489 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4491 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4492 device
->Flags
|= DEVICE_RUNNING
;
4495 alcSetError(device
, ALC_INVALID_DEVICE
);
4496 V0(device
->Backend
,lock
)();
4497 aluHandleDisconnect(device
);
4498 V0(device
->Backend
,unlock
)();
4502 almtx_unlock(&device
->BackendLock
);
4504 if(device
) ALCdevice_DecRef(device
);
4508 /************************************************
4509 * ALC HRTF functions
4510 ************************************************/
4512 /* alcGetStringiSOFT
4514 * Gets a string parameter at the given index.
4516 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4518 const ALCchar
*str
= NULL
;
4520 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4521 alcSetError(device
, ALC_INVALID_DEVICE
);
4522 else switch(paramName
)
4524 case ALC_HRTF_SPECIFIER_SOFT
:
4525 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4526 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4528 alcSetError(device
, ALC_INVALID_VALUE
);
4532 alcSetError(device
, ALC_INVALID_ENUM
);
4535 if(device
) ALCdevice_DecRef(device
);
4540 /* alcResetDeviceSOFT
4542 * Resets the given device output, using the specified attribute list.
4544 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4549 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4552 alcSetError(device
, ALC_INVALID_DEVICE
);
4553 if(device
) ALCdevice_DecRef(device
);
4556 almtx_lock(&device
->BackendLock
);
4559 err
= UpdateDeviceParams(device
, attribs
);
4560 almtx_unlock(&device
->BackendLock
);
4562 if(err
!= ALC_NO_ERROR
)
4564 alcSetError(device
, err
);
4565 if(err
== ALC_INVALID_DEVICE
)
4567 V0(device
->Backend
,lock
)();
4568 aluHandleDisconnect(device
);
4569 V0(device
->Backend
,unlock
)();
4571 ALCdevice_DecRef(device
);
4574 ALCdevice_DecRef(device
);