2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
40 #include "bformatdec.h"
48 #include "backends/base.h"
51 /************************************************
53 ************************************************/
56 ALCbackendFactory
* (*getFactory
)(void);
57 ALCboolean (*Init
)(BackendFuncs
*);
59 void (*Probe
)(enum DevProbe
);
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList
[] = {
66 { "jack", ALCjackBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
72 { "alsa", ALCalsaBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
75 { "core", NULL
, alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, EmptyFuncs
},
78 { "oss", ALCossBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
81 { "solaris", ALCsolarisBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
84 { "sndio", ALCsndioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
87 { "qsa", NULL
, alc_qsa_init
, alc_qsa_deinit
, alc_qsa_probe
, EmptyFuncs
},
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
93 { "dsound", ALCdsoundBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
96 { "winmm", ALCwinmmBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
99 { "port", ALCportBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
102 { "opensl", ALCopenslBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
105 { "null", ALCnullBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
107 { "wave", ALCwaveBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
110 static ALsizei BackendListSize
= COUNTOF(BackendList
);
113 static struct BackendInfo PlaybackBackend
;
114 static struct BackendInfo CaptureBackend
;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 typedef struct ALCfunction
{
121 const ALCchar
*funcName
;
125 typedef struct ALCenums
{
126 const ALCchar
*enumName
;
130 #define DECL(x) { #x, (ALCvoid*)(x) }
131 static const ALCfunction alcFunctions
[] = {
132 DECL(alcCreateContext
),
133 DECL(alcMakeContextCurrent
),
134 DECL(alcProcessContext
),
135 DECL(alcSuspendContext
),
136 DECL(alcDestroyContext
),
137 DECL(alcGetCurrentContext
),
138 DECL(alcGetContextsDevice
),
140 DECL(alcCloseDevice
),
142 DECL(alcIsExtensionPresent
),
143 DECL(alcGetProcAddress
),
144 DECL(alcGetEnumValue
),
146 DECL(alcGetIntegerv
),
147 DECL(alcCaptureOpenDevice
),
148 DECL(alcCaptureCloseDevice
),
149 DECL(alcCaptureStart
),
150 DECL(alcCaptureStop
),
151 DECL(alcCaptureSamples
),
153 DECL(alcSetThreadContext
),
154 DECL(alcGetThreadContext
),
156 DECL(alcLoopbackOpenDeviceSOFT
),
157 DECL(alcIsRenderFormatSupportedSOFT
),
158 DECL(alcRenderSamplesSOFT
),
160 DECL(alcIsAmbisonicFormatSupportedSOFT
),
162 DECL(alcDevicePauseSOFT
),
163 DECL(alcDeviceResumeSOFT
),
165 DECL(alcGetStringiSOFT
),
166 DECL(alcResetDeviceSOFT
),
168 DECL(alcGetInteger64vSOFT
),
183 DECL(alIsExtensionPresent
),
184 DECL(alGetProcAddress
),
185 DECL(alGetEnumValue
),
192 DECL(alGetListenerf
),
193 DECL(alGetListener3f
),
194 DECL(alGetListenerfv
),
195 DECL(alGetListeneri
),
196 DECL(alGetListener3i
),
197 DECL(alGetListeneriv
),
199 DECL(alDeleteSources
),
215 DECL(alSourceRewindv
),
216 DECL(alSourcePausev
),
219 DECL(alSourceRewind
),
221 DECL(alSourceQueueBuffers
),
222 DECL(alSourceUnqueueBuffers
),
224 DECL(alDeleteBuffers
),
239 DECL(alDopplerFactor
),
240 DECL(alDopplerVelocity
),
241 DECL(alSpeedOfSound
),
242 DECL(alDistanceModel
),
245 DECL(alDeleteFilters
),
256 DECL(alDeleteEffects
),
266 DECL(alGenAuxiliaryEffectSlots
),
267 DECL(alDeleteAuxiliaryEffectSlots
),
268 DECL(alIsAuxiliaryEffectSlot
),
269 DECL(alAuxiliaryEffectSloti
),
270 DECL(alAuxiliaryEffectSlotiv
),
271 DECL(alAuxiliaryEffectSlotf
),
272 DECL(alAuxiliaryEffectSlotfv
),
273 DECL(alGetAuxiliaryEffectSloti
),
274 DECL(alGetAuxiliaryEffectSlotiv
),
275 DECL(alGetAuxiliaryEffectSlotf
),
276 DECL(alGetAuxiliaryEffectSlotfv
),
278 DECL(alDeferUpdatesSOFT
),
279 DECL(alProcessUpdatesSOFT
),
282 DECL(alSource3dSOFT
),
283 DECL(alSourcedvSOFT
),
284 DECL(alGetSourcedSOFT
),
285 DECL(alGetSource3dSOFT
),
286 DECL(alGetSourcedvSOFT
),
287 DECL(alSourcei64SOFT
),
288 DECL(alSource3i64SOFT
),
289 DECL(alSourcei64vSOFT
),
290 DECL(alGetSourcei64SOFT
),
291 DECL(alGetSource3i64SOFT
),
292 DECL(alGetSourcei64vSOFT
),
294 DECL(alBufferSamplesSOFT
),
295 DECL(alGetBufferSamplesSOFT
),
296 DECL(alIsBufferFormatSupportedSOFT
),
302 #define DECL(x) { #x, (x) }
303 static const ALCenums enumeration
[] = {
308 DECL(ALC_MAJOR_VERSION
),
309 DECL(ALC_MINOR_VERSION
),
310 DECL(ALC_ATTRIBUTES_SIZE
),
311 DECL(ALC_ALL_ATTRIBUTES
),
312 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
313 DECL(ALC_DEVICE_SPECIFIER
),
314 DECL(ALC_ALL_DEVICES_SPECIFIER
),
315 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
316 DECL(ALC_EXTENSIONS
),
320 DECL(ALC_MONO_SOURCES
),
321 DECL(ALC_STEREO_SOURCES
),
322 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
323 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
324 DECL(ALC_CAPTURE_SAMPLES
),
327 DECL(ALC_EFX_MAJOR_VERSION
),
328 DECL(ALC_EFX_MINOR_VERSION
),
329 DECL(ALC_MAX_AUXILIARY_SENDS
),
331 DECL(ALC_FORMAT_CHANNELS_SOFT
),
332 DECL(ALC_FORMAT_TYPE_SOFT
),
335 DECL(ALC_STEREO_SOFT
),
337 DECL(ALC_5POINT1_SOFT
),
338 DECL(ALC_6POINT1_SOFT
),
339 DECL(ALC_7POINT1_SOFT
),
340 DECL(ALC_BFORMAT3D_SOFT
),
343 DECL(ALC_UNSIGNED_BYTE_SOFT
),
344 DECL(ALC_SHORT_SOFT
),
345 DECL(ALC_UNSIGNED_SHORT_SOFT
),
347 DECL(ALC_UNSIGNED_INT_SOFT
),
348 DECL(ALC_FLOAT_SOFT
),
351 DECL(ALC_DONT_CARE_SOFT
),
352 DECL(ALC_HRTF_STATUS_SOFT
),
353 DECL(ALC_HRTF_DISABLED_SOFT
),
354 DECL(ALC_HRTF_ENABLED_SOFT
),
355 DECL(ALC_HRTF_DENIED_SOFT
),
356 DECL(ALC_HRTF_REQUIRED_SOFT
),
357 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
358 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
359 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
360 DECL(ALC_HRTF_SPECIFIER_SOFT
),
361 DECL(ALC_HRTF_ID_SOFT
),
363 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
364 DECL(ALC_AMBISONIC_SCALING_SOFT
),
365 DECL(ALC_AMBISONIC_ORDER_SOFT
),
372 DECL(ALC_INVALID_DEVICE
),
373 DECL(ALC_INVALID_CONTEXT
),
374 DECL(ALC_INVALID_ENUM
),
375 DECL(ALC_INVALID_VALUE
),
376 DECL(ALC_OUT_OF_MEMORY
),
384 DECL(AL_SOURCE_RELATIVE
),
385 DECL(AL_CONE_INNER_ANGLE
),
386 DECL(AL_CONE_OUTER_ANGLE
),
396 DECL(AL_ORIENTATION
),
397 DECL(AL_REFERENCE_DISTANCE
),
398 DECL(AL_ROLLOFF_FACTOR
),
399 DECL(AL_CONE_OUTER_GAIN
),
400 DECL(AL_MAX_DISTANCE
),
402 DECL(AL_SAMPLE_OFFSET
),
403 DECL(AL_BYTE_OFFSET
),
404 DECL(AL_SOURCE_TYPE
),
407 DECL(AL_UNDETERMINED
),
408 DECL(AL_METERS_PER_UNIT
),
409 DECL(AL_LOOP_POINTS_SOFT
),
410 DECL(AL_DIRECT_CHANNELS_SOFT
),
412 DECL(AL_DIRECT_FILTER
),
413 DECL(AL_AUXILIARY_SEND_FILTER
),
414 DECL(AL_AIR_ABSORPTION_FACTOR
),
415 DECL(AL_ROOM_ROLLOFF_FACTOR
),
416 DECL(AL_CONE_OUTER_GAINHF
),
417 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
418 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
419 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
421 DECL(AL_SOURCE_STATE
),
427 DECL(AL_BUFFERS_QUEUED
),
428 DECL(AL_BUFFERS_PROCESSED
),
430 DECL(AL_FORMAT_MONO8
),
431 DECL(AL_FORMAT_MONO16
),
432 DECL(AL_FORMAT_MONO_FLOAT32
),
433 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
434 DECL(AL_FORMAT_STEREO8
),
435 DECL(AL_FORMAT_STEREO16
),
436 DECL(AL_FORMAT_STEREO_FLOAT32
),
437 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
438 DECL(AL_FORMAT_MONO_IMA4
),
439 DECL(AL_FORMAT_STEREO_IMA4
),
440 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
441 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
442 DECL(AL_FORMAT_QUAD8_LOKI
),
443 DECL(AL_FORMAT_QUAD16_LOKI
),
444 DECL(AL_FORMAT_QUAD8
),
445 DECL(AL_FORMAT_QUAD16
),
446 DECL(AL_FORMAT_QUAD32
),
447 DECL(AL_FORMAT_51CHN8
),
448 DECL(AL_FORMAT_51CHN16
),
449 DECL(AL_FORMAT_51CHN32
),
450 DECL(AL_FORMAT_61CHN8
),
451 DECL(AL_FORMAT_61CHN16
),
452 DECL(AL_FORMAT_61CHN32
),
453 DECL(AL_FORMAT_71CHN8
),
454 DECL(AL_FORMAT_71CHN16
),
455 DECL(AL_FORMAT_71CHN32
),
456 DECL(AL_FORMAT_REAR8
),
457 DECL(AL_FORMAT_REAR16
),
458 DECL(AL_FORMAT_REAR32
),
459 DECL(AL_FORMAT_MONO_MULAW
),
460 DECL(AL_FORMAT_MONO_MULAW_EXT
),
461 DECL(AL_FORMAT_STEREO_MULAW
),
462 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
463 DECL(AL_FORMAT_QUAD_MULAW
),
464 DECL(AL_FORMAT_51CHN_MULAW
),
465 DECL(AL_FORMAT_61CHN_MULAW
),
466 DECL(AL_FORMAT_71CHN_MULAW
),
467 DECL(AL_FORMAT_REAR_MULAW
),
468 DECL(AL_FORMAT_MONO_ALAW_EXT
),
469 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
471 DECL(AL_FORMAT_BFORMAT2D_8
),
472 DECL(AL_FORMAT_BFORMAT2D_16
),
473 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
474 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
475 DECL(AL_FORMAT_BFORMAT3D_8
),
476 DECL(AL_FORMAT_BFORMAT3D_16
),
477 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
478 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
481 DECL(AL_MONO16_SOFT
),
482 DECL(AL_MONO32F_SOFT
),
483 DECL(AL_STEREO8_SOFT
),
484 DECL(AL_STEREO16_SOFT
),
485 DECL(AL_STEREO32F_SOFT
),
487 DECL(AL_QUAD16_SOFT
),
488 DECL(AL_QUAD32F_SOFT
),
490 DECL(AL_REAR16_SOFT
),
491 DECL(AL_REAR32F_SOFT
),
492 DECL(AL_5POINT1_8_SOFT
),
493 DECL(AL_5POINT1_16_SOFT
),
494 DECL(AL_5POINT1_32F_SOFT
),
495 DECL(AL_6POINT1_8_SOFT
),
496 DECL(AL_6POINT1_16_SOFT
),
497 DECL(AL_6POINT1_32F_SOFT
),
498 DECL(AL_7POINT1_8_SOFT
),
499 DECL(AL_7POINT1_16_SOFT
),
500 DECL(AL_7POINT1_32F_SOFT
),
501 DECL(AL_BFORMAT2D_8_SOFT
),
502 DECL(AL_BFORMAT2D_16_SOFT
),
503 DECL(AL_BFORMAT2D_32F_SOFT
),
504 DECL(AL_BFORMAT3D_8_SOFT
),
505 DECL(AL_BFORMAT3D_16_SOFT
),
506 DECL(AL_BFORMAT3D_32F_SOFT
),
509 DECL(AL_STEREO_SOFT
),
512 DECL(AL_5POINT1_SOFT
),
513 DECL(AL_6POINT1_SOFT
),
514 DECL(AL_7POINT1_SOFT
),
515 DECL(AL_BFORMAT2D_SOFT
),
516 DECL(AL_BFORMAT3D_SOFT
),
519 DECL(AL_UNSIGNED_BYTE_SOFT
),
521 DECL(AL_UNSIGNED_SHORT_SOFT
),
523 DECL(AL_UNSIGNED_INT_SOFT
),
525 DECL(AL_DOUBLE_SOFT
),
527 DECL(AL_UNSIGNED_BYTE3_SOFT
),
534 DECL(AL_INTERNAL_FORMAT_SOFT
),
535 DECL(AL_BYTE_LENGTH_SOFT
),
536 DECL(AL_SAMPLE_LENGTH_SOFT
),
537 DECL(AL_SEC_LENGTH_SOFT
),
538 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
539 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
541 DECL(AL_SOURCE_RADIUS
),
543 DECL(AL_STEREO_ANGLES
),
550 DECL(AL_INVALID_NAME
),
551 DECL(AL_INVALID_ENUM
),
552 DECL(AL_INVALID_VALUE
),
553 DECL(AL_INVALID_OPERATION
),
554 DECL(AL_OUT_OF_MEMORY
),
561 DECL(AL_DOPPLER_FACTOR
),
562 DECL(AL_DOPPLER_VELOCITY
),
563 DECL(AL_DISTANCE_MODEL
),
564 DECL(AL_SPEED_OF_SOUND
),
565 DECL(AL_SOURCE_DISTANCE_MODEL
),
566 DECL(AL_DEFERRED_UPDATES_SOFT
),
567 DECL(AL_GAIN_LIMIT_SOFT
),
569 DECL(AL_INVERSE_DISTANCE
),
570 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
571 DECL(AL_LINEAR_DISTANCE
),
572 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
573 DECL(AL_EXPONENT_DISTANCE
),
574 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
576 DECL(AL_FILTER_TYPE
),
577 DECL(AL_FILTER_NULL
),
578 DECL(AL_FILTER_LOWPASS
),
579 DECL(AL_FILTER_HIGHPASS
),
580 DECL(AL_FILTER_BANDPASS
),
582 DECL(AL_LOWPASS_GAIN
),
583 DECL(AL_LOWPASS_GAINHF
),
585 DECL(AL_HIGHPASS_GAIN
),
586 DECL(AL_HIGHPASS_GAINLF
),
588 DECL(AL_BANDPASS_GAIN
),
589 DECL(AL_BANDPASS_GAINHF
),
590 DECL(AL_BANDPASS_GAINLF
),
592 DECL(AL_EFFECT_TYPE
),
593 DECL(AL_EFFECT_NULL
),
594 DECL(AL_EFFECT_REVERB
),
595 DECL(AL_EFFECT_EAXREVERB
),
596 DECL(AL_EFFECT_CHORUS
),
597 DECL(AL_EFFECT_DISTORTION
),
598 DECL(AL_EFFECT_ECHO
),
599 DECL(AL_EFFECT_FLANGER
),
601 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
602 DECL(AL_EFFECT_VOCAL_MORPHER
),
603 DECL(AL_EFFECT_PITCH_SHIFTER
),
605 DECL(AL_EFFECT_RING_MODULATOR
),
607 DECL(AL_EFFECT_AUTOWAH
),
609 DECL(AL_EFFECT_COMPRESSOR
),
610 DECL(AL_EFFECT_EQUALIZER
),
611 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
612 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
614 DECL(AL_EFFECTSLOT_EFFECT
),
615 DECL(AL_EFFECTSLOT_GAIN
),
616 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
617 DECL(AL_EFFECTSLOT_NULL
),
619 DECL(AL_EAXREVERB_DENSITY
),
620 DECL(AL_EAXREVERB_DIFFUSION
),
621 DECL(AL_EAXREVERB_GAIN
),
622 DECL(AL_EAXREVERB_GAINHF
),
623 DECL(AL_EAXREVERB_GAINLF
),
624 DECL(AL_EAXREVERB_DECAY_TIME
),
625 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
626 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
627 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
628 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
629 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
630 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
631 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
632 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
633 DECL(AL_EAXREVERB_ECHO_TIME
),
634 DECL(AL_EAXREVERB_ECHO_DEPTH
),
635 DECL(AL_EAXREVERB_MODULATION_TIME
),
636 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
637 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
638 DECL(AL_EAXREVERB_HFREFERENCE
),
639 DECL(AL_EAXREVERB_LFREFERENCE
),
640 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
641 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
643 DECL(AL_REVERB_DENSITY
),
644 DECL(AL_REVERB_DIFFUSION
),
645 DECL(AL_REVERB_GAIN
),
646 DECL(AL_REVERB_GAINHF
),
647 DECL(AL_REVERB_DECAY_TIME
),
648 DECL(AL_REVERB_DECAY_HFRATIO
),
649 DECL(AL_REVERB_REFLECTIONS_GAIN
),
650 DECL(AL_REVERB_REFLECTIONS_DELAY
),
651 DECL(AL_REVERB_LATE_REVERB_GAIN
),
652 DECL(AL_REVERB_LATE_REVERB_DELAY
),
653 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
654 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
655 DECL(AL_REVERB_DECAY_HFLIMIT
),
657 DECL(AL_CHORUS_WAVEFORM
),
658 DECL(AL_CHORUS_PHASE
),
659 DECL(AL_CHORUS_RATE
),
660 DECL(AL_CHORUS_DEPTH
),
661 DECL(AL_CHORUS_FEEDBACK
),
662 DECL(AL_CHORUS_DELAY
),
664 DECL(AL_DISTORTION_EDGE
),
665 DECL(AL_DISTORTION_GAIN
),
666 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
667 DECL(AL_DISTORTION_EQCENTER
),
668 DECL(AL_DISTORTION_EQBANDWIDTH
),
671 DECL(AL_ECHO_LRDELAY
),
672 DECL(AL_ECHO_DAMPING
),
673 DECL(AL_ECHO_FEEDBACK
),
674 DECL(AL_ECHO_SPREAD
),
676 DECL(AL_FLANGER_WAVEFORM
),
677 DECL(AL_FLANGER_PHASE
),
678 DECL(AL_FLANGER_RATE
),
679 DECL(AL_FLANGER_DEPTH
),
680 DECL(AL_FLANGER_FEEDBACK
),
681 DECL(AL_FLANGER_DELAY
),
683 DECL(AL_RING_MODULATOR_FREQUENCY
),
684 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
685 DECL(AL_RING_MODULATOR_WAVEFORM
),
687 DECL(AL_COMPRESSOR_ONOFF
),
689 DECL(AL_EQUALIZER_LOW_GAIN
),
690 DECL(AL_EQUALIZER_LOW_CUTOFF
),
691 DECL(AL_EQUALIZER_MID1_GAIN
),
692 DECL(AL_EQUALIZER_MID1_CENTER
),
693 DECL(AL_EQUALIZER_MID1_WIDTH
),
694 DECL(AL_EQUALIZER_MID2_GAIN
),
695 DECL(AL_EQUALIZER_MID2_CENTER
),
696 DECL(AL_EQUALIZER_MID2_WIDTH
),
697 DECL(AL_EQUALIZER_HIGH_GAIN
),
698 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
700 DECL(AL_DEDICATED_GAIN
),
706 static const ALCchar alcNoError
[] = "No Error";
707 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
708 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
709 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
710 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
711 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
714 /************************************************
716 ************************************************/
718 /* Enumerated device names */
719 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
721 static al_string alcAllDevicesList
;
722 static al_string alcCaptureDeviceList
;
724 /* Default is always the first in the list */
725 static ALCchar
*alcDefaultAllDevicesSpecifier
;
726 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
728 /* Default context extensions */
729 static const ALchar alExtList
[] =
730 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
731 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
732 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
733 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
734 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
735 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
736 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
738 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
740 /* Thread-local current context */
741 static altss_t LocalContext
;
742 /* Process-wide current context */
743 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
745 /* Mixing thread piority level */
750 enum LogLevel LogLevel
= LogWarning
;
752 enum LogLevel LogLevel
= LogError
;
755 /* Flag to trap ALC device errors */
756 static ALCboolean TrapALCError
= ALC_FALSE
;
758 /* One-time configuration init control */
759 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
761 /* Default effect that applies to sources that don't have an effect on send 0 */
762 static ALeffect DefaultEffect
;
764 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
767 static ALCboolean SuspendDefers
= ALC_TRUE
;
770 /************************************************
772 ************************************************/
773 static const ALCchar alcNoDeviceExtList
[] =
774 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
775 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
776 static const ALCchar alcExtensionList
[] =
777 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
778 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
779 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
780 "ALC_SOFT_loopback ALC_SOFT_pause_device";
781 static const ALCint alcMajorVersion
= 1;
782 static const ALCint alcMinorVersion
= 1;
784 static const ALCint alcEFXMajorVersion
= 1;
785 static const ALCint alcEFXMinorVersion
= 0;
788 /************************************************
790 ************************************************/
791 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
793 static almtx_t ListLock
;
794 static inline void LockLists(void)
796 int ret
= almtx_lock(&ListLock
);
797 assert(ret
== althrd_success
);
799 static inline void UnlockLists(void)
801 int ret
= almtx_unlock(&ListLock
);
802 assert(ret
== althrd_success
);
805 /************************************************
806 * Library initialization
807 ************************************************/
809 static void alc_init(void);
810 static void alc_deinit(void);
811 static void alc_deinit_safe(void);
813 #ifndef AL_LIBTYPE_STATIC
814 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
818 case DLL_PROCESS_ATTACH
:
819 /* Pin the DLL so we won't get unloaded until the process terminates */
820 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
821 (WCHAR
*)hModule
, &hModule
);
825 case DLL_THREAD_DETACH
:
828 case DLL_PROCESS_DETACH
:
837 #elif defined(_MSC_VER)
838 #pragma section(".CRT$XCU",read)
839 static void alc_constructor(void);
840 static void alc_destructor(void);
841 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
843 static void alc_constructor(void)
845 atexit(alc_destructor
);
849 static void alc_destructor(void)
853 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor
));
855 static void alc_deinit(void) __attribute__((destructor
));
857 #error "No static initialization available on this platform!"
860 #elif defined(HAVE_GCC_DESTRUCTOR)
862 static void alc_init(void) __attribute__((constructor
));
863 static void alc_deinit(void) __attribute__((destructor
));
866 #error "No global initialization available on this platform!"
869 static void ReleaseThreadCtx(void *ptr
);
870 static void alc_init(void)
877 AL_STRING_INIT(alcAllDevicesList
);
878 AL_STRING_INIT(alcCaptureDeviceList
);
880 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
881 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
884 str
= getenv("__ALSOFT_REVERSE_Z");
885 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
888 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
889 assert(ret
== althrd_success
);
891 ret
= almtx_init(&ListLock
, almtx_recursive
);
892 assert(ret
== althrd_success
);
897 static void alc_initconfig(void)
899 const char *devs
, *str
;
904 str
= getenv("ALSOFT_LOGLEVEL");
907 long lvl
= strtol(str
, NULL
, 0);
908 if(lvl
>= NoLog
&& lvl
<= LogRef
)
912 str
= getenv("ALSOFT_LOGFILE");
915 FILE *logfile
= al_fopen(str
, "wt");
916 if(logfile
) LogFile
= logfile
;
917 else ERR("Failed to open log file '%s'\n", str
);
920 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
921 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
926 if(BackendListSize
> 0)
927 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
928 for(i
= 1;i
< BackendListSize
;i
++)
929 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
930 TRACE("Supported backends: %s\n", buf
);
934 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
937 if(strcasecmp(str
, "ignore") == 0)
939 SuspendDefers
= ALC_FALSE
;
940 TRACE("Selected context suspend behavior, \"ignore\"\n");
943 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
947 #if defined(HAVE_SSE4_1)
948 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
949 #elif defined(HAVE_SSE3)
950 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
951 #elif defined(HAVE_SSE2)
952 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
953 #elif defined(HAVE_SSE)
954 capfilter
|= CPU_CAP_SSE
;
957 capfilter
|= CPU_CAP_NEON
;
959 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
961 if(strcasecmp(str
, "all") == 0)
966 const char *next
= str
;
970 while(isspace(str
[0]))
972 next
= strchr(str
, ',');
974 if(!str
[0] || str
[0] == ',')
977 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
978 while(len
> 0 && isspace(str
[len
-1]))
980 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
981 capfilter
&= ~CPU_CAP_SSE
;
982 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
983 capfilter
&= ~CPU_CAP_SSE2
;
984 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
985 capfilter
&= ~CPU_CAP_SSE3
;
986 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
987 capfilter
&= ~CPU_CAP_SSE4_1
;
988 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
989 capfilter
&= ~CPU_CAP_NEON
;
991 WARN("Invalid CPU extension \"%s\"\n", str
);
995 FillCPUCaps(capfilter
);
1002 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1006 str
= getenv("ALSOFT_TRAP_ERROR");
1007 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1009 TrapALError
= AL_TRUE
;
1010 TrapALCError
= AL_TRUE
;
1014 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1015 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1016 TrapALError
= AL_TRUE
;
1017 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1019 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1020 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1021 TrapALCError
= ALC_TRUE
;
1022 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1025 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1026 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1028 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1030 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1031 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1035 const char *next
= devs
;
1036 int endlist
, delitem
;
1041 while(isspace(devs
[0]))
1043 next
= strchr(devs
, ',');
1045 delitem
= (devs
[0] == '-');
1046 if(devs
[0] == '-') devs
++;
1048 if(!devs
[0] || devs
[0] == ',')
1055 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1056 while(len
> 0 && isspace(devs
[len
-1]))
1058 for(n
= i
;n
< BackendListSize
;n
++)
1060 if(len
== strlen(BackendList
[n
].name
) &&
1061 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1065 for(;n
+1 < BackendListSize
;n
++)
1066 BackendList
[n
] = BackendList
[n
+1];
1071 struct BackendInfo Bkp
= BackendList
[n
];
1073 BackendList
[n
] = BackendList
[n
-1];
1074 BackendList
[n
] = Bkp
;
1084 BackendListSize
= i
;
1087 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1089 if(BackendList
[i
].getFactory
)
1091 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1092 if(!V0(factory
,init
)())
1094 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1098 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1099 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1101 PlaybackBackend
= BackendList
[i
];
1102 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1104 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1106 CaptureBackend
= BackendList
[i
];
1107 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1113 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1115 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1119 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1120 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1122 PlaybackBackend
= BackendList
[i
];
1123 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1125 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1127 CaptureBackend
= BackendList
[i
];
1128 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1132 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1136 if(!PlaybackBackend
.name
)
1137 WARN("No playback backend available!\n");
1138 if(!CaptureBackend
.name
)
1139 WARN("No capture backend available!\n");
1141 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1144 const char *next
= str
;
1148 next
= strchr(str
, ',');
1150 if(!str
[0] || next
== str
)
1153 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1154 for(n
= 0;EffectList
[n
].name
;n
++)
1156 if(len
== strlen(EffectList
[n
].name
) &&
1157 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1158 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1163 InitEffectFactoryMap();
1165 InitEffect(&DefaultEffect
);
1166 str
= getenv("ALSOFT_DEFAULT_REVERB");
1167 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1168 LoadReverbPreset(str
, &DefaultEffect
);
1170 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1175 static JavaVM
*gJavaVM
;
1176 static pthread_key_t gJVMThreadKey
;
1178 static void CleanupJNIEnv(void* UNUSED(ptr
))
1180 JCALL0(gJavaVM
,DetachCurrentThread
)();
1183 void *Android_GetJNIEnv(void)
1187 WARN("gJavaVM is NULL!\n");
1191 /* http://developer.android.com/guide/practices/jni.html
1193 * All threads are Linux threads, scheduled by the kernel. They're usually
1194 * started from managed code (using Thread.start), but they can also be
1195 * created elsewhere and then attached to the JavaVM. For example, a thread
1196 * started with pthread_create can be attached with the JNI
1197 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1198 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1199 * Attaching a natively-created thread causes a java.lang.Thread object to
1200 * be constructed and added to the "main" ThreadGroup, making it visible to
1201 * the debugger. Calling AttachCurrentThread on an already-attached thread
1204 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1207 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1210 ERR("Failed to attach current thread\n");
1213 pthread_setspecific(gJVMThreadKey
, env
);
1218 /* Automatically called by JNI. */
1219 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1225 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1227 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1231 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1232 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1234 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1235 ERR("pthread_key_create failed: %d\n", err
);
1236 pthread_setspecific(gJVMThreadKey
, env
);
1237 return JNI_VERSION_1_4
;
1243 /************************************************
1244 * Library deinitialization
1245 ************************************************/
1246 static void alc_cleanup(void)
1250 AL_STRING_DEINIT(alcAllDevicesList
);
1251 AL_STRING_DEINIT(alcCaptureDeviceList
);
1253 free(alcDefaultAllDevicesSpecifier
);
1254 alcDefaultAllDevicesSpecifier
= NULL
;
1255 free(alcCaptureDefaultDeviceSpecifier
);
1256 alcCaptureDefaultDeviceSpecifier
= NULL
;
1258 if((dev
=ATOMIC_EXCHANGE_SEQ(ALCdevice
*, &DeviceList
, NULL
)) != NULL
)
1263 } while((dev
=dev
->next
) != NULL
);
1264 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1267 DeinitEffectFactoryMap();
1270 static void alc_deinit_safe(void)
1278 almtx_destroy(&ListLock
);
1279 altss_delete(LocalContext
);
1281 if(LogFile
!= stderr
)
1286 static void alc_deinit(void)
1292 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1293 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1295 for(i
= 0;i
< BackendListSize
;i
++)
1297 if(!BackendList
[i
].getFactory
)
1298 BackendList
[i
].Deinit();
1301 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1302 V0(factory
,deinit
)();
1306 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1307 V0(factory
,deinit
)();
1314 /************************************************
1315 * Device enumeration
1316 ************************************************/
1317 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1322 al_string_clear(list
);
1324 if(backendinfo
->Probe
)
1325 backendinfo
->Probe(type
);
1326 else if(backendinfo
->getFactory
)
1328 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1329 V(factory
,probe
)(type
);
1334 static void ProbeAllDevicesList(void)
1335 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1336 static void ProbeCaptureDeviceList(void)
1337 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1339 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1341 size_t len
= strlen(name
);
1343 al_string_append_range(devnames
, name
, name
+len
+1);
1345 void AppendAllDevicesList(const ALCchar
*name
)
1346 { AppendDevice(name
, &alcAllDevicesList
); }
1347 void AppendCaptureDeviceList(const ALCchar
*name
)
1348 { AppendDevice(name
, &alcCaptureDeviceList
); }
1351 /************************************************
1352 * Device format information
1353 ************************************************/
1354 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1358 case DevFmtByte
: return "Signed Byte";
1359 case DevFmtUByte
: return "Unsigned Byte";
1360 case DevFmtShort
: return "Signed Short";
1361 case DevFmtUShort
: return "Unsigned Short";
1362 case DevFmtInt
: return "Signed Int";
1363 case DevFmtUInt
: return "Unsigned Int";
1364 case DevFmtFloat
: return "Float";
1366 return "(unknown type)";
1368 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1372 case DevFmtMono
: return "Mono";
1373 case DevFmtStereo
: return "Stereo";
1374 case DevFmtQuad
: return "Quadraphonic";
1375 case DevFmtX51
: return "5.1 Surround";
1376 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1377 case DevFmtX61
: return "6.1 Surround";
1378 case DevFmtX71
: return "7.1 Surround";
1379 case DevFmtAmbi1
: return "Ambisonic (1st Order)";
1380 case DevFmtAmbi2
: return "Ambisonic (2nd Order)";
1381 case DevFmtAmbi3
: return "Ambisonic (3rd Order)";
1383 return "(unknown channels)";
1386 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
);
1387 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1391 case DevFmtByte
: return sizeof(ALbyte
);
1392 case DevFmtUByte
: return sizeof(ALubyte
);
1393 case DevFmtShort
: return sizeof(ALshort
);
1394 case DevFmtUShort
: return sizeof(ALushort
);
1395 case DevFmtInt
: return sizeof(ALint
);
1396 case DevFmtUInt
: return sizeof(ALuint
);
1397 case DevFmtFloat
: return sizeof(ALfloat
);
1401 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1405 case DevFmtMono
: return 1;
1406 case DevFmtStereo
: return 2;
1407 case DevFmtQuad
: return 4;
1408 case DevFmtX51
: return 6;
1409 case DevFmtX51Rear
: return 6;
1410 case DevFmtX61
: return 7;
1411 case DevFmtX71
: return 8;
1412 case DevFmtAmbi1
: return 4;
1413 case DevFmtAmbi2
: return 9;
1414 case DevFmtAmbi3
: return 16;
1419 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1420 enum DevFmtType
*type
)
1422 static const struct {
1424 enum DevFmtChannels channels
;
1425 enum DevFmtType type
;
1427 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1428 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1429 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1431 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1432 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1433 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1435 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1436 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1437 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1439 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1440 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1441 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1443 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1444 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1445 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1447 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1448 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1449 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1453 for(i
= 0;i
< COUNTOF(list
);i
++)
1455 if(list
[i
].format
== format
)
1457 *chans
= list
[i
].channels
;
1458 *type
= list
[i
].type
;
1466 static ALCboolean
IsValidALCType(ALCenum type
)
1471 case ALC_UNSIGNED_BYTE_SOFT
:
1472 case ALC_SHORT_SOFT
:
1473 case ALC_UNSIGNED_SHORT_SOFT
:
1475 case ALC_UNSIGNED_INT_SOFT
:
1476 case ALC_FLOAT_SOFT
:
1482 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1487 case ALC_STEREO_SOFT
:
1489 case ALC_5POINT1_SOFT
:
1490 case ALC_6POINT1_SOFT
:
1491 case ALC_7POINT1_SOFT
:
1492 case ALC_BFORMAT3D_SOFT
:
1498 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1509 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1521 /************************************************
1522 * Miscellaneous ALC helpers
1523 ************************************************/
1525 void ALCdevice_Lock(ALCdevice
*device
)
1527 V0(device
->Backend
,lock
)();
1530 void ALCdevice_Unlock(ALCdevice
*device
)
1532 V0(device
->Backend
,unlock
)();
1536 /* SetDefaultWFXChannelOrder
1538 * Sets the default channel order used by WaveFormatEx.
1540 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1544 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1545 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1547 switch(device
->FmtChans
)
1550 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1553 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1554 device
->RealOut
.ChannelName
[1] = FrontRight
;
1557 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1558 device
->RealOut
.ChannelName
[1] = FrontRight
;
1559 device
->RealOut
.ChannelName
[2] = BackLeft
;
1560 device
->RealOut
.ChannelName
[3] = BackRight
;
1563 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1564 device
->RealOut
.ChannelName
[1] = FrontRight
;
1565 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1566 device
->RealOut
.ChannelName
[3] = LFE
;
1567 device
->RealOut
.ChannelName
[4] = SideLeft
;
1568 device
->RealOut
.ChannelName
[5] = SideRight
;
1571 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1572 device
->RealOut
.ChannelName
[1] = FrontRight
;
1573 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1574 device
->RealOut
.ChannelName
[3] = LFE
;
1575 device
->RealOut
.ChannelName
[4] = BackLeft
;
1576 device
->RealOut
.ChannelName
[5] = BackRight
;
1579 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1580 device
->RealOut
.ChannelName
[1] = FrontRight
;
1581 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1582 device
->RealOut
.ChannelName
[3] = LFE
;
1583 device
->RealOut
.ChannelName
[4] = BackCenter
;
1584 device
->RealOut
.ChannelName
[5] = SideLeft
;
1585 device
->RealOut
.ChannelName
[6] = SideRight
;
1588 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1589 device
->RealOut
.ChannelName
[1] = FrontRight
;
1590 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1591 device
->RealOut
.ChannelName
[3] = LFE
;
1592 device
->RealOut
.ChannelName
[4] = BackLeft
;
1593 device
->RealOut
.ChannelName
[5] = BackRight
;
1594 device
->RealOut
.ChannelName
[6] = SideLeft
;
1595 device
->RealOut
.ChannelName
[7] = SideRight
;
1598 device
->RealOut
.ChannelName
[0] = Aux0
;
1599 device
->RealOut
.ChannelName
[1] = Aux1
;
1600 device
->RealOut
.ChannelName
[2] = Aux2
;
1601 device
->RealOut
.ChannelName
[3] = Aux3
;
1604 device
->RealOut
.ChannelName
[0] = Aux0
;
1605 device
->RealOut
.ChannelName
[1] = Aux1
;
1606 device
->RealOut
.ChannelName
[2] = Aux2
;
1607 device
->RealOut
.ChannelName
[3] = Aux3
;
1608 device
->RealOut
.ChannelName
[4] = Aux4
;
1609 device
->RealOut
.ChannelName
[5] = Aux5
;
1610 device
->RealOut
.ChannelName
[6] = Aux6
;
1611 device
->RealOut
.ChannelName
[7] = Aux7
;
1612 device
->RealOut
.ChannelName
[8] = Aux8
;
1615 device
->RealOut
.ChannelName
[0] = Aux0
;
1616 device
->RealOut
.ChannelName
[1] = Aux1
;
1617 device
->RealOut
.ChannelName
[2] = Aux2
;
1618 device
->RealOut
.ChannelName
[3] = Aux3
;
1619 device
->RealOut
.ChannelName
[4] = Aux4
;
1620 device
->RealOut
.ChannelName
[5] = Aux5
;
1621 device
->RealOut
.ChannelName
[6] = Aux6
;
1622 device
->RealOut
.ChannelName
[7] = Aux7
;
1623 device
->RealOut
.ChannelName
[8] = Aux8
;
1624 device
->RealOut
.ChannelName
[9] = Aux9
;
1625 device
->RealOut
.ChannelName
[10] = Aux10
;
1626 device
->RealOut
.ChannelName
[11] = Aux11
;
1627 device
->RealOut
.ChannelName
[12] = Aux12
;
1628 device
->RealOut
.ChannelName
[13] = Aux13
;
1629 device
->RealOut
.ChannelName
[14] = Aux14
;
1630 device
->RealOut
.ChannelName
[15] = Aux15
;
1635 /* SetDefaultChannelOrder
1637 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1639 void SetDefaultChannelOrder(ALCdevice
*device
)
1643 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1644 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1646 switch(device
->FmtChans
)
1649 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1650 device
->RealOut
.ChannelName
[1] = FrontRight
;
1651 device
->RealOut
.ChannelName
[2] = BackLeft
;
1652 device
->RealOut
.ChannelName
[3] = BackRight
;
1653 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1654 device
->RealOut
.ChannelName
[5] = LFE
;
1657 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1658 device
->RealOut
.ChannelName
[1] = FrontRight
;
1659 device
->RealOut
.ChannelName
[2] = BackLeft
;
1660 device
->RealOut
.ChannelName
[3] = BackRight
;
1661 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1662 device
->RealOut
.ChannelName
[5] = LFE
;
1663 device
->RealOut
.ChannelName
[6] = SideLeft
;
1664 device
->RealOut
.ChannelName
[7] = SideRight
;
1667 /* Same as WFX order */
1676 SetDefaultWFXChannelOrder(device
);
1681 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1684 /* ALCcontext_DeferUpdates
1686 * Defers/suspends updates for the given context's listener and sources. This
1687 * does *NOT* stop mixing, but rather prevents certain property changes from
1690 void ALCcontext_DeferUpdates(ALCcontext
*context
, ALenum type
)
1692 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, type
);
1695 /* ALCcontext_ProcessUpdates
1697 * Resumes update processing after being deferred.
1699 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1701 ALCdevice
*device
= context
->Device
;
1703 ReadLock(&context
->PropLock
);
1704 if(ATOMIC_EXCHANGE_SEQ(ALenum
, &context
->DeferUpdates
, AL_FALSE
))
1708 /* Tell the mixer to stop applying updates, then wait for any active
1709 * updating to finish, before providing updates.
1711 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1712 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1715 UpdateListenerProps(context
);
1716 UpdateAllEffectSlotProps(context
);
1718 LockUIntMapRead(&context
->SourceMap
);
1719 V0(device
->Backend
,lock
)();
1720 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
1722 ALvoice
*voice
= context
->Voices
[pos
];
1723 ALsource
*source
= ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
);
1724 if(source
&& source
->OffsetType
!= AL_NONE
)
1726 WriteLock(&source
->queue_lock
);
1727 ApplyOffset(source
, voice
);
1728 WriteUnlock(&source
->queue_lock
);
1731 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1733 ALsource
*source
= context
->SourceMap
.values
[pos
];
1734 ALenum new_state
= source
->new_state
;
1735 source
->new_state
= AL_NONE
;
1737 SetSourceState(source
, context
, new_state
);
1739 V0(device
->Backend
,unlock
)();
1740 UnlockUIntMapRead(&context
->SourceMap
);
1742 UpdateAllSourceProps(context
);
1744 /* Now with all updates declared, let the mixer continue applying them
1745 * so they all happen at once.
1747 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1749 ReadUnlock(&context
->PropLock
);
1755 * Stores the latest ALC device error
1757 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1759 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1763 /* DebugBreak() will cause an exception if there is no debugger */
1764 if(IsDebuggerPresent())
1766 #elif defined(SIGTRAP)
1772 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1774 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1780 * Updates the device's base clock time with however many samples have been
1781 * done. This is used so frequency changes on the device don't cause the time
1782 * to jump forward or back. Must not be called while the device is running/
1785 static inline void UpdateClockBase(ALCdevice
*device
)
1787 IncrementRef(&device
->MixCount
);
1788 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1789 device
->SamplesDone
= 0;
1790 IncrementRef(&device
->MixCount
);
1793 /* UpdateDeviceParams
1795 * Updates device parameters according to the attribute list (caller is
1796 * responsible for holding the list lock).
1798 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1800 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1801 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1802 const ALsizei old_sends
= device
->NumAuxSends
;
1803 ALsizei new_sends
= device
->NumAuxSends
;
1804 enum DevFmtChannels oldChans
;
1805 enum DevFmtType oldType
;
1806 ALboolean update_failed
;
1807 ALCsizei hrtf_id
= -1;
1808 ALCcontext
*context
;
1814 // Check for attributes
1815 if(device
->Type
== Loopback
)
1817 ALCsizei numMono
, numStereo
, numSends
;
1818 ALCenum alayout
= AL_NONE
;
1819 ALCenum ascale
= AL_NONE
;
1820 ALCenum schans
= AL_NONE
;
1821 ALCenum stype
= AL_NONE
;
1822 ALCsizei attrIdx
= 0;
1823 ALCsizei aorder
= 0;
1828 WARN("Missing attributes for loopback device\n");
1829 return ALC_INVALID_VALUE
;
1832 numMono
= device
->NumMonoSources
;
1833 numStereo
= device
->NumStereoSources
;
1834 numSends
= old_sends
;
1836 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1837 while(attrList
[attrIdx
])
1839 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1841 schans
= attrList
[attrIdx
+ 1];
1842 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1843 if(!IsValidALCChannels(schans
))
1844 return ALC_INVALID_VALUE
;
1847 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1849 stype
= attrList
[attrIdx
+ 1];
1850 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1851 if(!IsValidALCType(stype
))
1852 return ALC_INVALID_VALUE
;
1855 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1857 freq
= attrList
[attrIdx
+ 1];
1858 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1859 if(freq
< MIN_OUTPUT_RATE
)
1860 return ALC_INVALID_VALUE
;
1863 if(attrList
[attrIdx
] == ALC_AMBISONIC_LAYOUT_SOFT
)
1865 alayout
= attrList
[attrIdx
+ 1];
1866 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1867 if(!IsValidAmbiLayout(alayout
))
1868 return ALC_INVALID_VALUE
;
1871 if(attrList
[attrIdx
] == ALC_AMBISONIC_SCALING_SOFT
)
1873 ascale
= attrList
[attrIdx
+ 1];
1874 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1875 if(!IsValidAmbiScaling(ascale
))
1876 return ALC_INVALID_VALUE
;
1879 if(attrList
[attrIdx
] == ALC_AMBISONIC_ORDER_SOFT
)
1881 aorder
= attrList
[attrIdx
+ 1];
1882 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1883 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1884 return ALC_INVALID_VALUE
;
1887 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1889 numStereo
= attrList
[attrIdx
+ 1];
1890 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1892 numStereo
= clampi(numStereo
, 0, device
->SourcesMax
);
1893 numMono
= device
->SourcesMax
- numStereo
;
1896 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1898 numSends
= attrList
[attrIdx
+ 1];
1899 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1900 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1903 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1905 ALCint val
= attrList
[attrIdx
+ 1];
1906 TRACE_ATTR(ALC_HRTF_SOFT
, val
);
1907 if(val
== ALC_FALSE
)
1908 hrtf_appreq
= Hrtf_Disable
;
1909 else if(val
== ALC_TRUE
)
1910 hrtf_appreq
= Hrtf_Enable
;
1912 hrtf_appreq
= Hrtf_Default
;
1915 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
1917 hrtf_id
= attrList
[attrIdx
+ 1];
1918 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1925 if(!schans
|| !stype
|| !freq
)
1927 WARN("Missing format for loopback device\n");
1928 return ALC_INVALID_VALUE
;
1930 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1932 WARN("Missing ambisonic info for loopback device\n");
1933 return ALC_INVALID_VALUE
;
1936 if((device
->Flags
&DEVICE_RUNNING
))
1937 V0(device
->Backend
,stop
)();
1938 device
->Flags
&= ~DEVICE_RUNNING
;
1940 UpdateClockBase(device
);
1942 if(schans
== ALC_BFORMAT3D_SOFT
)
1944 device
->FmtChans
= DevFmtAmbi1
+ aorder
;
1945 device
->AmbiLayout
= alayout
;
1946 device
->AmbiScale
= ascale
;
1949 device
->FmtChans
= schans
;
1950 device
->Frequency
= freq
;
1951 device
->FmtType
= stype
;
1952 device
->NumMonoSources
= numMono
;
1953 device
->NumStereoSources
= numStereo
;
1955 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1956 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1958 new_sends
= numSends
;
1960 else if(attrList
&& attrList
[0])
1962 ALCsizei numMono
, numStereo
, numSends
;
1963 ALCsizei attrIdx
= 0;
1966 /* If a context is already running on the device, stop playback so the
1967 * device attributes can be updated. */
1968 if((device
->Flags
&DEVICE_RUNNING
))
1969 V0(device
->Backend
,stop
)();
1970 device
->Flags
&= ~DEVICE_RUNNING
;
1972 UpdateClockBase(device
);
1974 freq
= device
->Frequency
;
1975 numMono
= device
->NumMonoSources
;
1976 numStereo
= device
->NumStereoSources
;
1977 numSends
= old_sends
;
1979 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1980 while(attrList
[attrIdx
])
1982 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1984 freq
= attrList
[attrIdx
+ 1];
1985 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1986 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1989 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1991 numStereo
= attrList
[attrIdx
+ 1];
1992 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1994 numStereo
= clampi(numStereo
, 0, device
->SourcesMax
);
1995 numMono
= device
->SourcesMax
- numStereo
;
1998 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
2000 numSends
= attrList
[attrIdx
+ 1];
2001 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
2002 numSends
= clampi(numSends
, 0, MAX_SENDS
);
2005 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
2007 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
2008 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
2009 hrtf_appreq
= Hrtf_Disable
;
2010 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
2011 hrtf_appreq
= Hrtf_Enable
;
2013 hrtf_appreq
= Hrtf_Default
;
2016 if(attrList
[attrIdx
] == ALC_HRTF_ID_SOFT
)
2018 hrtf_id
= attrList
[attrIdx
+ 1];
2019 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
2026 ConfigValueUInt(al_string_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2027 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2029 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2031 /* SSE and Neon do best with the update size being a multiple of 4 */
2032 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2033 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2035 device
->Frequency
= freq
;
2036 device
->NumMonoSources
= numMono
;
2037 device
->NumStereoSources
= numStereo
;
2039 if(ConfigValueInt(al_string_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2040 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2042 new_sends
= numSends
;
2045 if((device
->Flags
&DEVICE_RUNNING
))
2046 return ALC_NO_ERROR
;
2048 al_free(device
->Uhj_Encoder
);
2049 device
->Uhj_Encoder
= NULL
;
2051 al_free(device
->Bs2b
);
2052 device
->Bs2b
= NULL
;
2054 al_free(device
->ChannelDelay
[0].Buffer
);
2055 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2057 device
->ChannelDelay
[i
].Length
= 0;
2058 device
->ChannelDelay
[i
].Buffer
= NULL
;
2061 al_free(device
->Dry
.Buffer
);
2062 device
->Dry
.Buffer
= NULL
;
2063 device
->Dry
.NumChannels
= 0;
2064 device
->FOAOut
.Buffer
= NULL
;
2065 device
->FOAOut
.NumChannels
= 0;
2066 device
->RealOut
.Buffer
= NULL
;
2067 device
->RealOut
.NumChannels
= 0;
2069 UpdateClockBase(device
);
2071 /*************************************************************************
2072 * Update device format request if HRTF is requested
2074 device
->Hrtf
.Status
= ALC_HRTF_DISABLED_SOFT
;
2075 if(device
->Type
!= Loopback
)
2078 if(ConfigValueStr(al_string_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2080 if(strcasecmp(hrtf
, "true") == 0)
2081 hrtf_userreq
= Hrtf_Enable
;
2082 else if(strcasecmp(hrtf
, "false") == 0)
2083 hrtf_userreq
= Hrtf_Disable
;
2084 else if(strcasecmp(hrtf
, "auto") != 0)
2085 ERR("Unexpected hrtf value: %s\n", hrtf
);
2088 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2090 if(VECTOR_SIZE(device
->Hrtf
.List
) == 0)
2092 VECTOR_DEINIT(device
->Hrtf
.List
);
2093 device
->Hrtf
.List
= EnumerateHrtf(device
->DeviceName
);
2095 if(VECTOR_SIZE(device
->Hrtf
.List
) > 0)
2097 device
->FmtChans
= DevFmtStereo
;
2098 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->Hrtf
.List
))
2099 device
->Frequency
= VECTOR_ELEM(device
->Hrtf
.List
, hrtf_id
).hrtf
->sampleRate
;
2101 device
->Frequency
= VECTOR_ELEM(device
->Hrtf
.List
, 0).hrtf
->sampleRate
;
2102 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2106 hrtf_userreq
= Hrtf_Default
;
2107 hrtf_appreq
= Hrtf_Disable
;
2108 device
->Hrtf
.Status
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2112 else if(hrtf_appreq
== Hrtf_Enable
)
2114 size_t i
= VECTOR_SIZE(device
->Hrtf
.List
);
2115 /* Loopback device. We don't need to match to a specific HRTF entry
2116 * here. If the requested ID matches, we'll pick that later, if not,
2117 * we'll try to auto-select one anyway. Just make sure one exists
2120 if(device
->FmtChans
== DevFmtStereo
)
2122 if(VECTOR_SIZE(device
->Hrtf
.List
) == 0)
2124 VECTOR_DEINIT(device
->Hrtf
.List
);
2125 device
->Hrtf
.List
= EnumerateHrtf(device
->DeviceName
);
2127 for(i
= 0;i
< VECTOR_SIZE(device
->Hrtf
.List
);i
++)
2129 const struct Hrtf
*hrtf
= VECTOR_ELEM(device
->Hrtf
.List
, i
).hrtf
;
2130 if(hrtf
->sampleRate
== device
->Frequency
)
2134 if(i
== VECTOR_SIZE(device
->Hrtf
.List
))
2136 ERR("Requested format not HRTF compatible: %s, %uhz\n",
2137 DevFmtChannelsString(device
->FmtChans
), device
->Frequency
);
2138 hrtf_appreq
= Hrtf_Disable
;
2139 device
->Hrtf
.Status
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2143 oldFreq
= device
->Frequency
;
2144 oldChans
= device
->FmtChans
;
2145 oldType
= device
->FmtType
;
2147 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2148 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2149 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2150 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2151 device
->UpdateSize
, device
->NumUpdates
2154 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2155 return ALC_INVALID_DEVICE
;
2157 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2159 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2160 DevFmtChannelsString(device
->FmtChans
));
2161 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2163 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2165 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2166 DevFmtTypeString(device
->FmtType
));
2167 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2169 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2171 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2172 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2175 if((device
->UpdateSize
&3) != 0)
2177 if((CPUCapFlags
&CPU_CAP_SSE
))
2178 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2179 if((CPUCapFlags
&CPU_CAP_NEON
))
2180 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2183 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2184 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2185 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2188 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2189 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2190 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2192 /* Allocate extra channels for any post-filter output. */
2193 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2194 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2196 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2197 device
->Dry
.Buffer
= al_calloc(16, size
);
2198 if(!device
->Dry
.Buffer
)
2200 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2201 return ALC_INVALID_DEVICE
;
2204 if(device
->RealOut
.NumChannels
!= 0)
2205 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2206 device
->FOAOut
.NumChannels
;
2209 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2210 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2213 if(device
->FOAOut
.NumChannels
!= 0)
2214 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2217 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2218 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2221 /* Need to delay returning failure until replacement Send arrays have been
2222 * allocated with the appropriate size.
2224 device
->NumAuxSends
= new_sends
;
2225 update_failed
= AL_FALSE
;
2226 SetMixerFPUMode(&oldMode
);
2227 if(device
->DefaultSlot
)
2229 ALeffectslot
*slot
= device
->DefaultSlot
;
2230 ALeffectState
*state
= slot
->Effect
.State
;
2232 state
->OutBuffer
= device
->Dry
.Buffer
;
2233 state
->OutChannels
= device
->Dry
.NumChannels
;
2234 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2235 update_failed
= AL_TRUE
;
2237 UpdateEffectSlotProps(slot
);
2240 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2245 WriteLock(&context
->PropLock
);
2246 LockUIntMapRead(&context
->EffectSlotMap
);
2247 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2249 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2250 ALeffectState
*state
= slot
->Effect
.State
;
2252 state
->OutBuffer
= device
->Dry
.Buffer
;
2253 state
->OutChannels
= device
->Dry
.NumChannels
;
2254 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2255 update_failed
= AL_TRUE
;
2257 UpdateEffectSlotProps(slot
);
2259 UnlockUIntMapRead(&context
->EffectSlotMap
);
2261 LockUIntMapRead(&context
->SourceMap
);
2262 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2264 ALsource
*source
= context
->SourceMap
.values
[pos
];
2265 struct ALsourceProps
*props
;
2267 if(old_sends
!= device
->NumAuxSends
)
2269 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2272 memcpy(sends
, source
->Send
,
2273 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2275 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2277 if(source
->Send
[s
].Slot
)
2278 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2279 source
->Send
[s
].Slot
= NULL
;
2281 al_free(source
->Send
);
2282 source
->Send
= sends
;
2283 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2285 source
->Send
[s
].Slot
= NULL
;
2286 source
->Send
[s
].Gain
= 1.0f
;
2287 source
->Send
[s
].GainHF
= 1.0f
;
2288 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2289 source
->Send
[s
].GainLF
= 1.0f
;
2290 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2294 source
->NeedsUpdate
= AL_TRUE
;
2296 /* Clear any pre-existing source property structs, in case the
2297 * number of auxiliary sends changed. Playing (or paused) sources
2298 * will have updates respecified in UpdateAllSourceProps.
2300 props
= ATOMIC_EXCHANGE_SEQ(struct ALsourceProps
*, &source
->Update
, NULL
);
2303 props
= ATOMIC_EXCHANGE(struct ALsourceProps
*, &source
->FreeList
, NULL
,
2304 almemory_order_relaxed
);
2307 struct ALsourceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2312 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2313 UnlockUIntMapRead(&context
->SourceMap
);
2315 UpdateListenerProps(context
);
2316 UpdateAllSourceProps(context
);
2317 WriteUnlock(&context
->PropLock
);
2319 context
= context
->next
;
2321 RestoreFPUMode(&oldMode
);
2323 return ALC_INVALID_DEVICE
;
2325 if(!(device
->Flags
&DEVICE_PAUSED
))
2327 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2328 return ALC_INVALID_DEVICE
;
2329 device
->Flags
|= DEVICE_RUNNING
;
2332 return ALC_NO_ERROR
;
2337 * Frees the device structure, and destroys any objects the app failed to
2338 * delete. Called once there's no more references on the device.
2340 static ALCvoid
FreeDevice(ALCdevice
*device
)
2344 TRACE("%p\n", device
);
2346 V0(device
->Backend
,close
)();
2347 DELETE_OBJ(device
->Backend
);
2348 device
->Backend
= NULL
;
2350 almtx_destroy(&device
->BackendLock
);
2352 if(device
->DefaultSlot
)
2354 DeinitEffectSlot(device
->DefaultSlot
);
2355 device
->DefaultSlot
= NULL
;
2358 if(device
->BufferMap
.size
> 0)
2360 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2361 (device
->BufferMap
.size
==1)?"":"s");
2362 ReleaseALBuffers(device
);
2364 ResetUIntMap(&device
->BufferMap
);
2366 if(device
->EffectMap
.size
> 0)
2368 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2369 (device
->EffectMap
.size
==1)?"":"s");
2370 ReleaseALEffects(device
);
2372 ResetUIntMap(&device
->EffectMap
);
2374 if(device
->FilterMap
.size
> 0)
2376 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2377 (device
->FilterMap
.size
==1)?"":"s");
2378 ReleaseALFilters(device
);
2380 ResetUIntMap(&device
->FilterMap
);
2382 AL_STRING_DEINIT(device
->Hrtf
.Name
);
2383 FreeHrtfList(&device
->Hrtf
.List
);
2385 al_free(device
->Bs2b
);
2386 device
->Bs2b
= NULL
;
2388 al_free(device
->Uhj_Encoder
);
2389 device
->Uhj_Encoder
= NULL
;
2391 bformatdec_free(device
->AmbiDecoder
);
2392 device
->AmbiDecoder
= NULL
;
2394 ambiup_free(device
->AmbiUp
);
2395 device
->AmbiUp
= NULL
;
2397 al_free(device
->ChannelDelay
[0].Buffer
);
2398 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2400 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2401 device
->ChannelDelay
[i
].Length
= 0;
2402 device
->ChannelDelay
[i
].Buffer
= NULL
;
2405 AL_STRING_DEINIT(device
->DeviceName
);
2407 al_free(device
->Dry
.Buffer
);
2408 device
->Dry
.Buffer
= NULL
;
2409 device
->Dry
.NumChannels
= 0;
2410 device
->FOAOut
.Buffer
= NULL
;
2411 device
->FOAOut
.NumChannels
= 0;
2412 device
->RealOut
.Buffer
= NULL
;
2413 device
->RealOut
.NumChannels
= 0;
2419 void ALCdevice_IncRef(ALCdevice
*device
)
2422 ref
= IncrementRef(&device
->ref
);
2423 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2426 void ALCdevice_DecRef(ALCdevice
*device
)
2429 ref
= DecrementRef(&device
->ref
);
2430 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2431 if(ref
== 0) FreeDevice(device
);
2436 * Checks if the device handle is valid, and increments its ref count if so.
2438 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2440 ALCdevice
*tmpDevice
;
2443 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2446 if(tmpDevice
== *device
)
2448 ALCdevice_IncRef(tmpDevice
);
2452 tmpDevice
= tmpDevice
->next
;
2463 * Initializes context fields
2465 static ALvoid
InitContext(ALCcontext
*Context
)
2467 ALlistener
*listener
= Context
->Listener
;
2469 //Initialise listener
2470 listener
->Gain
= 1.0f
;
2471 listener
->MetersPerUnit
= 1.0f
;
2472 listener
->Position
[0] = 0.0f
;
2473 listener
->Position
[1] = 0.0f
;
2474 listener
->Position
[2] = 0.0f
;
2475 listener
->Velocity
[0] = 0.0f
;
2476 listener
->Velocity
[1] = 0.0f
;
2477 listener
->Velocity
[2] = 0.0f
;
2478 listener
->Forward
[0] = 0.0f
;
2479 listener
->Forward
[1] = 0.0f
;
2480 listener
->Forward
[2] = -1.0f
;
2481 listener
->Up
[0] = 0.0f
;
2482 listener
->Up
[1] = 1.0f
;
2483 listener
->Up
[2] = 0.0f
;
2485 aluMatrixfSet(&listener
->Params
.Matrix
,
2486 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2487 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2488 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2489 0.0f
, 0.0f
, 0.0f
, 1.0f
2491 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2492 listener
->Params
.Gain
= 1.0f
;
2493 listener
->Params
.MetersPerUnit
= 1.0f
;
2494 listener
->Params
.DopplerFactor
= 1.0f
;
2495 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2497 ATOMIC_INIT(&listener
->Update
, NULL
);
2498 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2501 InitRef(&Context
->UpdateCount
, 0);
2502 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2503 Context
->GainBoost
= 1.0f
;
2504 RWLockInit(&Context
->PropLock
);
2505 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2506 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2507 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
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 ALlistenerProps
*lprops
;
2532 TRACE("%p\n", context
);
2534 if(context
->SourceMap
.size
> 0)
2536 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2537 (context
->SourceMap
.size
==1)?"":"s");
2538 ReleaseALSources(context
);
2540 ResetUIntMap(&context
->SourceMap
);
2542 if(context
->EffectSlotMap
.size
> 0)
2544 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2545 (context
->EffectSlotMap
.size
==1)?"":"s");
2546 ReleaseALAuxiliaryEffectSlots(context
);
2548 ResetUIntMap(&context
->EffectSlotMap
);
2550 al_free(context
->Voices
);
2551 context
->Voices
= NULL
;
2552 context
->VoiceCount
= 0;
2553 context
->MaxVoices
= 0;
2555 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2557 TRACE("Freed unapplied listener update %p\n", lprops
);
2561 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2564 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2569 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2571 ALCdevice_DecRef(context
->Device
);
2572 context
->Device
= NULL
;
2574 //Invalidate context
2575 memset(context
, 0, sizeof(ALCcontext
));
2581 * Removes the context reference from the given device and removes it from
2582 * being current on the running thread or globally.
2584 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2586 ALCcontext
*origctx
;
2588 if(altss_get(LocalContext
) == context
)
2590 WARN("%p released while current on thread\n", context
);
2591 altss_set(LocalContext
, NULL
);
2592 ALCcontext_DecRef(context
);
2596 if(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &GlobalContext
, &origctx
, NULL
))
2597 ALCcontext_DecRef(context
);
2599 ALCdevice_Lock(device
);
2601 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCcontext
*, &device
->ContextList
,
2602 &origctx
, context
->next
))
2604 ALCcontext
*volatile*list
= &origctx
->next
;
2607 if(*list
== context
)
2609 *list
= (*list
)->next
;
2612 list
= &(*list
)->next
;
2615 ALCdevice_Unlock(device
);
2617 ALCcontext_DecRef(context
);
2620 void ALCcontext_IncRef(ALCcontext
*context
)
2622 uint ref
= IncrementRef(&context
->ref
);
2623 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2626 void ALCcontext_DecRef(ALCcontext
*context
)
2628 uint ref
= DecrementRef(&context
->ref
);
2629 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2630 if(ref
== 0) FreeContext(context
);
2633 static void ReleaseThreadCtx(void *ptr
)
2635 ALCcontext
*context
= ptr
;
2636 uint ref
= DecrementRef(&context
->ref
);
2637 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2638 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2643 * Checks that the given context is valid, and increments its reference count.
2645 static ALCboolean
VerifyContext(ALCcontext
**context
)
2650 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2653 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2658 ALCcontext_IncRef(ctx
);
2675 * Returns the currently active context for this thread, and adds a reference
2676 * without locking it.
2678 ALCcontext
*GetContextRef(void)
2680 ALCcontext
*context
;
2682 context
= altss_get(LocalContext
);
2684 ALCcontext_IncRef(context
);
2688 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2690 ALCcontext_IncRef(context
);
2698 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2700 ALCdevice
*device
= context
->Device
;
2701 ALsizei num_sends
= device
->NumAuxSends
;
2702 struct ALsourceProps
*props
;
2703 size_t sizeof_props
;
2704 size_t sizeof_voice
;
2710 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2713 /* Allocate the voice pointers, voices, and the voices' stored source
2714 * property set (including the dynamically-sized Send[] array) in one
2717 sizeof_props
= RoundUp(offsetof(struct ALsourceProps
, Send
[num_sends
]), 16);
2718 sizeof_voice
= RoundUp(offsetof(ALvoice
, Send
[num_sends
]), 16);
2719 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2721 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2722 /* The voice and property objects are stored interleaved since they're
2725 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2726 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2730 ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2731 for(;v
< v_count
;v
++)
2733 ALsizei s_count
= mini(old_sends
, num_sends
);
2736 /* Copy the old voice data and source property set to the new
2739 *voice
= *(context
->Voices
[v
]);
2740 for(i
= 0;i
< s_count
;i
++)
2741 voice
->Send
[i
] = context
->Voices
[v
]->Send
[i
];
2742 *props
= *(context
->Voices
[v
]->Props
);
2743 for(i
= 0;i
< s_count
;i
++)
2744 props
->Send
[i
] = context
->Voices
[v
]->Props
->Send
[i
];
2746 /* Set this voice's property set pointer and voice reference. */
2747 voice
->Props
= props
;
2750 /* Increment pointers to the next storage space. */
2751 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2752 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2755 /* Finish setting the voices' property set pointers and references. */
2756 for(;v
< num_voices
;v
++)
2758 voice
->Props
= props
;
2761 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2762 props
= (struct ALsourceProps
*)((char*)voice
+ sizeof_voice
);
2765 al_free(context
->Voices
);
2766 context
->Voices
= voices
;
2767 context
->MaxVoices
= num_voices
;
2768 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2772 /************************************************
2773 * Standard ALC functions
2774 ************************************************/
2778 * Return last ALC generated error code for the given device
2780 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2784 if(VerifyDevice(&device
))
2786 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &device
->LastError
, ALC_NO_ERROR
);
2787 ALCdevice_DecRef(device
);
2790 errorCode
= ATOMIC_EXCHANGE_SEQ(ALCenum
, &LastNullDeviceError
, ALC_NO_ERROR
);
2796 /* alcSuspendContext
2798 * Suspends updates for the given context
2800 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2805 if(!VerifyContext(&context
))
2806 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2809 ALCcontext_DeferUpdates(context
, DeferAllowPlay
);
2810 ALCcontext_DecRef(context
);
2814 /* alcProcessContext
2816 * Resumes processing updates for the given context
2818 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2823 if(!VerifyContext(&context
))
2824 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2827 ALCcontext_ProcessUpdates(context
);
2828 ALCcontext_DecRef(context
);
2835 * Returns information about the device, and error strings
2837 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2839 const ALCchar
*value
= NULL
;
2847 case ALC_INVALID_ENUM
:
2848 value
= alcErrInvalidEnum
;
2851 case ALC_INVALID_VALUE
:
2852 value
= alcErrInvalidValue
;
2855 case ALC_INVALID_DEVICE
:
2856 value
= alcErrInvalidDevice
;
2859 case ALC_INVALID_CONTEXT
:
2860 value
= alcErrInvalidContext
;
2863 case ALC_OUT_OF_MEMORY
:
2864 value
= alcErrOutOfMemory
;
2867 case ALC_DEVICE_SPECIFIER
:
2868 value
= alcDefaultName
;
2871 case ALC_ALL_DEVICES_SPECIFIER
:
2872 if(VerifyDevice(&Device
))
2874 value
= al_string_get_cstr(Device
->DeviceName
);
2875 ALCdevice_DecRef(Device
);
2879 ProbeAllDevicesList();
2880 value
= al_string_get_cstr(alcAllDevicesList
);
2884 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2885 if(VerifyDevice(&Device
))
2887 value
= al_string_get_cstr(Device
->DeviceName
);
2888 ALCdevice_DecRef(Device
);
2892 ProbeCaptureDeviceList();
2893 value
= al_string_get_cstr(alcCaptureDeviceList
);
2897 /* Default devices are always first in the list */
2898 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2899 value
= alcDefaultName
;
2902 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2903 if(al_string_empty(alcAllDevicesList
))
2904 ProbeAllDevicesList();
2906 VerifyDevice(&Device
);
2908 free(alcDefaultAllDevicesSpecifier
);
2909 alcDefaultAllDevicesSpecifier
= strdup(al_string_get_cstr(alcAllDevicesList
));
2910 if(!alcDefaultAllDevicesSpecifier
)
2911 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2913 value
= alcDefaultAllDevicesSpecifier
;
2914 if(Device
) ALCdevice_DecRef(Device
);
2917 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2918 if(al_string_empty(alcCaptureDeviceList
))
2919 ProbeCaptureDeviceList();
2921 VerifyDevice(&Device
);
2923 free(alcCaptureDefaultDeviceSpecifier
);
2924 alcCaptureDefaultDeviceSpecifier
= strdup(al_string_get_cstr(alcCaptureDeviceList
));
2925 if(!alcCaptureDefaultDeviceSpecifier
)
2926 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2928 value
= alcCaptureDefaultDeviceSpecifier
;
2929 if(Device
) ALCdevice_DecRef(Device
);
2932 case ALC_EXTENSIONS
:
2933 if(!VerifyDevice(&Device
))
2934 value
= alcNoDeviceExtList
;
2937 value
= alcExtensionList
;
2938 ALCdevice_DecRef(Device
);
2942 case ALC_HRTF_SPECIFIER_SOFT
:
2943 if(!VerifyDevice(&Device
))
2944 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2947 almtx_lock(&Device
->BackendLock
);
2948 value
= (Device
->Hrtf
.Handle
? al_string_get_cstr(Device
->Hrtf
.Name
) : "");
2949 almtx_unlock(&Device
->BackendLock
);
2950 ALCdevice_DecRef(Device
);
2955 VerifyDevice(&Device
);
2956 alcSetError(Device
, ALC_INVALID_ENUM
);
2957 if(Device
) ALCdevice_DecRef(Device
);
2965 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2967 if(device
->Type
== Loopback
&& device
->FmtChans
>= DevFmtAmbi1
&&
2968 device
->FmtChans
<= DevFmtAmbi3
)
2973 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2977 if(size
<= 0 || values
== NULL
)
2979 alcSetError(device
, ALC_INVALID_VALUE
);
2987 case ALC_MAJOR_VERSION
:
2988 values
[0] = alcMajorVersion
;
2990 case ALC_MINOR_VERSION
:
2991 values
[0] = alcMinorVersion
;
2994 case ALC_ATTRIBUTES_SIZE
:
2995 case ALC_ALL_ATTRIBUTES
:
2999 case ALC_MONO_SOURCES
:
3000 case ALC_STEREO_SOURCES
:
3001 case ALC_CAPTURE_SAMPLES
:
3002 case ALC_FORMAT_CHANNELS_SOFT
:
3003 case ALC_FORMAT_TYPE_SOFT
:
3004 case ALC_AMBISONIC_LAYOUT_SOFT
:
3005 case ALC_AMBISONIC_SCALING_SOFT
:
3006 case ALC_AMBISONIC_ORDER_SOFT
:
3007 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3011 alcSetError(NULL
, ALC_INVALID_ENUM
);
3017 if(device
->Type
== Capture
)
3021 case ALC_CAPTURE_SAMPLES
:
3022 almtx_lock(&device
->BackendLock
);
3023 values
[0] = V0(device
->Backend
,availableSamples
)();
3024 almtx_unlock(&device
->BackendLock
);
3028 values
[0] = device
->Connected
;
3032 alcSetError(device
, ALC_INVALID_ENUM
);
3041 case ALC_MAJOR_VERSION
:
3042 values
[0] = alcMajorVersion
;
3045 case ALC_MINOR_VERSION
:
3046 values
[0] = alcMinorVersion
;
3049 case ALC_EFX_MAJOR_VERSION
:
3050 values
[0] = alcEFXMajorVersion
;
3053 case ALC_EFX_MINOR_VERSION
:
3054 values
[0] = alcEFXMinorVersion
;
3057 case ALC_ATTRIBUTES_SIZE
:
3058 values
[0] = NumAttrsForDevice(device
);
3061 case ALC_ALL_ATTRIBUTES
:
3062 if(size
< NumAttrsForDevice(device
))
3064 alcSetError(device
, ALC_INVALID_VALUE
);
3069 almtx_lock(&device
->BackendLock
);
3070 values
[i
++] = ALC_FREQUENCY
;
3071 values
[i
++] = device
->Frequency
;
3073 if(device
->Type
!= Loopback
)
3075 values
[i
++] = ALC_REFRESH
;
3076 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3078 values
[i
++] = ALC_SYNC
;
3079 values
[i
++] = ALC_FALSE
;
3083 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3085 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3086 values
[i
++] = ALC_BFORMAT3D_SOFT
;
3088 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3089 values
[i
++] = device
->AmbiLayout
;
3091 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3092 values
[i
++] = device
->AmbiScale
;
3094 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3095 values
[i
++] = device
->FmtChans
-DevFmtAmbi1
+1;
3099 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3100 values
[i
++] = device
->FmtChans
;
3103 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3104 values
[i
++] = device
->FmtType
;
3107 values
[i
++] = ALC_MONO_SOURCES
;
3108 values
[i
++] = device
->NumMonoSources
;
3110 values
[i
++] = ALC_STEREO_SOURCES
;
3111 values
[i
++] = device
->NumStereoSources
;
3113 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3114 values
[i
++] = device
->NumAuxSends
;
3116 values
[i
++] = ALC_HRTF_SOFT
;
3117 values
[i
++] = (device
->Hrtf
.Handle
? ALC_TRUE
: ALC_FALSE
);
3119 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3120 values
[i
++] = device
->Hrtf
.Status
;
3121 almtx_unlock(&device
->BackendLock
);
3127 values
[0] = device
->Frequency
;
3131 if(device
->Type
== Loopback
)
3133 alcSetError(device
, ALC_INVALID_DEVICE
);
3136 almtx_lock(&device
->BackendLock
);
3137 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3138 almtx_unlock(&device
->BackendLock
);
3142 if(device
->Type
== Loopback
)
3144 alcSetError(device
, ALC_INVALID_DEVICE
);
3147 values
[0] = ALC_FALSE
;
3150 case ALC_FORMAT_CHANNELS_SOFT
:
3151 if(device
->Type
!= Loopback
)
3153 alcSetError(device
, ALC_INVALID_DEVICE
);
3156 if(device
->FmtChans
>= DevFmtAmbi1
&& device
->FmtChans
<= DevFmtAmbi3
)
3157 values
[0] = ALC_BFORMAT3D_SOFT
;
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
>= DevFmtAmbi1
&&
3173 device
->FmtChans
<= DevFmtAmbi3
))
3175 alcSetError(device
, ALC_INVALID_DEVICE
);
3178 values
[0] = device
->AmbiLayout
;
3181 case ALC_AMBISONIC_SCALING_SOFT
:
3182 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3183 device
->FmtChans
<= DevFmtAmbi3
))
3185 alcSetError(device
, ALC_INVALID_DEVICE
);
3188 values
[0] = device
->AmbiScale
;
3191 case ALC_AMBISONIC_ORDER_SOFT
:
3192 if(device
->Type
!= Loopback
|| !(device
->FmtChans
>= DevFmtAmbi1
&&
3193 device
->FmtChans
<= DevFmtAmbi3
))
3195 alcSetError(device
, ALC_INVALID_DEVICE
);
3198 values
[0] = device
->FmtChans
- DevFmtAmbi1
+ 1;
3201 case ALC_MONO_SOURCES
:
3202 values
[0] = device
->NumMonoSources
;
3205 case ALC_STEREO_SOURCES
:
3206 values
[0] = device
->NumStereoSources
;
3209 case ALC_MAX_AUXILIARY_SENDS
:
3210 values
[0] = device
->NumAuxSends
;
3214 values
[0] = device
->Connected
;
3218 values
[0] = (device
->Hrtf
.Handle
? ALC_TRUE
: ALC_FALSE
);
3221 case ALC_HRTF_STATUS_SOFT
:
3222 values
[0] = device
->Hrtf
.Status
;
3225 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3226 almtx_lock(&device
->BackendLock
);
3227 FreeHrtfList(&device
->Hrtf
.List
);
3228 device
->Hrtf
.List
= EnumerateHrtf(device
->DeviceName
);
3229 values
[0] = (ALCint
)VECTOR_SIZE(device
->Hrtf
.List
);
3230 almtx_unlock(&device
->BackendLock
);
3234 alcSetError(device
, ALC_INVALID_ENUM
);
3242 * Returns information about the device and the version of OpenAL
3244 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3246 VerifyDevice(&device
);
3247 if(size
<= 0 || values
== NULL
)
3248 alcSetError(device
, ALC_INVALID_VALUE
);
3250 GetIntegerv(device
, param
, size
, values
);
3251 if(device
) ALCdevice_DecRef(device
);
3254 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3259 VerifyDevice(&device
);
3260 if(size
<= 0 || values
== NULL
)
3261 alcSetError(device
, ALC_INVALID_VALUE
);
3262 else if(!device
|| device
->Type
== Capture
)
3264 ivals
= malloc(size
* sizeof(ALCint
));
3265 size
= GetIntegerv(device
, pname
, size
, ivals
);
3266 for(i
= 0;i
< size
;i
++)
3267 values
[i
] = ivals
[i
];
3270 else /* render device */
3279 case ALC_ATTRIBUTES_SIZE
:
3283 case ALC_ALL_ATTRIBUTES
:
3285 alcSetError(device
, ALC_INVALID_VALUE
);
3289 almtx_lock(&device
->BackendLock
);
3290 values
[i
++] = ALC_FREQUENCY
;
3291 values
[i
++] = device
->Frequency
;
3293 if(device
->Type
!= Loopback
)
3295 values
[i
++] = ALC_REFRESH
;
3296 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3298 values
[i
++] = ALC_SYNC
;
3299 values
[i
++] = ALC_FALSE
;
3303 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3304 values
[i
++] = device
->FmtChans
;
3306 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3307 values
[i
++] = device
->FmtType
;
3310 values
[i
++] = ALC_MONO_SOURCES
;
3311 values
[i
++] = device
->NumMonoSources
;
3313 values
[i
++] = ALC_STEREO_SOURCES
;
3314 values
[i
++] = device
->NumStereoSources
;
3316 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3317 values
[i
++] = device
->NumAuxSends
;
3319 values
[i
++] = ALC_HRTF_SOFT
;
3320 values
[i
++] = (device
->Hrtf
.Handle
? ALC_TRUE
: ALC_FALSE
);
3322 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3323 values
[i
++] = device
->Hrtf
.Status
;
3325 clock
= V0(device
->Backend
,getClockLatency
)();
3326 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3327 values
[i
++] = clock
.ClockTime
;
3329 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3330 values
[i
++] = clock
.Latency
;
3331 almtx_unlock(&device
->BackendLock
);
3337 case ALC_DEVICE_CLOCK_SOFT
:
3338 almtx_lock(&device
->BackendLock
);
3340 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3342 basecount
= device
->ClockBase
;
3343 samplecount
= device
->SamplesDone
;
3344 } while(refcount
!= ReadRef(&device
->MixCount
));
3345 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3346 almtx_unlock(&device
->BackendLock
);
3349 case ALC_DEVICE_LATENCY_SOFT
:
3351 almtx_lock(&device
->BackendLock
);
3352 clock
= V0(device
->Backend
,getClockLatency
)();
3353 almtx_unlock(&device
->BackendLock
);
3354 *values
= clock
.Latency
;
3358 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3360 alcSetError(device
, ALC_INVALID_VALUE
);
3364 almtx_lock(&device
->BackendLock
);
3365 clock
= V0(device
->Backend
,getClockLatency
)();
3366 almtx_unlock(&device
->BackendLock
);
3367 values
[0] = clock
.ClockTime
;
3368 values
[1] = clock
.Latency
;
3373 ivals
= malloc(size
* sizeof(ALCint
));
3374 size
= GetIntegerv(device
, pname
, size
, ivals
);
3375 for(i
= 0;i
< size
;i
++)
3376 values
[i
] = ivals
[i
];
3382 ALCdevice_DecRef(device
);
3386 /* alcIsExtensionPresent
3388 * Determines if there is support for a particular extension
3390 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3392 ALCboolean bResult
= ALC_FALSE
;
3394 VerifyDevice(&device
);
3397 alcSetError(device
, ALC_INVALID_VALUE
);
3400 size_t len
= strlen(extName
);
3401 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3404 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3405 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3410 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3414 } while(isspace(*ptr
));
3419 ALCdevice_DecRef(device
);
3424 /* alcGetProcAddress
3426 * Retrieves the function address for a particular extension function
3428 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3430 ALCvoid
*ptr
= NULL
;
3434 VerifyDevice(&device
);
3435 alcSetError(device
, ALC_INVALID_VALUE
);
3436 if(device
) ALCdevice_DecRef(device
);
3441 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
3443 ptr
= alcFunctions
[i
].address
;
3452 * Get the value for a particular ALC enumeration name
3454 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3460 VerifyDevice(&device
);
3461 alcSetError(device
, ALC_INVALID_VALUE
);
3462 if(device
) ALCdevice_DecRef(device
);
3467 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
3469 val
= enumeration
[i
].value
;
3478 * Create and attach a context to the given device.
3480 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3482 ALCcontext
*ALContext
;
3487 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3490 alcSetError(device
, ALC_INVALID_DEVICE
);
3491 if(device
) ALCdevice_DecRef(device
);
3494 almtx_lock(&device
->BackendLock
);
3497 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3499 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3502 InitRef(&ALContext
->ref
, 1);
3503 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3505 ALContext
->Device
= device
;
3506 ATOMIC_INIT(&ALContext
->ActiveAuxSlotList
, NULL
);
3508 ALContext
->Voices
= NULL
;
3509 ALContext
->MaxVoices
= 0;
3510 ALContext
->VoiceCount
= 0;
3511 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3513 if(!ALContext
|| !ALContext
->Voices
)
3515 almtx_unlock(&device
->BackendLock
);
3519 al_free(ALContext
->Voices
);
3520 ALContext
->Voices
= NULL
;
3526 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3527 ALCdevice_DecRef(device
);
3531 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3533 almtx_unlock(&device
->BackendLock
);
3535 al_free(ALContext
->Voices
);
3536 ALContext
->Voices
= NULL
;
3541 alcSetError(device
, err
);
3542 if(err
== ALC_INVALID_DEVICE
)
3544 V0(device
->Backend
,lock
)();
3545 aluHandleDisconnect(device
);
3546 V0(device
->Backend
,unlock
)();
3548 ALCdevice_DecRef(device
);
3552 ALCdevice_IncRef(ALContext
->Device
);
3553 InitContext(ALContext
);
3555 if(ConfigValueFloat(al_string_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3558 ERR("volume-adjust must be finite: %f\n", valf
);
3561 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3563 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3564 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3565 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3568 UpdateListenerProps(ALContext
);
3571 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3573 ALContext
->next
= head
;
3574 } while(ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCcontext
*,
3575 &device
->ContextList
, &head
, ALContext
) == 0);
3577 almtx_unlock(&device
->BackendLock
);
3579 ALCdevice_DecRef(device
);
3581 TRACE("Created context %p\n", ALContext
);
3585 /* alcDestroyContext
3587 * Remove a context from its device
3589 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3594 /* alcGetContextsDevice sets an error for invalid contexts */
3595 Device
= alcGetContextsDevice(context
);
3598 almtx_lock(&Device
->BackendLock
);
3599 ReleaseContext(context
, Device
);
3600 if(!ATOMIC_LOAD_SEQ(&Device
->ContextList
))
3602 V0(Device
->Backend
,stop
)();
3603 Device
->Flags
&= ~DEVICE_RUNNING
;
3605 almtx_unlock(&Device
->BackendLock
);
3611 /* alcGetCurrentContext
3613 * Returns the currently active context on the calling thread
3615 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3617 ALCcontext
*Context
= altss_get(LocalContext
);
3618 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3622 /* alcGetThreadContext
3624 * Returns the currently active thread-local context
3626 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3628 return altss_get(LocalContext
);
3632 /* alcMakeContextCurrent
3634 * Makes the given context the active process-wide context, and removes the
3635 * thread-local context for the calling thread.
3637 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3639 /* context must be valid or NULL */
3640 if(context
&& !VerifyContext(&context
))
3642 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3645 /* context's reference count is already incremented */
3646 context
= ATOMIC_EXCHANGE_SEQ(ALCcontext
*, &GlobalContext
, context
);
3647 if(context
) ALCcontext_DecRef(context
);
3649 if((context
=altss_get(LocalContext
)) != NULL
)
3651 altss_set(LocalContext
, NULL
);
3652 ALCcontext_DecRef(context
);
3658 /* alcSetThreadContext
3660 * Makes the given context the active context for the current thread
3662 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(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 old
= altss_get(LocalContext
);
3674 altss_set(LocalContext
, context
);
3675 if(old
) ALCcontext_DecRef(old
);
3681 /* alcGetContextsDevice
3683 * Returns the device that a particular context is attached to
3685 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3689 if(!VerifyContext(&Context
))
3691 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3694 Device
= Context
->Device
;
3695 ALCcontext_DecRef(Context
);
3703 * Opens the named device.
3705 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3714 if(!PlaybackBackend
.name
)
3716 alcSetError(NULL
, ALC_INVALID_VALUE
);
3720 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3722 /* Some old Windows apps hardcode these expecting OpenAL to use a
3723 * specific audio API, even when they're not enumerated. Creative's
3724 * router effectively ignores them too.
3726 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3727 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3732 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3735 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3740 InitRef(&device
->ref
, 1);
3741 device
->Connected
= ALC_TRUE
;
3742 device
->Type
= Playback
;
3743 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3746 device
->Bs2b
= NULL
;
3747 device
->Uhj_Encoder
= NULL
;
3748 VECTOR_INIT(device
->Hrtf
.List
);
3749 AL_STRING_INIT(device
->Hrtf
.Name
);
3750 device
->Render_Mode
= NormalRender
;
3751 AL_STRING_INIT(device
->DeviceName
);
3752 device
->Dry
.Buffer
= NULL
;
3753 device
->Dry
.NumChannels
= 0;
3754 device
->FOAOut
.Buffer
= NULL
;
3755 device
->FOAOut
.NumChannels
= 0;
3756 device
->RealOut
.Buffer
= NULL
;
3757 device
->RealOut
.NumChannels
= 0;
3759 ATOMIC_INIT(&device
->ContextList
, NULL
);
3761 device
->ClockBase
= 0;
3762 device
->SamplesDone
= 0;
3764 device
->SourcesMax
= 256;
3765 device
->AuxiliaryEffectSlotMax
= 64;
3766 device
->NumAuxSends
= DEFAULT_SENDS
;
3768 InitUIntMap(&device
->BufferMap
, ~0);
3769 InitUIntMap(&device
->EffectMap
, ~0);
3770 InitUIntMap(&device
->FilterMap
, ~0);
3772 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3774 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3775 device
->ChannelDelay
[i
].Length
= 0;
3776 device
->ChannelDelay
[i
].Buffer
= NULL
;
3780 device
->FmtChans
= DevFmtChannelsDefault
;
3781 device
->FmtType
= DevFmtTypeDefault
;
3782 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3783 device
->IsHeadphones
= AL_FALSE
;
3784 device
->AmbiLayout
= AmbiLayout_Default
;
3785 device
->AmbiScale
= AmbiNorm_Default
;
3786 device
->NumUpdates
= 3;
3787 device
->UpdateSize
= 1024;
3789 if(!PlaybackBackend
.getFactory
)
3790 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3791 ALCbackend_Playback
);
3794 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3795 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3797 if(!device
->Backend
)
3800 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3805 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3807 static const struct {
3808 const char name
[16];
3809 enum DevFmtChannels chans
;
3811 { "mono", DevFmtMono
},
3812 { "stereo", DevFmtStereo
},
3813 { "quad", DevFmtQuad
},
3814 { "surround51", DevFmtX51
},
3815 { "surround61", DevFmtX61
},
3816 { "surround71", DevFmtX71
},
3817 { "surround51rear", DevFmtX51Rear
},
3818 { "ambi1", DevFmtAmbi1
},
3819 { "ambi2", DevFmtAmbi2
},
3820 { "ambi3", DevFmtAmbi3
},
3824 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3826 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3828 device
->FmtChans
= chanlist
[i
].chans
;
3829 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3833 if(i
== COUNTOF(chanlist
))
3834 ERR("Unsupported channels: %s\n", fmt
);
3836 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3838 static const struct {
3839 const char name
[16];
3840 enum DevFmtType type
;
3842 { "int8", DevFmtByte
},
3843 { "uint8", DevFmtUByte
},
3844 { "int16", DevFmtShort
},
3845 { "uint16", DevFmtUShort
},
3846 { "int32", DevFmtInt
},
3847 { "uint32", DevFmtUInt
},
3848 { "float32", DevFmtFloat
},
3852 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3854 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3856 device
->FmtType
= typelist
[i
].type
;
3857 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3861 if(i
== COUNTOF(typelist
))
3862 ERR("Unsupported sample-type: %s\n", fmt
);
3865 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3867 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3868 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3869 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3870 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3873 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3874 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3876 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3877 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3878 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3879 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3881 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3882 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3884 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3885 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3887 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3888 device
->NumAuxSends
= clampi(
3889 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3892 device
->NumStereoSources
= 1;
3893 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3895 // Find a playback device to open
3896 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3898 DELETE_OBJ(device
->Backend
);
3900 alcSetError(NULL
, err
);
3903 almtx_init(&device
->BackendLock
, almtx_plain
);
3905 if(ConfigValueStr(al_string_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3907 if(strcasecmp(fmt
, "fuma") == 0)
3909 device
->AmbiLayout
= AmbiLayout_FuMa
;
3910 device
->AmbiScale
= AmbiNorm_FuMa
;
3912 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3914 device
->AmbiLayout
= AmbiLayout_ACN
;
3915 device
->AmbiScale
= AmbiNorm_SN3D
;
3917 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3919 device
->AmbiLayout
= AmbiLayout_ACN
;
3920 device
->AmbiScale
= AmbiNorm_N3D
;
3923 ERR("Unsupported ambi-format: %s\n", fmt
);
3926 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3928 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3929 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3931 device
->DefaultSlot
= NULL
;
3932 ERR("Failed to initialize the default effect slot\n");
3936 aluInitEffectPanning(device
->DefaultSlot
);
3937 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3939 DeinitEffectSlot(device
->DefaultSlot
);
3940 device
->DefaultSlot
= NULL
;
3941 ERR("Failed to initialize the default effect\n");
3947 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
3949 device
->next
= head
;
3950 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
3953 TRACE("Created device %p, \"%s\"\n", device
, al_string_get_cstr(device
->DeviceName
));
3959 * Closes the given device.
3961 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3963 ALCdevice
*iter
, *origdev
;
3967 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
3971 } while((iter
=iter
->next
) != NULL
);
3972 if(!iter
|| iter
->Type
== Capture
)
3974 alcSetError(iter
, ALC_INVALID_DEVICE
);
3978 almtx_lock(&device
->BackendLock
);
3981 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
3983 ALCdevice
*volatile*list
= &origdev
->next
;
3988 *list
= (*list
)->next
;
3991 list
= &(*list
)->next
;
3996 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3999 ALCcontext
*next
= ctx
->next
;
4000 WARN("Releasing context %p\n", ctx
);
4001 ReleaseContext(ctx
, device
);
4004 if((device
->Flags
&DEVICE_RUNNING
))
4005 V0(device
->Backend
,stop
)();
4006 device
->Flags
&= ~DEVICE_RUNNING
;
4007 almtx_unlock(&device
->BackendLock
);
4009 ALCdevice_DecRef(device
);
4015 /************************************************
4016 * ALC capture functions
4017 ************************************************/
4018 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4020 ALCdevice
*device
= NULL
;
4026 if(!CaptureBackend
.name
)
4028 alcSetError(NULL
, ALC_INVALID_VALUE
);
4034 alcSetError(NULL
, ALC_INVALID_VALUE
);
4038 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4041 device
= al_calloc(16, sizeof(ALCdevice
));
4044 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4049 InitRef(&device
->ref
, 1);
4050 device
->Connected
= ALC_TRUE
;
4051 device
->Type
= Capture
;
4053 VECTOR_INIT(device
->Hrtf
.List
);
4054 AL_STRING_INIT(device
->Hrtf
.Name
);
4056 AL_STRING_INIT(device
->DeviceName
);
4057 device
->Dry
.Buffer
= NULL
;
4058 device
->Dry
.NumChannels
= 0;
4059 device
->FOAOut
.Buffer
= NULL
;
4060 device
->FOAOut
.NumChannels
= 0;
4061 device
->RealOut
.Buffer
= NULL
;
4062 device
->RealOut
.NumChannels
= 0;
4064 InitUIntMap(&device
->BufferMap
, ~0);
4065 InitUIntMap(&device
->EffectMap
, ~0);
4066 InitUIntMap(&device
->FilterMap
, ~0);
4068 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4070 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4071 device
->ChannelDelay
[i
].Length
= 0;
4072 device
->ChannelDelay
[i
].Buffer
= NULL
;
4075 if(!CaptureBackend
.getFactory
)
4076 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4077 ALCbackend_Capture
);
4080 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4081 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4083 if(!device
->Backend
)
4086 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4090 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4091 device
->Frequency
= frequency
;
4093 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4094 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4097 alcSetError(NULL
, ALC_INVALID_ENUM
);
4100 device
->IsHeadphones
= AL_FALSE
;
4101 device
->AmbiLayout
= AmbiLayout_Default
;
4102 device
->AmbiScale
= AmbiNorm_Default
;
4104 device
->UpdateSize
= samples
;
4105 device
->NumUpdates
= 1;
4107 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4110 alcSetError(NULL
, err
);
4113 almtx_init(&device
->BackendLock
, almtx_plain
);
4116 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4118 device
->next
= head
;
4119 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4122 TRACE("Created device %p, \"%s\"\n", device
, al_string_get_cstr(device
->DeviceName
));
4126 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4128 ALCdevice
*iter
, *origdev
;
4131 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4135 } while((iter
=iter
->next
) != NULL
);
4136 if(!iter
|| iter
->Type
!= Capture
)
4138 alcSetError(iter
, ALC_INVALID_DEVICE
);
4144 if(!ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(ALCdevice
*, &DeviceList
, &origdev
, device
->next
))
4146 ALCdevice
*volatile*list
= &origdev
->next
;
4151 *list
= (*list
)->next
;
4154 list
= &(*list
)->next
;
4159 ALCdevice_DecRef(device
);
4164 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4166 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4167 alcSetError(device
, ALC_INVALID_DEVICE
);
4170 almtx_lock(&device
->BackendLock
);
4171 if(!device
->Connected
)
4172 alcSetError(device
, ALC_INVALID_DEVICE
);
4173 else if(!(device
->Flags
&DEVICE_RUNNING
))
4175 if(V0(device
->Backend
,start
)())
4176 device
->Flags
|= DEVICE_RUNNING
;
4179 aluHandleDisconnect(device
);
4180 alcSetError(device
, ALC_INVALID_DEVICE
);
4183 almtx_unlock(&device
->BackendLock
);
4186 if(device
) ALCdevice_DecRef(device
);
4189 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4191 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4192 alcSetError(device
, ALC_INVALID_DEVICE
);
4195 almtx_lock(&device
->BackendLock
);
4196 if((device
->Flags
&DEVICE_RUNNING
))
4197 V0(device
->Backend
,stop
)();
4198 device
->Flags
&= ~DEVICE_RUNNING
;
4199 almtx_unlock(&device
->BackendLock
);
4202 if(device
) ALCdevice_DecRef(device
);
4205 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4207 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4208 alcSetError(device
, ALC_INVALID_DEVICE
);
4211 ALCenum err
= ALC_INVALID_VALUE
;
4213 almtx_lock(&device
->BackendLock
);
4214 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4215 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4216 almtx_unlock(&device
->BackendLock
);
4218 if(err
!= ALC_NO_ERROR
)
4219 alcSetError(device
, err
);
4221 if(device
) ALCdevice_DecRef(device
);
4225 /************************************************
4226 * ALC loopback functions
4227 ************************************************/
4229 /* alcLoopbackOpenDeviceSOFT
4231 * Open a loopback device, for manual rendering.
4233 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4235 ALCbackendFactory
*factory
;
4241 /* Make sure the device name, if specified, is us. */
4242 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4244 alcSetError(NULL
, ALC_INVALID_VALUE
);
4248 device
= al_calloc(16, sizeof(ALCdevice
));
4251 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4256 InitRef(&device
->ref
, 1);
4257 device
->Connected
= ALC_TRUE
;
4258 device
->Type
= Loopback
;
4259 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4262 VECTOR_INIT(device
->Hrtf
.List
);
4263 AL_STRING_INIT(device
->Hrtf
.Name
);
4264 device
->Bs2b
= NULL
;
4265 device
->Uhj_Encoder
= NULL
;
4266 device
->Render_Mode
= NormalRender
;
4267 AL_STRING_INIT(device
->DeviceName
);
4268 device
->Dry
.Buffer
= NULL
;
4269 device
->Dry
.NumChannels
= 0;
4270 device
->FOAOut
.Buffer
= NULL
;
4271 device
->FOAOut
.NumChannels
= 0;
4272 device
->RealOut
.Buffer
= NULL
;
4273 device
->RealOut
.NumChannels
= 0;
4275 ATOMIC_INIT(&device
->ContextList
, NULL
);
4277 device
->ClockBase
= 0;
4278 device
->SamplesDone
= 0;
4280 device
->SourcesMax
= 256;
4281 device
->AuxiliaryEffectSlotMax
= 64;
4282 device
->NumAuxSends
= DEFAULT_SENDS
;
4284 InitUIntMap(&device
->BufferMap
, ~0);
4285 InitUIntMap(&device
->EffectMap
, ~0);
4286 InitUIntMap(&device
->FilterMap
, ~0);
4288 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4290 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4291 device
->ChannelDelay
[i
].Length
= 0;
4292 device
->ChannelDelay
[i
].Buffer
= NULL
;
4295 factory
= ALCloopbackFactory_getFactory();
4296 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4297 if(!device
->Backend
)
4300 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4303 almtx_init(&device
->BackendLock
, almtx_plain
);
4306 device
->NumUpdates
= 0;
4307 device
->UpdateSize
= 0;
4309 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4310 device
->FmtChans
= DevFmtChannelsDefault
;
4311 device
->FmtType
= DevFmtTypeDefault
;
4312 device
->IsHeadphones
= AL_FALSE
;
4313 device
->AmbiLayout
= AmbiLayout_Default
;
4314 device
->AmbiScale
= AmbiNorm_Default
;
4316 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4317 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4319 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4320 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4322 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4323 device
->NumAuxSends
= clampi(
4324 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4327 device
->NumStereoSources
= 1;
4328 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4330 // Open the "backend"
4331 V(device
->Backend
,open
)("Loopback");
4334 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4336 device
->next
= head
;
4337 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK_SEQ(ALCdevice
*, &DeviceList
, &head
, device
));
4340 TRACE("Created device %p\n", device
);
4344 /* alcIsRenderFormatSupportedSOFT
4346 * Determines if the loopback device supports the given format for rendering.
4348 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4350 ALCboolean ret
= ALC_FALSE
;
4352 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4353 alcSetError(device
, ALC_INVALID_DEVICE
);
4355 alcSetError(device
, ALC_INVALID_VALUE
);
4358 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4361 if(device
) ALCdevice_DecRef(device
);
4366 /* alcRenderSamplesSOFT
4368 * Renders some samples into a buffer, using the format last set by the
4369 * attributes given to alcCreateContext.
4371 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4373 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4374 alcSetError(device
, ALC_INVALID_DEVICE
);
4375 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4376 alcSetError(device
, ALC_INVALID_VALUE
);
4379 V0(device
->Backend
,lock
)();
4380 aluMixData(device
, buffer
, samples
);
4381 V0(device
->Backend
,unlock
)();
4383 if(device
) ALCdevice_DecRef(device
);
4387 /************************************************
4388 * ALC loopback2 functions
4389 ************************************************/
4391 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4393 ALCboolean ret
= ALC_FALSE
;
4395 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4396 alcSetError(device
, ALC_INVALID_DEVICE
);
4398 alcSetError(device
, ALC_INVALID_VALUE
);
4401 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4404 if(device
) ALCdevice_DecRef(device
);
4409 /************************************************
4410 * ALC DSP pause/resume functions
4411 ************************************************/
4413 /* alcDevicePauseSOFT
4415 * Pause the DSP to stop audio processing.
4417 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4419 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4420 alcSetError(device
, ALC_INVALID_DEVICE
);
4423 almtx_lock(&device
->BackendLock
);
4424 if((device
->Flags
&DEVICE_RUNNING
))
4425 V0(device
->Backend
,stop
)();
4426 device
->Flags
&= ~DEVICE_RUNNING
;
4427 device
->Flags
|= DEVICE_PAUSED
;
4428 almtx_unlock(&device
->BackendLock
);
4430 if(device
) ALCdevice_DecRef(device
);
4433 /* alcDeviceResumeSOFT
4435 * Resume the DSP to restart audio processing.
4437 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4439 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4440 alcSetError(device
, ALC_INVALID_DEVICE
);
4443 almtx_lock(&device
->BackendLock
);
4444 if((device
->Flags
&DEVICE_PAUSED
))
4446 device
->Flags
&= ~DEVICE_PAUSED
;
4447 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4449 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4450 device
->Flags
|= DEVICE_RUNNING
;
4453 alcSetError(device
, ALC_INVALID_DEVICE
);
4454 V0(device
->Backend
,lock
)();
4455 aluHandleDisconnect(device
);
4456 V0(device
->Backend
,unlock
)();
4460 almtx_unlock(&device
->BackendLock
);
4462 if(device
) ALCdevice_DecRef(device
);
4466 /************************************************
4467 * ALC HRTF functions
4468 ************************************************/
4470 /* alcGetStringiSOFT
4472 * Gets a string parameter at the given index.
4474 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4476 const ALCchar
*str
= NULL
;
4478 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4479 alcSetError(device
, ALC_INVALID_DEVICE
);
4480 else switch(paramName
)
4482 case ALC_HRTF_SPECIFIER_SOFT
:
4483 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->Hrtf
.List
))
4484 str
= al_string_get_cstr(VECTOR_ELEM(device
->Hrtf
.List
, index
).name
);
4486 alcSetError(device
, ALC_INVALID_VALUE
);
4490 alcSetError(device
, ALC_INVALID_ENUM
);
4493 if(device
) ALCdevice_DecRef(device
);
4498 /* alcResetDeviceSOFT
4500 * Resets the given device output, using the specified attribute list.
4502 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4507 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4510 alcSetError(device
, ALC_INVALID_DEVICE
);
4511 if(device
) ALCdevice_DecRef(device
);
4514 almtx_lock(&device
->BackendLock
);
4517 err
= UpdateDeviceParams(device
, attribs
);
4518 almtx_unlock(&device
->BackendLock
);
4520 if(err
!= ALC_NO_ERROR
)
4522 alcSetError(device
, err
);
4523 if(err
== ALC_INVALID_DEVICE
)
4525 V0(device
->Backend
,lock
)();
4526 aluHandleDisconnect(device
);
4527 V0(device
->Backend
,unlock
)();
4529 ALCdevice_DecRef(device
);
4532 ALCdevice_DecRef(device
);