2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
34 #include "alListener.h"
38 #include "alAuxEffectSlot.h"
40 #include "bformatdec.h"
48 #include "backends/base.h"
51 /************************************************
53 ************************************************/
56 ALCbackendFactory
* (*getFactory
)(void);
57 ALCboolean (*Init
)(BackendFuncs
*);
59 void (*Probe
)(enum DevProbe
);
63 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
64 static struct BackendInfo BackendList
[] = {
66 { "jack", ALCjackBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
68 #ifdef HAVE_PULSEAUDIO
69 { "pulse", ALCpulseBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
72 { "alsa", ALCalsaBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
75 { "core", ALCcoreAudioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
78 { "oss", ALCossBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
81 { "solaris", ALCsolarisBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
84 { "sndio", ALCsndioBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
87 { "qsa", NULL
, alc_qsa_init
, alc_qsa_deinit
, alc_qsa_probe
, EmptyFuncs
},
90 { "mmdevapi", ALCmmdevBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
93 { "dsound", ALCdsoundBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
96 { "winmm", ALCwinmmBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
99 { "port", ALCportBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
102 { "opensl", ALCopenslBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
105 { "null", ALCnullBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
107 { "wave", ALCwaveBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
110 static ALsizei BackendListSize
= COUNTOF(BackendList
);
113 static struct BackendInfo PlaybackBackend
;
114 static struct BackendInfo CaptureBackend
;
117 /************************************************
118 * Functions, enums, and errors
119 ************************************************/
120 #define DECL(x) { #x, (ALCvoid*)(x) }
121 static const struct {
122 const ALCchar
*funcName
;
125 DECL(alcCreateContext
),
126 DECL(alcMakeContextCurrent
),
127 DECL(alcProcessContext
),
128 DECL(alcSuspendContext
),
129 DECL(alcDestroyContext
),
130 DECL(alcGetCurrentContext
),
131 DECL(alcGetContextsDevice
),
133 DECL(alcCloseDevice
),
135 DECL(alcIsExtensionPresent
),
136 DECL(alcGetProcAddress
),
137 DECL(alcGetEnumValue
),
139 DECL(alcGetIntegerv
),
140 DECL(alcCaptureOpenDevice
),
141 DECL(alcCaptureCloseDevice
),
142 DECL(alcCaptureStart
),
143 DECL(alcCaptureStop
),
144 DECL(alcCaptureSamples
),
146 DECL(alcSetThreadContext
),
147 DECL(alcGetThreadContext
),
149 DECL(alcLoopbackOpenDeviceSOFT
),
150 DECL(alcIsRenderFormatSupportedSOFT
),
151 DECL(alcRenderSamplesSOFT
),
153 DECL(alcIsAmbisonicFormatSupportedSOFT
),
155 DECL(alcDevicePauseSOFT
),
156 DECL(alcDeviceResumeSOFT
),
158 DECL(alcGetStringiSOFT
),
159 DECL(alcResetDeviceSOFT
),
161 DECL(alcGetInteger64vSOFT
),
176 DECL(alIsExtensionPresent
),
177 DECL(alGetProcAddress
),
178 DECL(alGetEnumValue
),
185 DECL(alGetListenerf
),
186 DECL(alGetListener3f
),
187 DECL(alGetListenerfv
),
188 DECL(alGetListeneri
),
189 DECL(alGetListener3i
),
190 DECL(alGetListeneriv
),
192 DECL(alDeleteSources
),
208 DECL(alSourceRewindv
),
209 DECL(alSourcePausev
),
212 DECL(alSourceRewind
),
214 DECL(alSourceQueueBuffers
),
215 DECL(alSourceUnqueueBuffers
),
217 DECL(alDeleteBuffers
),
232 DECL(alDopplerFactor
),
233 DECL(alDopplerVelocity
),
234 DECL(alSpeedOfSound
),
235 DECL(alDistanceModel
),
238 DECL(alDeleteFilters
),
249 DECL(alDeleteEffects
),
259 DECL(alGenAuxiliaryEffectSlots
),
260 DECL(alDeleteAuxiliaryEffectSlots
),
261 DECL(alIsAuxiliaryEffectSlot
),
262 DECL(alAuxiliaryEffectSloti
),
263 DECL(alAuxiliaryEffectSlotiv
),
264 DECL(alAuxiliaryEffectSlotf
),
265 DECL(alAuxiliaryEffectSlotfv
),
266 DECL(alGetAuxiliaryEffectSloti
),
267 DECL(alGetAuxiliaryEffectSlotiv
),
268 DECL(alGetAuxiliaryEffectSlotf
),
269 DECL(alGetAuxiliaryEffectSlotfv
),
271 DECL(alDeferUpdatesSOFT
),
272 DECL(alProcessUpdatesSOFT
),
275 DECL(alSource3dSOFT
),
276 DECL(alSourcedvSOFT
),
277 DECL(alGetSourcedSOFT
),
278 DECL(alGetSource3dSOFT
),
279 DECL(alGetSourcedvSOFT
),
280 DECL(alSourcei64SOFT
),
281 DECL(alSource3i64SOFT
),
282 DECL(alSourcei64vSOFT
),
283 DECL(alGetSourcei64SOFT
),
284 DECL(alGetSource3i64SOFT
),
285 DECL(alGetSourcei64vSOFT
),
287 DECL(alBufferSamplesSOFT
),
288 DECL(alGetBufferSamplesSOFT
),
289 DECL(alIsBufferFormatSupportedSOFT
),
293 #define DECL(x) { #x, (x) }
294 static const struct {
295 const ALCchar
*enumName
;
297 } alcEnumerations
[] = {
302 DECL(ALC_MAJOR_VERSION
),
303 DECL(ALC_MINOR_VERSION
),
304 DECL(ALC_ATTRIBUTES_SIZE
),
305 DECL(ALC_ALL_ATTRIBUTES
),
306 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
307 DECL(ALC_DEVICE_SPECIFIER
),
308 DECL(ALC_ALL_DEVICES_SPECIFIER
),
309 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
310 DECL(ALC_EXTENSIONS
),
314 DECL(ALC_MONO_SOURCES
),
315 DECL(ALC_STEREO_SOURCES
),
316 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
317 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
318 DECL(ALC_CAPTURE_SAMPLES
),
321 DECL(ALC_EFX_MAJOR_VERSION
),
322 DECL(ALC_EFX_MINOR_VERSION
),
323 DECL(ALC_MAX_AUXILIARY_SENDS
),
325 DECL(ALC_FORMAT_CHANNELS_SOFT
),
326 DECL(ALC_FORMAT_TYPE_SOFT
),
329 DECL(ALC_STEREO_SOFT
),
331 DECL(ALC_5POINT1_SOFT
),
332 DECL(ALC_6POINT1_SOFT
),
333 DECL(ALC_7POINT1_SOFT
),
334 DECL(ALC_BFORMAT3D_SOFT
),
337 DECL(ALC_UNSIGNED_BYTE_SOFT
),
338 DECL(ALC_SHORT_SOFT
),
339 DECL(ALC_UNSIGNED_SHORT_SOFT
),
341 DECL(ALC_UNSIGNED_INT_SOFT
),
342 DECL(ALC_FLOAT_SOFT
),
345 DECL(ALC_DONT_CARE_SOFT
),
346 DECL(ALC_HRTF_STATUS_SOFT
),
347 DECL(ALC_HRTF_DISABLED_SOFT
),
348 DECL(ALC_HRTF_ENABLED_SOFT
),
349 DECL(ALC_HRTF_DENIED_SOFT
),
350 DECL(ALC_HRTF_REQUIRED_SOFT
),
351 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
352 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
353 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
354 DECL(ALC_HRTF_SPECIFIER_SOFT
),
355 DECL(ALC_HRTF_ID_SOFT
),
357 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
358 DECL(ALC_AMBISONIC_SCALING_SOFT
),
359 DECL(ALC_AMBISONIC_ORDER_SOFT
),
366 DECL(ALC_INVALID_DEVICE
),
367 DECL(ALC_INVALID_CONTEXT
),
368 DECL(ALC_INVALID_ENUM
),
369 DECL(ALC_INVALID_VALUE
),
370 DECL(ALC_OUT_OF_MEMORY
),
378 DECL(AL_SOURCE_RELATIVE
),
379 DECL(AL_CONE_INNER_ANGLE
),
380 DECL(AL_CONE_OUTER_ANGLE
),
390 DECL(AL_ORIENTATION
),
391 DECL(AL_REFERENCE_DISTANCE
),
392 DECL(AL_ROLLOFF_FACTOR
),
393 DECL(AL_CONE_OUTER_GAIN
),
394 DECL(AL_MAX_DISTANCE
),
396 DECL(AL_SAMPLE_OFFSET
),
397 DECL(AL_BYTE_OFFSET
),
398 DECL(AL_SOURCE_TYPE
),
401 DECL(AL_UNDETERMINED
),
402 DECL(AL_METERS_PER_UNIT
),
403 DECL(AL_LOOP_POINTS_SOFT
),
404 DECL(AL_DIRECT_CHANNELS_SOFT
),
406 DECL(AL_DIRECT_FILTER
),
407 DECL(AL_AUXILIARY_SEND_FILTER
),
408 DECL(AL_AIR_ABSORPTION_FACTOR
),
409 DECL(AL_ROOM_ROLLOFF_FACTOR
),
410 DECL(AL_CONE_OUTER_GAINHF
),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
415 DECL(AL_SOURCE_STATE
),
421 DECL(AL_BUFFERS_QUEUED
),
422 DECL(AL_BUFFERS_PROCESSED
),
424 DECL(AL_FORMAT_MONO8
),
425 DECL(AL_FORMAT_MONO16
),
426 DECL(AL_FORMAT_MONO_FLOAT32
),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
428 DECL(AL_FORMAT_STEREO8
),
429 DECL(AL_FORMAT_STEREO16
),
430 DECL(AL_FORMAT_STEREO_FLOAT32
),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
432 DECL(AL_FORMAT_MONO_IMA4
),
433 DECL(AL_FORMAT_STEREO_IMA4
),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
436 DECL(AL_FORMAT_QUAD8_LOKI
),
437 DECL(AL_FORMAT_QUAD16_LOKI
),
438 DECL(AL_FORMAT_QUAD8
),
439 DECL(AL_FORMAT_QUAD16
),
440 DECL(AL_FORMAT_QUAD32
),
441 DECL(AL_FORMAT_51CHN8
),
442 DECL(AL_FORMAT_51CHN16
),
443 DECL(AL_FORMAT_51CHN32
),
444 DECL(AL_FORMAT_61CHN8
),
445 DECL(AL_FORMAT_61CHN16
),
446 DECL(AL_FORMAT_61CHN32
),
447 DECL(AL_FORMAT_71CHN8
),
448 DECL(AL_FORMAT_71CHN16
),
449 DECL(AL_FORMAT_71CHN32
),
450 DECL(AL_FORMAT_REAR8
),
451 DECL(AL_FORMAT_REAR16
),
452 DECL(AL_FORMAT_REAR32
),
453 DECL(AL_FORMAT_MONO_MULAW
),
454 DECL(AL_FORMAT_MONO_MULAW_EXT
),
455 DECL(AL_FORMAT_STEREO_MULAW
),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
457 DECL(AL_FORMAT_QUAD_MULAW
),
458 DECL(AL_FORMAT_51CHN_MULAW
),
459 DECL(AL_FORMAT_61CHN_MULAW
),
460 DECL(AL_FORMAT_71CHN_MULAW
),
461 DECL(AL_FORMAT_REAR_MULAW
),
462 DECL(AL_FORMAT_MONO_ALAW_EXT
),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
465 DECL(AL_FORMAT_BFORMAT2D_8
),
466 DECL(AL_FORMAT_BFORMAT2D_16
),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
469 DECL(AL_FORMAT_BFORMAT3D_8
),
470 DECL(AL_FORMAT_BFORMAT3D_16
),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
475 DECL(AL_MONO16_SOFT
),
476 DECL(AL_MONO32F_SOFT
),
477 DECL(AL_STEREO8_SOFT
),
478 DECL(AL_STEREO16_SOFT
),
479 DECL(AL_STEREO32F_SOFT
),
481 DECL(AL_QUAD16_SOFT
),
482 DECL(AL_QUAD32F_SOFT
),
484 DECL(AL_REAR16_SOFT
),
485 DECL(AL_REAR32F_SOFT
),
486 DECL(AL_5POINT1_8_SOFT
),
487 DECL(AL_5POINT1_16_SOFT
),
488 DECL(AL_5POINT1_32F_SOFT
),
489 DECL(AL_6POINT1_8_SOFT
),
490 DECL(AL_6POINT1_16_SOFT
),
491 DECL(AL_6POINT1_32F_SOFT
),
492 DECL(AL_7POINT1_8_SOFT
),
493 DECL(AL_7POINT1_16_SOFT
),
494 DECL(AL_7POINT1_32F_SOFT
),
495 DECL(AL_BFORMAT2D_8_SOFT
),
496 DECL(AL_BFORMAT2D_16_SOFT
),
497 DECL(AL_BFORMAT2D_32F_SOFT
),
498 DECL(AL_BFORMAT3D_8_SOFT
),
499 DECL(AL_BFORMAT3D_16_SOFT
),
500 DECL(AL_BFORMAT3D_32F_SOFT
),
503 DECL(AL_STEREO_SOFT
),
506 DECL(AL_5POINT1_SOFT
),
507 DECL(AL_6POINT1_SOFT
),
508 DECL(AL_7POINT1_SOFT
),
509 DECL(AL_BFORMAT2D_SOFT
),
510 DECL(AL_BFORMAT3D_SOFT
),
513 DECL(AL_UNSIGNED_BYTE_SOFT
),
515 DECL(AL_UNSIGNED_SHORT_SOFT
),
517 DECL(AL_UNSIGNED_INT_SOFT
),
519 DECL(AL_DOUBLE_SOFT
),
521 DECL(AL_UNSIGNED_BYTE3_SOFT
),
528 DECL(AL_INTERNAL_FORMAT_SOFT
),
529 DECL(AL_BYTE_LENGTH_SOFT
),
530 DECL(AL_SAMPLE_LENGTH_SOFT
),
531 DECL(AL_SEC_LENGTH_SOFT
),
532 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
533 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
535 DECL(AL_SOURCE_RADIUS
),
537 DECL(AL_STEREO_ANGLES
),
544 DECL(AL_INVALID_NAME
),
545 DECL(AL_INVALID_ENUM
),
546 DECL(AL_INVALID_VALUE
),
547 DECL(AL_INVALID_OPERATION
),
548 DECL(AL_OUT_OF_MEMORY
),
555 DECL(AL_DOPPLER_FACTOR
),
556 DECL(AL_DOPPLER_VELOCITY
),
557 DECL(AL_DISTANCE_MODEL
),
558 DECL(AL_SPEED_OF_SOUND
),
559 DECL(AL_SOURCE_DISTANCE_MODEL
),
560 DECL(AL_DEFERRED_UPDATES_SOFT
),
561 DECL(AL_GAIN_LIMIT_SOFT
),
563 DECL(AL_INVERSE_DISTANCE
),
564 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
565 DECL(AL_LINEAR_DISTANCE
),
566 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
567 DECL(AL_EXPONENT_DISTANCE
),
568 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
570 DECL(AL_FILTER_TYPE
),
571 DECL(AL_FILTER_NULL
),
572 DECL(AL_FILTER_LOWPASS
),
573 DECL(AL_FILTER_HIGHPASS
),
574 DECL(AL_FILTER_BANDPASS
),
576 DECL(AL_LOWPASS_GAIN
),
577 DECL(AL_LOWPASS_GAINHF
),
579 DECL(AL_HIGHPASS_GAIN
),
580 DECL(AL_HIGHPASS_GAINLF
),
582 DECL(AL_BANDPASS_GAIN
),
583 DECL(AL_BANDPASS_GAINHF
),
584 DECL(AL_BANDPASS_GAINLF
),
586 DECL(AL_EFFECT_TYPE
),
587 DECL(AL_EFFECT_NULL
),
588 DECL(AL_EFFECT_REVERB
),
589 DECL(AL_EFFECT_EAXREVERB
),
590 DECL(AL_EFFECT_CHORUS
),
591 DECL(AL_EFFECT_DISTORTION
),
592 DECL(AL_EFFECT_ECHO
),
593 DECL(AL_EFFECT_FLANGER
),
595 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
596 DECL(AL_EFFECT_VOCAL_MORPHER
),
597 DECL(AL_EFFECT_PITCH_SHIFTER
),
599 DECL(AL_EFFECT_RING_MODULATOR
),
601 DECL(AL_EFFECT_AUTOWAH
),
603 DECL(AL_EFFECT_COMPRESSOR
),
604 DECL(AL_EFFECT_EQUALIZER
),
605 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
606 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
608 DECL(AL_EFFECTSLOT_EFFECT
),
609 DECL(AL_EFFECTSLOT_GAIN
),
610 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
611 DECL(AL_EFFECTSLOT_NULL
),
613 DECL(AL_EAXREVERB_DENSITY
),
614 DECL(AL_EAXREVERB_DIFFUSION
),
615 DECL(AL_EAXREVERB_GAIN
),
616 DECL(AL_EAXREVERB_GAINHF
),
617 DECL(AL_EAXREVERB_GAINLF
),
618 DECL(AL_EAXREVERB_DECAY_TIME
),
619 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
620 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
621 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
622 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
623 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
624 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
625 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
626 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
627 DECL(AL_EAXREVERB_ECHO_TIME
),
628 DECL(AL_EAXREVERB_ECHO_DEPTH
),
629 DECL(AL_EAXREVERB_MODULATION_TIME
),
630 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
631 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
632 DECL(AL_EAXREVERB_HFREFERENCE
),
633 DECL(AL_EAXREVERB_LFREFERENCE
),
634 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
635 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
637 DECL(AL_REVERB_DENSITY
),
638 DECL(AL_REVERB_DIFFUSION
),
639 DECL(AL_REVERB_GAIN
),
640 DECL(AL_REVERB_GAINHF
),
641 DECL(AL_REVERB_DECAY_TIME
),
642 DECL(AL_REVERB_DECAY_HFRATIO
),
643 DECL(AL_REVERB_REFLECTIONS_GAIN
),
644 DECL(AL_REVERB_REFLECTIONS_DELAY
),
645 DECL(AL_REVERB_LATE_REVERB_GAIN
),
646 DECL(AL_REVERB_LATE_REVERB_DELAY
),
647 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
648 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
649 DECL(AL_REVERB_DECAY_HFLIMIT
),
651 DECL(AL_CHORUS_WAVEFORM
),
652 DECL(AL_CHORUS_PHASE
),
653 DECL(AL_CHORUS_RATE
),
654 DECL(AL_CHORUS_DEPTH
),
655 DECL(AL_CHORUS_FEEDBACK
),
656 DECL(AL_CHORUS_DELAY
),
658 DECL(AL_DISTORTION_EDGE
),
659 DECL(AL_DISTORTION_GAIN
),
660 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
661 DECL(AL_DISTORTION_EQCENTER
),
662 DECL(AL_DISTORTION_EQBANDWIDTH
),
665 DECL(AL_ECHO_LRDELAY
),
666 DECL(AL_ECHO_DAMPING
),
667 DECL(AL_ECHO_FEEDBACK
),
668 DECL(AL_ECHO_SPREAD
),
670 DECL(AL_FLANGER_WAVEFORM
),
671 DECL(AL_FLANGER_PHASE
),
672 DECL(AL_FLANGER_RATE
),
673 DECL(AL_FLANGER_DEPTH
),
674 DECL(AL_FLANGER_FEEDBACK
),
675 DECL(AL_FLANGER_DELAY
),
677 DECL(AL_RING_MODULATOR_FREQUENCY
),
678 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
679 DECL(AL_RING_MODULATOR_WAVEFORM
),
681 DECL(AL_COMPRESSOR_ONOFF
),
683 DECL(AL_EQUALIZER_LOW_GAIN
),
684 DECL(AL_EQUALIZER_LOW_CUTOFF
),
685 DECL(AL_EQUALIZER_MID1_GAIN
),
686 DECL(AL_EQUALIZER_MID1_CENTER
),
687 DECL(AL_EQUALIZER_MID1_WIDTH
),
688 DECL(AL_EQUALIZER_MID2_GAIN
),
689 DECL(AL_EQUALIZER_MID2_CENTER
),
690 DECL(AL_EQUALIZER_MID2_WIDTH
),
691 DECL(AL_EQUALIZER_HIGH_GAIN
),
692 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
694 DECL(AL_DEDICATED_GAIN
),
698 static const ALCchar alcNoError
[] = "No Error";
699 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
700 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
701 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
702 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
703 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
706 /************************************************
708 ************************************************/
710 /* Enumerated device names */
711 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
713 static al_string alcAllDevicesList
;
714 static al_string alcCaptureDeviceList
;
716 /* Default is always the first in the list */
717 static ALCchar
*alcDefaultAllDevicesSpecifier
;
718 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
720 /* Default context extensions */
721 static const ALchar alExtList
[] =
722 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
723 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
724 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
725 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
726 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
727 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
728 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length";
730 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
732 /* Thread-local current context */
733 static altss_t LocalContext
;
734 /* Process-wide current context */
735 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
737 /* Mixing thread piority level */
742 enum LogLevel LogLevel
= LogWarning
;
744 enum LogLevel LogLevel
= LogError
;
747 /* Flag to trap ALC device errors */
748 static ALCboolean TrapALCError
= ALC_FALSE
;
750 /* One-time configuration init control */
751 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
753 /* Default effect that applies to sources that don't have an effect on send 0 */
754 static ALeffect DefaultEffect
;
756 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
759 static ALCboolean SuspendDefers
= ALC_TRUE
;
762 /************************************************
764 ************************************************/
765 static const ALCchar alcNoDeviceExtList
[] =
766 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
767 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
768 static const ALCchar alcExtensionList
[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
771 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
772 "ALC_SOFT_loopback ALC_SOFT_pause_device";
773 static const ALCint alcMajorVersion
= 1;
774 static const ALCint alcMinorVersion
= 1;
776 static const ALCint alcEFXMajorVersion
= 1;
777 static const ALCint alcEFXMinorVersion
= 0;
780 /************************************************
782 ************************************************/
783 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
785 static almtx_t ListLock
;
786 static inline void LockLists(void)
788 int ret
= almtx_lock(&ListLock
);
789 assert(ret
== althrd_success
);
791 static inline void UnlockLists(void)
793 int ret
= almtx_unlock(&ListLock
);
794 assert(ret
== althrd_success
);
797 /************************************************
798 * Library initialization
799 ************************************************/
801 static void alc_init(void);
802 static void alc_deinit(void);
803 static void alc_deinit_safe(void);
805 #ifndef AL_LIBTYPE_STATIC
806 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
810 case DLL_PROCESS_ATTACH
:
811 /* Pin the DLL so we won't get unloaded until the process terminates */
812 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
813 (WCHAR
*)hModule
, &hModule
);
817 case DLL_THREAD_DETACH
:
820 case DLL_PROCESS_DETACH
:
829 #elif defined(_MSC_VER)
830 #pragma section(".CRT$XCU",read)
831 static void alc_constructor(void);
832 static void alc_destructor(void);
833 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
835 static void alc_constructor(void)
837 atexit(alc_destructor
);
841 static void alc_destructor(void)
845 #elif defined(HAVE_GCC_DESTRUCTOR)
846 static void alc_init(void) __attribute__((constructor
));
847 static void alc_deinit(void) __attribute__((destructor
));
849 #error "No static initialization available on this platform!"
852 #elif defined(HAVE_GCC_DESTRUCTOR)
854 static void alc_init(void) __attribute__((constructor
));
855 static void alc_deinit(void) __attribute__((destructor
));
858 #error "No global initialization available on this platform!"
861 static void ReleaseThreadCtx(void *ptr
);
862 static void alc_init(void)
869 AL_STRING_INIT(alcAllDevicesList
);
870 AL_STRING_INIT(alcCaptureDeviceList
);
872 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
873 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
876 str
= getenv("__ALSOFT_REVERSE_Z");
877 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
880 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
881 assert(ret
== althrd_success
);
883 ret
= almtx_init(&ListLock
, almtx_recursive
);
884 assert(ret
== althrd_success
);
889 static void alc_initconfig(void)
891 const char *devs
, *str
;
896 str
= getenv("ALSOFT_LOGLEVEL");
899 long lvl
= strtol(str
, NULL
, 0);
900 if(lvl
>= NoLog
&& lvl
<= LogRef
)
904 str
= getenv("ALSOFT_LOGFILE");
907 FILE *logfile
= al_fopen(str
, "wt");
908 if(logfile
) LogFile
= logfile
;
909 else ERR("Failed to open log file '%s'\n", str
);
912 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
913 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
918 if(BackendListSize
> 0)
919 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
920 for(i
= 1;i
< BackendListSize
;i
++)
921 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
922 TRACE("Supported backends: %s\n", buf
);
926 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
929 if(strcasecmp(str
, "ignore") == 0)
931 SuspendDefers
= ALC_FALSE
;
932 TRACE("Selected context suspend behavior, \"ignore\"\n");
935 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
939 #if defined(HAVE_SSE4_1)
940 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
941 #elif defined(HAVE_SSE3)
942 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
943 #elif defined(HAVE_SSE2)
944 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
945 #elif defined(HAVE_SSE)
946 capfilter
|= CPU_CAP_SSE
;
949 capfilter
|= CPU_CAP_NEON
;
951 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
953 if(strcasecmp(str
, "all") == 0)
958 const char *next
= str
;
962 while(isspace(str
[0]))
964 next
= strchr(str
, ',');
966 if(!str
[0] || str
[0] == ',')
969 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
970 while(len
> 0 && isspace(str
[len
-1]))
972 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
973 capfilter
&= ~CPU_CAP_SSE
;
974 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
975 capfilter
&= ~CPU_CAP_SSE2
;
976 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
977 capfilter
&= ~CPU_CAP_SSE3
;
978 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
979 capfilter
&= ~CPU_CAP_SSE4_1
;
980 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
981 capfilter
&= ~CPU_CAP_NEON
;
983 WARN("Invalid CPU extension \"%s\"\n", str
);
987 FillCPUCaps(capfilter
);
994 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
998 str
= getenv("ALSOFT_TRAP_ERROR");
999 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1001 TrapALError
= AL_TRUE
;
1002 TrapALCError
= AL_TRUE
;
1006 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1007 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1008 TrapALError
= AL_TRUE
;
1009 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1011 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1012 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1013 TrapALCError
= ALC_TRUE
;
1014 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1017 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1018 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1020 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1022 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1023 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1027 const char *next
= devs
;
1028 int endlist
, delitem
;
1033 while(isspace(devs
[0]))
1035 next
= strchr(devs
, ',');
1037 delitem
= (devs
[0] == '-');
1038 if(devs
[0] == '-') devs
++;
1040 if(!devs
[0] || devs
[0] == ',')
1047 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1048 while(len
> 0 && isspace(devs
[len
-1]))
1050 for(n
= i
;n
< BackendListSize
;n
++)
1052 if(len
== strlen(BackendList
[n
].name
) &&
1053 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1057 for(;n
+1 < BackendListSize
;n
++)
1058 BackendList
[n
] = BackendList
[n
+1];
1063 struct BackendInfo Bkp
= BackendList
[n
];
1065 BackendList
[n
] = BackendList
[n
-1];
1066 BackendList
[n
] = Bkp
;
1076 BackendListSize
= i
;
1079 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1081 if(BackendList
[i
].getFactory
)
1083 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1084 if(!V0(factory
,init
)())
1086 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1090 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1091 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1093 PlaybackBackend
= BackendList
[i
];
1094 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1096 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1098 CaptureBackend
= BackendList
[i
];
1099 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1105 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1107 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1111 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1112 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1114 PlaybackBackend
= BackendList
[i
];
1115 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1117 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1119 CaptureBackend
= BackendList
[i
];
1120 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1124 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1128 if(!PlaybackBackend
.name
)
1129 WARN("No playback backend available!\n");
1130 if(!CaptureBackend
.name
)
1131 WARN("No capture backend available!\n");
1133 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1136 const char *next
= str
;
1140 next
= strchr(str
, ',');
1142 if(!str
[0] || next
== str
)
1145 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1146 for(n
= 0;EffectList
[n
].name
;n
++)
1148 if(len
== strlen(EffectList
[n
].name
) &&
1149 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1150 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1155 InitEffectFactoryMap();
1157 InitEffect(&DefaultEffect
);
1158 str
= getenv("ALSOFT_DEFAULT_REVERB");
1159 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1160 LoadReverbPreset(str
, &DefaultEffect
);
1162 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1167 static JavaVM
*gJavaVM
;
1168 static pthread_key_t gJVMThreadKey
;
1170 static void CleanupJNIEnv(void* UNUSED(ptr
))
1172 JCALL0(gJavaVM
,DetachCurrentThread
)();
1175 void *Android_GetJNIEnv(void)
1179 WARN("gJavaVM is NULL!\n");
1183 /* http://developer.android.com/guide/practices/jni.html
1185 * All threads are Linux threads, scheduled by the kernel. They're usually
1186 * started from managed code (using Thread.start), but they can also be
1187 * created elsewhere and then attached to the JavaVM. For example, a thread
1188 * started with pthread_create can be attached with the JNI
1189 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1190 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1191 * Attaching a natively-created thread causes a java.lang.Thread object to
1192 * be constructed and added to the "main" ThreadGroup, making it visible to
1193 * the debugger. Calling AttachCurrentThread on an already-attached thread
1196 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1199 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1202 ERR("Failed to attach current thread\n");
1205 pthread_setspecific(gJVMThreadKey
, env
);
1210 /* Automatically called by JNI. */
1211 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1217 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1219 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1223 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1224 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1226 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1227 ERR("pthread_key_create failed: %d\n", err
);
1228 pthread_setspecific(gJVMThreadKey
, env
);
1229 return JNI_VERSION_1_4
;
1235 /************************************************
1236 * Library deinitialization
1237 ************************************************/
1238 static void alc_cleanup(void)
1242 AL_STRING_DEINIT(alcAllDevicesList
);
1243 AL_STRING_DEINIT(alcCaptureDeviceList
);
1245 free(alcDefaultAllDevicesSpecifier
);
1246 alcDefaultAllDevicesSpecifier
= NULL
;
1247 free(alcCaptureDefaultDeviceSpecifier
);
1248 alcCaptureDefaultDeviceSpecifier
= NULL
;
1250 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1255 } while((dev
=dev
->next
) != NULL
);
1256 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1259 DeinitEffectFactoryMap();
1262 static void alc_deinit_safe(void)
1270 almtx_destroy(&ListLock
);
1271 altss_delete(LocalContext
);
1273 if(LogFile
!= stderr
)
1278 static void alc_deinit(void)
1284 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1285 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1287 for(i
= 0;i
< BackendListSize
;i
++)
1289 if(!BackendList
[i
].getFactory
)
1290 BackendList
[i
].Deinit();
1293 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1294 V0(factory
,deinit
)();
1298 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1299 V0(factory
,deinit
)();
1306 /************************************************
1307 * Device enumeration
1308 ************************************************/
1309 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1316 if(backendinfo
->Probe
)
1317 backendinfo
->Probe(type
);
1318 else if(backendinfo
->getFactory
)
1320 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1321 V(factory
,probe
)(type
);
1325 static void ProbeAllDevicesList(void)
1326 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1327 static void ProbeCaptureDeviceList(void)
1328 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1330 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1332 size_t len
= strlen(name
);
1334 alstr_append_range(devnames
, name
, name
+len
+1);
1336 void AppendAllDevicesList(const ALCchar
*name
)
1337 { AppendDevice(name
, &alcAllDevicesList
); }
1338 void AppendCaptureDeviceList(const ALCchar
*name
)
1339 { AppendDevice(name
, &alcCaptureDeviceList
); }
1342 /************************************************
1343 * Device format information
1344 ************************************************/
1345 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1349 case DevFmtByte
: return "Signed Byte";
1350 case DevFmtUByte
: return "Unsigned Byte";
1351 case DevFmtShort
: return "Signed Short";
1352 case DevFmtUShort
: return "Unsigned Short";
1353 case DevFmtInt
: return "Signed Int";
1354 case DevFmtUInt
: return "Unsigned Int";
1355 case DevFmtFloat
: return "Float";
1357 return "(unknown type)";
1359 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1363 case DevFmtMono
: return "Mono";
1364 case DevFmtStereo
: return "Stereo";
1365 case DevFmtQuad
: return "Quadraphonic";
1366 case DevFmtX51
: return "5.1 Surround";
1367 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1368 case DevFmtX61
: return "6.1 Surround";
1369 case DevFmtX71
: return "7.1 Surround";
1370 case DevFmtAmbi3D
: return "Ambisonic 3D";
1372 return "(unknown channels)";
1375 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1376 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1380 case DevFmtByte
: return sizeof(ALbyte
);
1381 case DevFmtUByte
: return sizeof(ALubyte
);
1382 case DevFmtShort
: return sizeof(ALshort
);
1383 case DevFmtUShort
: return sizeof(ALushort
);
1384 case DevFmtInt
: return sizeof(ALint
);
1385 case DevFmtUInt
: return sizeof(ALuint
);
1386 case DevFmtFloat
: return sizeof(ALfloat
);
1390 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1394 case DevFmtMono
: return 1;
1395 case DevFmtStereo
: return 2;
1396 case DevFmtQuad
: return 4;
1397 case DevFmtX51
: return 6;
1398 case DevFmtX51Rear
: return 6;
1399 case DevFmtX61
: return 7;
1400 case DevFmtX71
: return 8;
1401 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1402 (ambiorder
== 2) ? 9 :
1403 (ambiorder
== 1) ? 4 : 1;
1408 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1409 enum DevFmtType
*type
)
1411 static const struct {
1413 enum DevFmtChannels channels
;
1414 enum DevFmtType type
;
1416 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1417 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1418 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1420 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1421 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1422 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1424 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1425 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1426 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1428 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1429 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1430 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1432 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1433 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1434 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1436 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1437 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1438 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1442 for(i
= 0;i
< COUNTOF(list
);i
++)
1444 if(list
[i
].format
== format
)
1446 *chans
= list
[i
].channels
;
1447 *type
= list
[i
].type
;
1455 static ALCboolean
IsValidALCType(ALCenum type
)
1460 case ALC_UNSIGNED_BYTE_SOFT
:
1461 case ALC_SHORT_SOFT
:
1462 case ALC_UNSIGNED_SHORT_SOFT
:
1464 case ALC_UNSIGNED_INT_SOFT
:
1465 case ALC_FLOAT_SOFT
:
1471 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1476 case ALC_STEREO_SOFT
:
1478 case ALC_5POINT1_SOFT
:
1479 case ALC_6POINT1_SOFT
:
1480 case ALC_7POINT1_SOFT
:
1481 case ALC_BFORMAT3D_SOFT
:
1487 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1498 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1510 /************************************************
1511 * Miscellaneous ALC helpers
1512 ************************************************/
1514 void ALCdevice_Lock(ALCdevice
*device
)
1516 V0(device
->Backend
,lock
)();
1519 void ALCdevice_Unlock(ALCdevice
*device
)
1521 V0(device
->Backend
,unlock
)();
1525 /* SetDefaultWFXChannelOrder
1527 * Sets the default channel order used by WaveFormatEx.
1529 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1533 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1534 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1536 switch(device
->FmtChans
)
1539 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1542 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1543 device
->RealOut
.ChannelName
[1] = FrontRight
;
1546 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1547 device
->RealOut
.ChannelName
[1] = FrontRight
;
1548 device
->RealOut
.ChannelName
[2] = BackLeft
;
1549 device
->RealOut
.ChannelName
[3] = BackRight
;
1552 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1553 device
->RealOut
.ChannelName
[1] = FrontRight
;
1554 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1555 device
->RealOut
.ChannelName
[3] = LFE
;
1556 device
->RealOut
.ChannelName
[4] = SideLeft
;
1557 device
->RealOut
.ChannelName
[5] = SideRight
;
1560 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1561 device
->RealOut
.ChannelName
[1] = FrontRight
;
1562 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1563 device
->RealOut
.ChannelName
[3] = LFE
;
1564 device
->RealOut
.ChannelName
[4] = BackLeft
;
1565 device
->RealOut
.ChannelName
[5] = BackRight
;
1568 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1569 device
->RealOut
.ChannelName
[1] = FrontRight
;
1570 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1571 device
->RealOut
.ChannelName
[3] = LFE
;
1572 device
->RealOut
.ChannelName
[4] = BackCenter
;
1573 device
->RealOut
.ChannelName
[5] = SideLeft
;
1574 device
->RealOut
.ChannelName
[6] = SideRight
;
1577 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1578 device
->RealOut
.ChannelName
[1] = FrontRight
;
1579 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1580 device
->RealOut
.ChannelName
[3] = LFE
;
1581 device
->RealOut
.ChannelName
[4] = BackLeft
;
1582 device
->RealOut
.ChannelName
[5] = BackRight
;
1583 device
->RealOut
.ChannelName
[6] = SideLeft
;
1584 device
->RealOut
.ChannelName
[7] = SideRight
;
1587 device
->RealOut
.ChannelName
[0] = Aux0
;
1588 if(device
->AmbiOrder
> 0)
1590 device
->RealOut
.ChannelName
[1] = Aux1
;
1591 device
->RealOut
.ChannelName
[2] = Aux2
;
1592 device
->RealOut
.ChannelName
[3] = Aux3
;
1594 if(device
->AmbiOrder
> 1)
1596 device
->RealOut
.ChannelName
[4] = Aux4
;
1597 device
->RealOut
.ChannelName
[5] = Aux5
;
1598 device
->RealOut
.ChannelName
[6] = Aux6
;
1599 device
->RealOut
.ChannelName
[7] = Aux7
;
1600 device
->RealOut
.ChannelName
[8] = Aux8
;
1602 if(device
->AmbiOrder
> 2)
1604 device
->RealOut
.ChannelName
[9] = Aux9
;
1605 device
->RealOut
.ChannelName
[10] = Aux10
;
1606 device
->RealOut
.ChannelName
[11] = Aux11
;
1607 device
->RealOut
.ChannelName
[12] = Aux12
;
1608 device
->RealOut
.ChannelName
[13] = Aux13
;
1609 device
->RealOut
.ChannelName
[14] = Aux14
;
1610 device
->RealOut
.ChannelName
[15] = Aux15
;
1616 /* SetDefaultChannelOrder
1618 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1620 void SetDefaultChannelOrder(ALCdevice
*device
)
1624 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1625 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1627 switch(device
->FmtChans
)
1630 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1631 device
->RealOut
.ChannelName
[1] = FrontRight
;
1632 device
->RealOut
.ChannelName
[2] = BackLeft
;
1633 device
->RealOut
.ChannelName
[3] = BackRight
;
1634 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1635 device
->RealOut
.ChannelName
[5] = LFE
;
1638 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1639 device
->RealOut
.ChannelName
[1] = FrontRight
;
1640 device
->RealOut
.ChannelName
[2] = BackLeft
;
1641 device
->RealOut
.ChannelName
[3] = BackRight
;
1642 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1643 device
->RealOut
.ChannelName
[5] = LFE
;
1644 device
->RealOut
.ChannelName
[6] = SideLeft
;
1645 device
->RealOut
.ChannelName
[7] = SideRight
;
1648 /* Same as WFX order */
1655 SetDefaultWFXChannelOrder(device
);
1660 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1663 /* ALCcontext_DeferUpdates
1665 * Defers/suspends updates for the given context's listener and sources. This
1666 * does *NOT* stop mixing, but rather prevents certain property changes from
1669 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1671 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1674 /* ALCcontext_ProcessUpdates
1676 * Resumes update processing after being deferred.
1678 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1680 ReadLock(&context
->PropLock
);
1681 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1683 /* Tell the mixer to stop applying updates, then wait for any active
1684 * updating to finish, before providing updates.
1686 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1687 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1690 UpdateListenerProps(context
);
1691 UpdateAllEffectSlotProps(context
);
1692 UpdateAllSourceProps(context
);
1694 /* Now with all updates declared, let the mixer continue applying them
1695 * so they all happen at once.
1697 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1699 ReadUnlock(&context
->PropLock
);
1705 * Stores the latest ALC device error
1707 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1709 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1713 /* DebugBreak() will cause an exception if there is no debugger */
1714 if(IsDebuggerPresent())
1716 #elif defined(SIGTRAP)
1722 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1724 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1730 * Updates the device's base clock time with however many samples have been
1731 * done. This is used so frequency changes on the device don't cause the time
1732 * to jump forward or back. Must not be called while the device is running/
1735 static inline void UpdateClockBase(ALCdevice
*device
)
1737 IncrementRef(&device
->MixCount
);
1738 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1739 device
->SamplesDone
= 0;
1740 IncrementRef(&device
->MixCount
);
1743 /* UpdateDeviceParams
1745 * Updates device parameters according to the attribute list (caller is
1746 * responsible for holding the list lock).
1748 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1750 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1751 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1752 const ALsizei old_sends
= device
->NumAuxSends
;
1753 ALsizei new_sends
= device
->NumAuxSends
;
1754 enum DevFmtChannels oldChans
;
1755 enum DevFmtType oldType
;
1756 ALboolean update_failed
;
1757 ALCsizei hrtf_id
= -1;
1758 ALCcontext
*context
;
1764 // Check for attributes
1765 if(device
->Type
== Loopback
)
1767 ALCsizei numMono
, numStereo
, numSends
;
1768 ALCenum alayout
= AL_NONE
;
1769 ALCenum ascale
= AL_NONE
;
1770 ALCenum schans
= AL_NONE
;
1771 ALCenum stype
= AL_NONE
;
1772 ALCsizei attrIdx
= 0;
1773 ALCsizei aorder
= 0;
1778 WARN("Missing attributes for loopback device\n");
1779 return ALC_INVALID_VALUE
;
1782 numMono
= device
->NumMonoSources
;
1783 numStereo
= device
->NumStereoSources
;
1784 numSends
= old_sends
;
1786 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1787 while(attrList
[attrIdx
])
1789 switch(attrList
[attrIdx
])
1791 case ALC_FORMAT_CHANNELS_SOFT
:
1792 schans
= attrList
[attrIdx
+ 1];
1793 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1794 if(!IsValidALCChannels(schans
))
1795 return ALC_INVALID_VALUE
;
1798 case ALC_FORMAT_TYPE_SOFT
:
1799 stype
= attrList
[attrIdx
+ 1];
1800 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1801 if(!IsValidALCType(stype
))
1802 return ALC_INVALID_VALUE
;
1806 freq
= attrList
[attrIdx
+ 1];
1807 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1808 if(freq
< MIN_OUTPUT_RATE
)
1809 return ALC_INVALID_VALUE
;
1812 case ALC_AMBISONIC_LAYOUT_SOFT
:
1813 alayout
= attrList
[attrIdx
+ 1];
1814 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1815 if(!IsValidAmbiLayout(alayout
))
1816 return ALC_INVALID_VALUE
;
1819 case ALC_AMBISONIC_SCALING_SOFT
:
1820 ascale
= attrList
[attrIdx
+ 1];
1821 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1822 if(!IsValidAmbiScaling(ascale
))
1823 return ALC_INVALID_VALUE
;
1826 case ALC_AMBISONIC_ORDER_SOFT
:
1827 aorder
= attrList
[attrIdx
+ 1];
1828 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1829 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1830 return ALC_INVALID_VALUE
;
1833 case ALC_MONO_SOURCES
:
1834 numMono
= attrList
[attrIdx
+ 1];
1835 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1836 numMono
= maxi(numMono
, 0);
1839 case ALC_STEREO_SOURCES
:
1840 numStereo
= attrList
[attrIdx
+ 1];
1841 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1842 numStereo
= maxi(numStereo
, 0);
1845 case ALC_MAX_AUXILIARY_SENDS
:
1846 numSends
= attrList
[attrIdx
+ 1];
1847 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1848 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1852 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1853 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1854 hrtf_appreq
= Hrtf_Disable
;
1855 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1856 hrtf_appreq
= Hrtf_Enable
;
1858 hrtf_appreq
= Hrtf_Default
;
1861 case ALC_HRTF_ID_SOFT
:
1862 hrtf_id
= attrList
[attrIdx
+ 1];
1863 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1867 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1868 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1876 if(!schans
|| !stype
|| !freq
)
1878 WARN("Missing format for loopback device\n");
1879 return ALC_INVALID_VALUE
;
1881 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1883 WARN("Missing ambisonic info for loopback device\n");
1884 return ALC_INVALID_VALUE
;
1887 if((device
->Flags
&DEVICE_RUNNING
))
1888 V0(device
->Backend
,stop
)();
1889 device
->Flags
&= ~DEVICE_RUNNING
;
1891 UpdateClockBase(device
);
1893 device
->Frequency
= freq
;
1894 device
->FmtChans
= schans
;
1895 device
->FmtType
= stype
;
1896 if(schans
== ALC_BFORMAT3D_SOFT
)
1898 device
->AmbiOrder
= aorder
;
1899 device
->AmbiLayout
= alayout
;
1900 device
->AmbiScale
= ascale
;
1903 if(numMono
> INT_MAX
-numStereo
)
1904 numMono
= INT_MAX
-numStereo
;
1905 numMono
+= numStereo
;
1906 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1912 numMono
= maxi(numMono
, 256);
1913 numStereo
= mini(numStereo
, numMono
);
1914 numMono
-= numStereo
;
1915 device
->SourcesMax
= numMono
+ numStereo
;
1917 device
->NumMonoSources
= numMono
;
1918 device
->NumStereoSources
= numStereo
;
1920 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1921 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1923 new_sends
= numSends
;
1925 else if(attrList
&& attrList
[0])
1927 ALCsizei numMono
, numStereo
, numSends
;
1928 ALCsizei attrIdx
= 0;
1931 /* If a context is already running on the device, stop playback so the
1932 * device attributes can be updated. */
1933 if((device
->Flags
&DEVICE_RUNNING
))
1934 V0(device
->Backend
,stop
)();
1935 device
->Flags
&= ~DEVICE_RUNNING
;
1937 UpdateClockBase(device
);
1939 freq
= device
->Frequency
;
1940 numMono
= device
->NumMonoSources
;
1941 numStereo
= device
->NumStereoSources
;
1942 numSends
= old_sends
;
1944 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1945 while(attrList
[attrIdx
])
1947 switch(attrList
[attrIdx
])
1950 freq
= attrList
[attrIdx
+ 1];
1951 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1952 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1955 case ALC_MONO_SOURCES
:
1956 numMono
= attrList
[attrIdx
+ 1];
1957 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1958 numMono
= maxi(numMono
, 0);
1961 case ALC_STEREO_SOURCES
:
1962 numStereo
= attrList
[attrIdx
+ 1];
1963 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1964 numStereo
= maxi(numStereo
, 0);
1967 case ALC_MAX_AUXILIARY_SENDS
:
1968 numSends
= attrList
[attrIdx
+ 1];
1969 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1970 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1974 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1975 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1976 hrtf_appreq
= Hrtf_Disable
;
1977 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1978 hrtf_appreq
= Hrtf_Enable
;
1980 hrtf_appreq
= Hrtf_Default
;
1983 case ALC_HRTF_ID_SOFT
:
1984 hrtf_id
= attrList
[attrIdx
+ 1];
1985 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1989 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1990 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1998 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
1999 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2001 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2003 /* SSE and Neon do best with the update size being a multiple of 4 */
2004 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2005 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2007 device
->Frequency
= freq
;
2009 if(numMono
> INT_MAX
-numStereo
)
2010 numMono
= INT_MAX
-numStereo
;
2011 numMono
+= numStereo
;
2012 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2018 numMono
= maxi(numMono
, 256);
2019 numStereo
= mini(numStereo
, numMono
);
2020 numMono
-= numStereo
;
2021 device
->SourcesMax
= numMono
+ numStereo
;
2023 device
->NumMonoSources
= numMono
;
2024 device
->NumStereoSources
= numStereo
;
2026 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2027 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2029 new_sends
= numSends
;
2032 if((device
->Flags
&DEVICE_RUNNING
))
2033 return ALC_NO_ERROR
;
2035 al_free(device
->Uhj_Encoder
);
2036 device
->Uhj_Encoder
= NULL
;
2038 al_free(device
->Bs2b
);
2039 device
->Bs2b
= NULL
;
2041 al_free(device
->ChannelDelay
[0].Buffer
);
2042 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2044 device
->ChannelDelay
[i
].Length
= 0;
2045 device
->ChannelDelay
[i
].Buffer
= NULL
;
2048 al_free(device
->Dry
.Buffer
);
2049 device
->Dry
.Buffer
= NULL
;
2050 device
->Dry
.NumChannels
= 0;
2051 device
->FOAOut
.Buffer
= NULL
;
2052 device
->FOAOut
.NumChannels
= 0;
2053 device
->RealOut
.Buffer
= NULL
;
2054 device
->RealOut
.NumChannels
= 0;
2056 UpdateClockBase(device
);
2058 /*************************************************************************
2059 * Update device format request if HRTF is requested
2061 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2062 if(device
->Type
!= Loopback
)
2065 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2067 if(strcasecmp(hrtf
, "true") == 0)
2068 hrtf_userreq
= Hrtf_Enable
;
2069 else if(strcasecmp(hrtf
, "false") == 0)
2070 hrtf_userreq
= Hrtf_Disable
;
2071 else if(strcasecmp(hrtf
, "auto") != 0)
2072 ERR("Unexpected hrtf value: %s\n", hrtf
);
2075 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2077 struct Hrtf
*hrtf
= NULL
;
2078 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2080 VECTOR_DEINIT(device
->HrtfList
);
2081 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2083 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2085 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2086 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2088 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2093 device
->FmtChans
= DevFmtStereo
;
2094 device
->Frequency
= hrtf
->sampleRate
;
2095 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2096 if(device
->HrtfHandle
)
2097 Hrtf_DecRef(device
->HrtfHandle
);
2098 device
->HrtfHandle
= hrtf
;
2102 hrtf_userreq
= Hrtf_Default
;
2103 hrtf_appreq
= Hrtf_Disable
;
2104 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2109 oldFreq
= device
->Frequency
;
2110 oldChans
= device
->FmtChans
;
2111 oldType
= device
->FmtType
;
2113 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2114 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2115 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2116 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2117 device
->UpdateSize
, device
->NumUpdates
2120 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2121 return ALC_INVALID_DEVICE
;
2123 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2125 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2126 DevFmtChannelsString(device
->FmtChans
));
2127 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2129 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2131 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2132 DevFmtTypeString(device
->FmtType
));
2133 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2135 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2137 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2138 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2141 if((device
->UpdateSize
&3) != 0)
2143 if((CPUCapFlags
&CPU_CAP_SSE
))
2144 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2145 if((CPUCapFlags
&CPU_CAP_NEON
))
2146 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2149 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2150 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2151 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2154 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2155 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2156 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2158 /* Allocate extra channels for any post-filter output. */
2159 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2160 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2162 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2163 device
->Dry
.Buffer
= al_calloc(16, size
);
2164 if(!device
->Dry
.Buffer
)
2166 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2167 return ALC_INVALID_DEVICE
;
2170 if(device
->RealOut
.NumChannels
!= 0)
2171 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2172 device
->FOAOut
.NumChannels
;
2175 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2176 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2179 if(device
->FOAOut
.NumChannels
!= 0)
2180 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2183 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2184 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2187 /* Need to delay returning failure until replacement Send arrays have been
2188 * allocated with the appropriate size.
2190 device
->NumAuxSends
= new_sends
;
2191 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2192 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2193 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2194 update_failed
= AL_FALSE
;
2195 SetMixerFPUMode(&oldMode
);
2196 if(device
->DefaultSlot
)
2198 ALeffectslot
*slot
= device
->DefaultSlot
;
2199 ALeffectState
*state
= slot
->Effect
.State
;
2201 state
->OutBuffer
= device
->Dry
.Buffer
;
2202 state
->OutChannels
= device
->Dry
.NumChannels
;
2203 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2204 update_failed
= AL_TRUE
;
2206 UpdateEffectSlotProps(slot
);
2209 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2214 WriteLock(&context
->PropLock
);
2215 LockUIntMapRead(&context
->EffectSlotMap
);
2216 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2218 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2219 ALeffectState
*state
= slot
->Effect
.State
;
2221 state
->OutBuffer
= device
->Dry
.Buffer
;
2222 state
->OutChannels
= device
->Dry
.NumChannels
;
2223 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2224 update_failed
= AL_TRUE
;
2226 UpdateEffectSlotProps(slot
);
2228 UnlockUIntMapRead(&context
->EffectSlotMap
);
2230 LockUIntMapRead(&context
->SourceMap
);
2231 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2232 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2234 ALsource
*source
= context
->SourceMap
.values
[pos
];
2236 if(old_sends
!= device
->NumAuxSends
)
2238 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2241 memcpy(sends
, source
->Send
,
2242 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2244 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2246 if(source
->Send
[s
].Slot
)
2247 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2248 source
->Send
[s
].Slot
= NULL
;
2250 al_free(source
->Send
);
2251 source
->Send
= sends
;
2252 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2254 source
->Send
[s
].Slot
= NULL
;
2255 source
->Send
[s
].Gain
= 1.0f
;
2256 source
->Send
[s
].GainHF
= 1.0f
;
2257 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2258 source
->Send
[s
].GainLF
= 1.0f
;
2259 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2263 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2265 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2266 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2268 ALvoice
*voice
= context
->Voices
[pos
];
2269 struct ALvoiceProps
*props
;
2271 /* Clear any pre-existing voice property structs, in case the
2272 * number of auxiliary sends changed. Active sources will have
2273 * updates respecified in UpdateAllSourceProps.
2275 props
= ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_relaxed
);
2278 props
= ATOMIC_EXCHANGE_PTR(&voice
->FreeList
, NULL
, almemory_order_relaxed
);
2281 struct ALvoiceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2286 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2289 if(device
->AvgSpeakerDist
> 0.0f
)
2291 /* Reinitialize the NFC filters for new parameters. */
2292 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2293 (device
->AvgSpeakerDist
* device
->Frequency
);
2294 for(i
= 0;i
< voice
->NumChannels
;i
++)
2296 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2297 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2298 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2302 UnlockUIntMapRead(&context
->SourceMap
);
2304 UpdateListenerProps(context
);
2305 UpdateAllSourceProps(context
);
2306 WriteUnlock(&context
->PropLock
);
2308 context
= context
->next
;
2310 RestoreFPUMode(&oldMode
);
2312 return ALC_INVALID_DEVICE
;
2314 if(!(device
->Flags
&DEVICE_PAUSED
))
2316 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2317 return ALC_INVALID_DEVICE
;
2318 device
->Flags
|= DEVICE_RUNNING
;
2321 return ALC_NO_ERROR
;
2326 * Frees the device structure, and destroys any objects the app failed to
2327 * delete. Called once there's no more references on the device.
2329 static ALCvoid
FreeDevice(ALCdevice
*device
)
2333 TRACE("%p\n", device
);
2335 V0(device
->Backend
,close
)();
2336 DELETE_OBJ(device
->Backend
);
2337 device
->Backend
= NULL
;
2339 almtx_destroy(&device
->BackendLock
);
2341 if(device
->DefaultSlot
)
2343 DeinitEffectSlot(device
->DefaultSlot
);
2344 device
->DefaultSlot
= NULL
;
2347 if(device
->BufferMap
.size
> 0)
2349 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2350 (device
->BufferMap
.size
==1)?"":"s");
2351 ReleaseALBuffers(device
);
2353 ResetUIntMap(&device
->BufferMap
);
2355 if(device
->EffectMap
.size
> 0)
2357 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2358 (device
->EffectMap
.size
==1)?"":"s");
2359 ReleaseALEffects(device
);
2361 ResetUIntMap(&device
->EffectMap
);
2363 if(device
->FilterMap
.size
> 0)
2365 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2366 (device
->FilterMap
.size
==1)?"":"s");
2367 ReleaseALFilters(device
);
2369 ResetUIntMap(&device
->FilterMap
);
2371 AL_STRING_DEINIT(device
->HrtfName
);
2372 FreeHrtfList(&device
->HrtfList
);
2373 if(device
->HrtfHandle
)
2374 Hrtf_DecRef(device
->HrtfHandle
);
2375 device
->HrtfHandle
= NULL
;
2376 al_free(device
->Hrtf
);
2377 device
->Hrtf
= NULL
;
2379 al_free(device
->Bs2b
);
2380 device
->Bs2b
= NULL
;
2382 al_free(device
->Uhj_Encoder
);
2383 device
->Uhj_Encoder
= NULL
;
2385 bformatdec_free(device
->AmbiDecoder
);
2386 device
->AmbiDecoder
= NULL
;
2388 ambiup_free(device
->AmbiUp
);
2389 device
->AmbiUp
= NULL
;
2391 al_free(device
->ChannelDelay
[0].Buffer
);
2392 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2394 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2395 device
->ChannelDelay
[i
].Length
= 0;
2396 device
->ChannelDelay
[i
].Buffer
= NULL
;
2399 AL_STRING_DEINIT(device
->DeviceName
);
2401 al_free(device
->Dry
.Buffer
);
2402 device
->Dry
.Buffer
= NULL
;
2403 device
->Dry
.NumChannels
= 0;
2404 device
->FOAOut
.Buffer
= NULL
;
2405 device
->FOAOut
.NumChannels
= 0;
2406 device
->RealOut
.Buffer
= NULL
;
2407 device
->RealOut
.NumChannels
= 0;
2413 void ALCdevice_IncRef(ALCdevice
*device
)
2416 ref
= IncrementRef(&device
->ref
);
2417 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2420 void ALCdevice_DecRef(ALCdevice
*device
)
2423 ref
= DecrementRef(&device
->ref
);
2424 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2425 if(ref
== 0) FreeDevice(device
);
2430 * Checks if the device handle is valid, and increments its ref count if so.
2432 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2434 ALCdevice
*tmpDevice
;
2437 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2440 if(tmpDevice
== *device
)
2442 ALCdevice_IncRef(tmpDevice
);
2446 tmpDevice
= tmpDevice
->next
;
2457 * Initializes context fields
2459 static ALvoid
InitContext(ALCcontext
*Context
)
2461 ALlistener
*listener
= Context
->Listener
;
2462 struct ALeffectslotArray
*auxslots
;
2464 //Initialise listener
2465 listener
->Gain
= 1.0f
;
2466 listener
->MetersPerUnit
= 1.0f
;
2467 listener
->Position
[0] = 0.0f
;
2468 listener
->Position
[1] = 0.0f
;
2469 listener
->Position
[2] = 0.0f
;
2470 listener
->Velocity
[0] = 0.0f
;
2471 listener
->Velocity
[1] = 0.0f
;
2472 listener
->Velocity
[2] = 0.0f
;
2473 listener
->Forward
[0] = 0.0f
;
2474 listener
->Forward
[1] = 0.0f
;
2475 listener
->Forward
[2] = -1.0f
;
2476 listener
->Up
[0] = 0.0f
;
2477 listener
->Up
[1] = 1.0f
;
2478 listener
->Up
[2] = 0.0f
;
2480 aluMatrixfSet(&listener
->Params
.Matrix
,
2481 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2482 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2483 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2484 0.0f
, 0.0f
, 0.0f
, 1.0f
2486 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2487 listener
->Params
.Gain
= 1.0f
;
2488 listener
->Params
.MetersPerUnit
= 1.0f
;
2489 listener
->Params
.DopplerFactor
= 1.0f
;
2490 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2492 ATOMIC_INIT(&listener
->Update
, NULL
);
2493 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2496 InitRef(&Context
->UpdateCount
, 0);
2497 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2498 Context
->GainBoost
= 1.0f
;
2499 RWLockInit(&Context
->PropLock
);
2500 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2501 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2502 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2504 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2505 auxslots
->count
= 0;
2506 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2509 Context
->DistanceModel
= DefaultDistanceModel
;
2510 Context
->SourceDistanceModel
= AL_FALSE
;
2511 Context
->DopplerFactor
= 1.0f
;
2512 Context
->DopplerVelocity
= 1.0f
;
2513 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2514 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2516 Context
->ExtensionList
= alExtList
;
2522 * Cleans up the context, and destroys any remaining objects the app failed to
2523 * delete. Called once there's no more references on the context.
2525 static void FreeContext(ALCcontext
*context
)
2527 ALlistener
*listener
= context
->Listener
;
2528 struct ALeffectslotArray
*auxslots
;
2529 struct ALlistenerProps
*lprops
;
2533 TRACE("%p\n", context
);
2535 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2538 if(context
->SourceMap
.size
> 0)
2540 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2541 (context
->SourceMap
.size
==1)?"":"s");
2542 ReleaseALSources(context
);
2544 ResetUIntMap(&context
->SourceMap
);
2546 if(context
->EffectSlotMap
.size
> 0)
2548 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2549 (context
->EffectSlotMap
.size
==1)?"":"s");
2550 ReleaseALAuxiliaryEffectSlots(context
);
2552 ResetUIntMap(&context
->EffectSlotMap
);
2554 for(i
= 0;i
< context
->VoiceCount
;i
++)
2555 DeinitVoice(context
->Voices
[i
]);
2556 al_free(context
->Voices
);
2557 context
->Voices
= NULL
;
2558 context
->VoiceCount
= 0;
2559 context
->MaxVoices
= 0;
2561 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2563 TRACE("Freed unapplied listener update %p\n", lprops
);
2567 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2570 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2575 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2577 ALCdevice_DecRef(context
->Device
);
2578 context
->Device
= NULL
;
2580 //Invalidate context
2581 memset(context
, 0, sizeof(ALCcontext
));
2587 * Removes the context reference from the given device and removes it from
2588 * being current on the running thread or globally. Returns true if other
2589 * contexts still exist on the device.
2591 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2593 ALCcontext
*origctx
, *newhead
;
2596 if(altss_get(LocalContext
) == context
)
2598 WARN("%p released while current on thread\n", context
);
2599 altss_set(LocalContext
, NULL
);
2600 ALCcontext_DecRef(context
);
2604 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2605 ALCcontext_DecRef(context
);
2607 ALCdevice_Lock(device
);
2609 newhead
= context
->next
;
2610 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2612 ALCcontext
*volatile*list
= &origctx
->next
;
2615 if(*list
== context
)
2617 *list
= (*list
)->next
;
2620 list
= &(*list
)->next
;
2625 ALCdevice_Unlock(device
);
2627 ALCcontext_DecRef(context
);
2631 void ALCcontext_IncRef(ALCcontext
*context
)
2633 uint ref
= IncrementRef(&context
->ref
);
2634 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2637 void ALCcontext_DecRef(ALCcontext
*context
)
2639 uint ref
= DecrementRef(&context
->ref
);
2640 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2641 if(ref
== 0) FreeContext(context
);
2644 static void ReleaseThreadCtx(void *ptr
)
2646 ALCcontext
*context
= ptr
;
2647 uint ref
= DecrementRef(&context
->ref
);
2648 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2649 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2654 * Checks that the given context is valid, and increments its reference count.
2656 static ALCboolean
VerifyContext(ALCcontext
**context
)
2661 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2664 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2669 ALCcontext_IncRef(ctx
);
2686 * Returns the currently active context for this thread, and adds a reference
2687 * without locking it.
2689 ALCcontext
*GetContextRef(void)
2691 ALCcontext
*context
;
2693 context
= altss_get(LocalContext
);
2695 ALCcontext_IncRef(context
);
2699 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2701 ALCcontext_IncRef(context
);
2709 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2711 ALCdevice
*device
= context
->Device
;
2712 ALsizei num_sends
= device
->NumAuxSends
;
2713 struct ALvoiceProps
*props
;
2714 size_t sizeof_props
;
2715 size_t sizeof_voice
;
2721 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2724 /* Allocate the voice pointers, voices, and the voices' stored source
2725 * property set (including the dynamically-sized Send[] array) in one
2728 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2729 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2730 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2732 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2733 /* The voice and property objects are stored interleaved since they're
2736 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2737 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2741 ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2742 for(;v
< v_count
;v
++)
2744 ALsizei s_count
= mini(old_sends
, num_sends
);
2745 ALvoice
*old_voice
= context
->Voices
[v
];
2748 /* Copy the old voice data and source property set to the new
2751 *voice
= *old_voice
;
2752 for(i
= 0;i
< s_count
;i
++)
2753 voice
->Send
[i
] = old_voice
->Send
[i
];
2754 *props
= *(old_voice
->Props
);
2755 for(i
= 0;i
< s_count
;i
++)
2756 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2758 /* Set this voice's property set pointer and voice reference. */
2759 voice
->Props
= props
;
2762 /* Increment pointers to the next storage space. */
2763 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2764 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2766 /* Deinit any left over voices that weren't copied over to the new
2767 * array. NOTE: If this does anything, v equals num_voices and
2768 * num_voices is less than VoiceCount, so the following loop won't do
2771 for(;v
< context
->VoiceCount
;v
++)
2772 DeinitVoice(context
->Voices
[v
]);
2774 /* Finish setting the voices' property set pointers and references. */
2775 for(;v
< num_voices
;v
++)
2777 ATOMIC_INIT(&voice
->Update
, NULL
);
2778 ATOMIC_INIT(&voice
->FreeList
, NULL
);
2780 voice
->Props
= props
;
2783 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2784 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2787 al_free(context
->Voices
);
2788 context
->Voices
= voices
;
2789 context
->MaxVoices
= num_voices
;
2790 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2794 /************************************************
2795 * Standard ALC functions
2796 ************************************************/
2800 * Return last ALC generated error code for the given device
2802 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2806 if(VerifyDevice(&device
))
2808 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2809 ALCdevice_DecRef(device
);
2812 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2818 /* alcSuspendContext
2820 * Suspends updates for the given context
2822 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2827 if(!VerifyContext(&context
))
2828 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2831 ALCcontext_DeferUpdates(context
);
2832 ALCcontext_DecRef(context
);
2836 /* alcProcessContext
2838 * Resumes processing updates for the given context
2840 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2845 if(!VerifyContext(&context
))
2846 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2849 ALCcontext_ProcessUpdates(context
);
2850 ALCcontext_DecRef(context
);
2857 * Returns information about the device, and error strings
2859 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2861 const ALCchar
*value
= NULL
;
2869 case ALC_INVALID_ENUM
:
2870 value
= alcErrInvalidEnum
;
2873 case ALC_INVALID_VALUE
:
2874 value
= alcErrInvalidValue
;
2877 case ALC_INVALID_DEVICE
:
2878 value
= alcErrInvalidDevice
;
2881 case ALC_INVALID_CONTEXT
:
2882 value
= alcErrInvalidContext
;
2885 case ALC_OUT_OF_MEMORY
:
2886 value
= alcErrOutOfMemory
;
2889 case ALC_DEVICE_SPECIFIER
:
2890 value
= alcDefaultName
;
2893 case ALC_ALL_DEVICES_SPECIFIER
:
2894 if(VerifyDevice(&Device
))
2896 value
= alstr_get_cstr(Device
->DeviceName
);
2897 ALCdevice_DecRef(Device
);
2901 ProbeAllDevicesList();
2902 value
= alstr_get_cstr(alcAllDevicesList
);
2906 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2907 if(VerifyDevice(&Device
))
2909 value
= alstr_get_cstr(Device
->DeviceName
);
2910 ALCdevice_DecRef(Device
);
2914 ProbeCaptureDeviceList();
2915 value
= alstr_get_cstr(alcCaptureDeviceList
);
2919 /* Default devices are always first in the list */
2920 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2921 value
= alcDefaultName
;
2924 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2925 if(alstr_empty(alcAllDevicesList
))
2926 ProbeAllDevicesList();
2928 VerifyDevice(&Device
);
2930 free(alcDefaultAllDevicesSpecifier
);
2931 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
2932 if(!alcDefaultAllDevicesSpecifier
)
2933 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2935 value
= alcDefaultAllDevicesSpecifier
;
2936 if(Device
) ALCdevice_DecRef(Device
);
2939 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2940 if(alstr_empty(alcCaptureDeviceList
))
2941 ProbeCaptureDeviceList();
2943 VerifyDevice(&Device
);
2945 free(alcCaptureDefaultDeviceSpecifier
);
2946 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
2947 if(!alcCaptureDefaultDeviceSpecifier
)
2948 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2950 value
= alcCaptureDefaultDeviceSpecifier
;
2951 if(Device
) ALCdevice_DecRef(Device
);
2954 case ALC_EXTENSIONS
:
2955 if(!VerifyDevice(&Device
))
2956 value
= alcNoDeviceExtList
;
2959 value
= alcExtensionList
;
2960 ALCdevice_DecRef(Device
);
2964 case ALC_HRTF_SPECIFIER_SOFT
:
2965 if(!VerifyDevice(&Device
))
2966 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2969 almtx_lock(&Device
->BackendLock
);
2970 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
2971 almtx_unlock(&Device
->BackendLock
);
2972 ALCdevice_DecRef(Device
);
2977 VerifyDevice(&Device
);
2978 alcSetError(Device
, ALC_INVALID_ENUM
);
2979 if(Device
) ALCdevice_DecRef(Device
);
2987 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
2989 if(device
->Type
== Loopback
&& device
->FmtChans
== DevFmtAmbi3D
)
2994 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2998 if(size
<= 0 || values
== NULL
)
3000 alcSetError(device
, ALC_INVALID_VALUE
);
3008 case ALC_MAJOR_VERSION
:
3009 values
[0] = alcMajorVersion
;
3011 case ALC_MINOR_VERSION
:
3012 values
[0] = alcMinorVersion
;
3015 case ALC_ATTRIBUTES_SIZE
:
3016 case ALC_ALL_ATTRIBUTES
:
3020 case ALC_MONO_SOURCES
:
3021 case ALC_STEREO_SOURCES
:
3022 case ALC_CAPTURE_SAMPLES
:
3023 case ALC_FORMAT_CHANNELS_SOFT
:
3024 case ALC_FORMAT_TYPE_SOFT
:
3025 case ALC_AMBISONIC_LAYOUT_SOFT
:
3026 case ALC_AMBISONIC_SCALING_SOFT
:
3027 case ALC_AMBISONIC_ORDER_SOFT
:
3028 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3032 alcSetError(NULL
, ALC_INVALID_ENUM
);
3038 if(device
->Type
== Capture
)
3042 case ALC_CAPTURE_SAMPLES
:
3043 almtx_lock(&device
->BackendLock
);
3044 values
[0] = V0(device
->Backend
,availableSamples
)();
3045 almtx_unlock(&device
->BackendLock
);
3049 values
[0] = device
->Connected
;
3053 alcSetError(device
, ALC_INVALID_ENUM
);
3062 case ALC_MAJOR_VERSION
:
3063 values
[0] = alcMajorVersion
;
3066 case ALC_MINOR_VERSION
:
3067 values
[0] = alcMinorVersion
;
3070 case ALC_EFX_MAJOR_VERSION
:
3071 values
[0] = alcEFXMajorVersion
;
3074 case ALC_EFX_MINOR_VERSION
:
3075 values
[0] = alcEFXMinorVersion
;
3078 case ALC_ATTRIBUTES_SIZE
:
3079 values
[0] = NumAttrsForDevice(device
);
3082 case ALC_ALL_ATTRIBUTES
:
3083 if(size
< NumAttrsForDevice(device
))
3085 alcSetError(device
, ALC_INVALID_VALUE
);
3090 almtx_lock(&device
->BackendLock
);
3091 values
[i
++] = ALC_FREQUENCY
;
3092 values
[i
++] = device
->Frequency
;
3094 if(device
->Type
!= Loopback
)
3096 values
[i
++] = ALC_REFRESH
;
3097 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3099 values
[i
++] = ALC_SYNC
;
3100 values
[i
++] = ALC_FALSE
;
3104 if(device
->FmtChans
== DevFmtAmbi3D
)
3106 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3107 values
[i
++] = device
->AmbiLayout
;
3109 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3110 values
[i
++] = device
->AmbiScale
;
3112 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3113 values
[i
++] = device
->AmbiOrder
;
3116 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3117 values
[i
++] = device
->FmtChans
;
3119 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3120 values
[i
++] = device
->FmtType
;
3123 values
[i
++] = ALC_MONO_SOURCES
;
3124 values
[i
++] = device
->NumMonoSources
;
3126 values
[i
++] = ALC_STEREO_SOURCES
;
3127 values
[i
++] = device
->NumStereoSources
;
3129 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3130 values
[i
++] = device
->NumAuxSends
;
3132 values
[i
++] = ALC_HRTF_SOFT
;
3133 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3135 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3136 values
[i
++] = device
->HrtfStatus
;
3137 almtx_unlock(&device
->BackendLock
);
3143 values
[0] = device
->Frequency
;
3147 if(device
->Type
== Loopback
)
3149 alcSetError(device
, ALC_INVALID_DEVICE
);
3152 almtx_lock(&device
->BackendLock
);
3153 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3154 almtx_unlock(&device
->BackendLock
);
3158 if(device
->Type
== Loopback
)
3160 alcSetError(device
, ALC_INVALID_DEVICE
);
3163 values
[0] = ALC_FALSE
;
3166 case ALC_FORMAT_CHANNELS_SOFT
:
3167 if(device
->Type
!= Loopback
)
3169 alcSetError(device
, ALC_INVALID_DEVICE
);
3172 values
[0] = device
->FmtChans
;
3175 case ALC_FORMAT_TYPE_SOFT
:
3176 if(device
->Type
!= Loopback
)
3178 alcSetError(device
, ALC_INVALID_DEVICE
);
3181 values
[0] = device
->FmtType
;
3184 case ALC_AMBISONIC_LAYOUT_SOFT
:
3185 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3187 alcSetError(device
, ALC_INVALID_DEVICE
);
3190 values
[0] = device
->AmbiLayout
;
3193 case ALC_AMBISONIC_SCALING_SOFT
:
3194 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3196 alcSetError(device
, ALC_INVALID_DEVICE
);
3199 values
[0] = device
->AmbiScale
;
3202 case ALC_AMBISONIC_ORDER_SOFT
:
3203 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3205 alcSetError(device
, ALC_INVALID_DEVICE
);
3208 values
[0] = device
->AmbiOrder
;
3211 case ALC_MONO_SOURCES
:
3212 values
[0] = device
->NumMonoSources
;
3215 case ALC_STEREO_SOURCES
:
3216 values
[0] = device
->NumStereoSources
;
3219 case ALC_MAX_AUXILIARY_SENDS
:
3220 values
[0] = device
->NumAuxSends
;
3224 values
[0] = device
->Connected
;
3228 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3231 case ALC_HRTF_STATUS_SOFT
:
3232 values
[0] = device
->HrtfStatus
;
3235 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3236 almtx_lock(&device
->BackendLock
);
3237 FreeHrtfList(&device
->HrtfList
);
3238 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3239 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3240 almtx_unlock(&device
->BackendLock
);
3244 alcSetError(device
, ALC_INVALID_ENUM
);
3252 * Returns information about the device and the version of OpenAL
3254 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3256 VerifyDevice(&device
);
3257 if(size
<= 0 || values
== NULL
)
3258 alcSetError(device
, ALC_INVALID_VALUE
);
3260 GetIntegerv(device
, param
, size
, values
);
3261 if(device
) ALCdevice_DecRef(device
);
3264 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3269 VerifyDevice(&device
);
3270 if(size
<= 0 || values
== NULL
)
3271 alcSetError(device
, ALC_INVALID_VALUE
);
3272 else if(!device
|| device
->Type
== Capture
)
3274 ivals
= malloc(size
* sizeof(ALCint
));
3275 size
= GetIntegerv(device
, pname
, size
, ivals
);
3276 for(i
= 0;i
< size
;i
++)
3277 values
[i
] = ivals
[i
];
3280 else /* render device */
3289 case ALC_ATTRIBUTES_SIZE
:
3290 *values
= NumAttrsForDevice(device
)+4;
3293 case ALC_ALL_ATTRIBUTES
:
3294 if(size
< NumAttrsForDevice(device
)+4)
3295 alcSetError(device
, ALC_INVALID_VALUE
);
3299 almtx_lock(&device
->BackendLock
);
3300 values
[i
++] = ALC_FREQUENCY
;
3301 values
[i
++] = device
->Frequency
;
3303 if(device
->Type
!= Loopback
)
3305 values
[i
++] = ALC_REFRESH
;
3306 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3308 values
[i
++] = ALC_SYNC
;
3309 values
[i
++] = ALC_FALSE
;
3313 if(device
->FmtChans
== DevFmtAmbi3D
)
3315 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3316 values
[i
++] = device
->AmbiLayout
;
3318 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3319 values
[i
++] = device
->AmbiScale
;
3321 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3322 values
[i
++] = device
->AmbiOrder
;
3325 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3326 values
[i
++] = device
->FmtChans
;
3328 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3329 values
[i
++] = device
->FmtType
;
3332 values
[i
++] = ALC_MONO_SOURCES
;
3333 values
[i
++] = device
->NumMonoSources
;
3335 values
[i
++] = ALC_STEREO_SOURCES
;
3336 values
[i
++] = device
->NumStereoSources
;
3338 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3339 values
[i
++] = device
->NumAuxSends
;
3341 values
[i
++] = ALC_HRTF_SOFT
;
3342 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3344 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3345 values
[i
++] = device
->HrtfStatus
;
3347 clock
= V0(device
->Backend
,getClockLatency
)();
3348 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3349 values
[i
++] = clock
.ClockTime
;
3351 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3352 values
[i
++] = clock
.Latency
;
3353 almtx_unlock(&device
->BackendLock
);
3359 case ALC_DEVICE_CLOCK_SOFT
:
3360 almtx_lock(&device
->BackendLock
);
3362 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3364 basecount
= device
->ClockBase
;
3365 samplecount
= device
->SamplesDone
;
3366 } while(refcount
!= ReadRef(&device
->MixCount
));
3367 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3368 almtx_unlock(&device
->BackendLock
);
3371 case ALC_DEVICE_LATENCY_SOFT
:
3372 almtx_lock(&device
->BackendLock
);
3373 clock
= V0(device
->Backend
,getClockLatency
)();
3374 almtx_unlock(&device
->BackendLock
);
3375 *values
= clock
.Latency
;
3378 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3380 alcSetError(device
, ALC_INVALID_VALUE
);
3383 almtx_lock(&device
->BackendLock
);
3384 clock
= V0(device
->Backend
,getClockLatency
)();
3385 almtx_unlock(&device
->BackendLock
);
3386 values
[0] = clock
.ClockTime
;
3387 values
[1] = clock
.Latency
;
3392 ivals
= malloc(size
* sizeof(ALCint
));
3393 size
= GetIntegerv(device
, pname
, size
, ivals
);
3394 for(i
= 0;i
< size
;i
++)
3395 values
[i
] = ivals
[i
];
3401 ALCdevice_DecRef(device
);
3405 /* alcIsExtensionPresent
3407 * Determines if there is support for a particular extension
3409 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3411 ALCboolean bResult
= ALC_FALSE
;
3413 VerifyDevice(&device
);
3416 alcSetError(device
, ALC_INVALID_VALUE
);
3419 size_t len
= strlen(extName
);
3420 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3423 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3424 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3429 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3433 } while(isspace(*ptr
));
3438 ALCdevice_DecRef(device
);
3443 /* alcGetProcAddress
3445 * Retrieves the function address for a particular extension function
3447 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3449 ALCvoid
*ptr
= NULL
;
3453 VerifyDevice(&device
);
3454 alcSetError(device
, ALC_INVALID_VALUE
);
3455 if(device
) ALCdevice_DecRef(device
);
3460 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3462 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3464 ptr
= alcFunctions
[i
].address
;
3476 * Get the value for a particular ALC enumeration name
3478 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3484 VerifyDevice(&device
);
3485 alcSetError(device
, ALC_INVALID_VALUE
);
3486 if(device
) ALCdevice_DecRef(device
);
3491 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3493 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3495 val
= alcEnumerations
[i
].value
;
3507 * Create and attach a context to the given device.
3509 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3511 ALCcontext
*ALContext
;
3515 /* Explicitly hold the list lock while taking the BackendLock in case the
3516 * device is asynchronously destropyed, to ensure this new context is
3517 * properly cleaned up after being made.
3520 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3523 alcSetError(device
, ALC_INVALID_DEVICE
);
3524 if(device
) ALCdevice_DecRef(device
);
3527 almtx_lock(&device
->BackendLock
);
3530 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3532 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3535 InitRef(&ALContext
->ref
, 1);
3536 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3538 ALContext
->Device
= device
;
3539 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3541 ALContext
->Voices
= NULL
;
3542 ALContext
->MaxVoices
= 0;
3543 ALContext
->VoiceCount
= 0;
3544 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3546 if(!ALContext
|| !ALContext
->Voices
)
3548 almtx_unlock(&device
->BackendLock
);
3552 al_free(ALContext
->Voices
);
3553 ALContext
->Voices
= NULL
;
3559 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3560 ALCdevice_DecRef(device
);
3564 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3566 almtx_unlock(&device
->BackendLock
);
3568 al_free(ALContext
->Voices
);
3569 ALContext
->Voices
= NULL
;
3574 alcSetError(device
, err
);
3575 if(err
== ALC_INVALID_DEVICE
)
3577 V0(device
->Backend
,lock
)();
3578 aluHandleDisconnect(device
);
3579 V0(device
->Backend
,unlock
)();
3581 ALCdevice_DecRef(device
);
3585 ALCdevice_IncRef(ALContext
->Device
);
3586 InitContext(ALContext
);
3588 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3591 ERR("volume-adjust must be finite: %f\n", valf
);
3594 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3596 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3597 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3598 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3601 UpdateListenerProps(ALContext
);
3604 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3606 ALContext
->next
= head
;
3607 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3610 almtx_unlock(&device
->BackendLock
);
3612 ALCdevice_DecRef(device
);
3614 TRACE("Created context %p\n", ALContext
);
3618 /* alcDestroyContext
3620 * Remove a context from its device
3622 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3627 if(!VerifyContext(&context
))
3630 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3634 Device
= context
->Device
;
3637 almtx_lock(&Device
->BackendLock
);
3638 if(!ReleaseContext(context
, Device
))
3640 V0(Device
->Backend
,stop
)();
3641 Device
->Flags
&= ~DEVICE_RUNNING
;
3643 almtx_unlock(&Device
->BackendLock
);
3647 ALCcontext_DecRef(context
);
3651 /* alcGetCurrentContext
3653 * Returns the currently active context on the calling thread
3655 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3657 ALCcontext
*Context
= altss_get(LocalContext
);
3658 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3662 /* alcGetThreadContext
3664 * Returns the currently active thread-local context
3666 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3668 return altss_get(LocalContext
);
3672 /* alcMakeContextCurrent
3674 * Makes the given context the active process-wide context, and removes the
3675 * thread-local context for the calling thread.
3677 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3679 /* context must be valid or NULL */
3680 if(context
&& !VerifyContext(&context
))
3682 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3685 /* context's reference count is already incremented */
3686 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3687 if(context
) ALCcontext_DecRef(context
);
3689 if((context
=altss_get(LocalContext
)) != NULL
)
3691 altss_set(LocalContext
, NULL
);
3692 ALCcontext_DecRef(context
);
3698 /* alcSetThreadContext
3700 * Makes the given context the active context for the current thread
3702 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3706 /* context must be valid or NULL */
3707 if(context
&& !VerifyContext(&context
))
3709 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3712 /* context's reference count is already incremented */
3713 old
= altss_get(LocalContext
);
3714 altss_set(LocalContext
, context
);
3715 if(old
) ALCcontext_DecRef(old
);
3721 /* alcGetContextsDevice
3723 * Returns the device that a particular context is attached to
3725 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3729 if(!VerifyContext(&Context
))
3731 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3734 Device
= Context
->Device
;
3735 ALCcontext_DecRef(Context
);
3743 * Opens the named device.
3745 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3754 if(!PlaybackBackend
.name
)
3756 alcSetError(NULL
, ALC_INVALID_VALUE
);
3760 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3762 /* Some old Windows apps hardcode these expecting OpenAL to use a
3763 * specific audio API, even when they're not enumerated. Creative's
3764 * router effectively ignores them too.
3766 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3767 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3772 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3775 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3780 InitRef(&device
->ref
, 1);
3781 device
->Connected
= ALC_TRUE
;
3782 device
->Type
= Playback
;
3783 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3786 device
->Bs2b
= NULL
;
3787 device
->Uhj_Encoder
= NULL
;
3788 device
->Hrtf
= NULL
;
3789 device
->HrtfHandle
= NULL
;
3790 VECTOR_INIT(device
->HrtfList
);
3791 AL_STRING_INIT(device
->HrtfName
);
3792 device
->Render_Mode
= NormalRender
;
3793 AL_STRING_INIT(device
->DeviceName
);
3794 device
->Dry
.Buffer
= NULL
;
3795 device
->Dry
.NumChannels
= 0;
3796 device
->FOAOut
.Buffer
= NULL
;
3797 device
->FOAOut
.NumChannels
= 0;
3798 device
->RealOut
.Buffer
= NULL
;
3799 device
->RealOut
.NumChannels
= 0;
3800 device
->AvgSpeakerDist
= 0.0f
;
3802 ATOMIC_INIT(&device
->ContextList
, NULL
);
3804 device
->ClockBase
= 0;
3805 device
->SamplesDone
= 0;
3807 device
->SourcesMax
= 256;
3808 device
->AuxiliaryEffectSlotMax
= 64;
3809 device
->NumAuxSends
= DEFAULT_SENDS
;
3811 InitUIntMap(&device
->BufferMap
, INT_MAX
);
3812 InitUIntMap(&device
->EffectMap
, INT_MAX
);
3813 InitUIntMap(&device
->FilterMap
, INT_MAX
);
3815 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3817 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3818 device
->ChannelDelay
[i
].Length
= 0;
3819 device
->ChannelDelay
[i
].Buffer
= NULL
;
3823 device
->FmtChans
= DevFmtChannelsDefault
;
3824 device
->FmtType
= DevFmtTypeDefault
;
3825 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3826 device
->IsHeadphones
= AL_FALSE
;
3827 device
->AmbiLayout
= AmbiLayout_Default
;
3828 device
->AmbiScale
= AmbiNorm_Default
;
3829 device
->NumUpdates
= 3;
3830 device
->UpdateSize
= 1024;
3832 if(!PlaybackBackend
.getFactory
)
3833 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3834 ALCbackend_Playback
);
3837 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3838 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3840 if(!device
->Backend
)
3843 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3848 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3850 static const struct {
3851 const char name
[16];
3852 enum DevFmtChannels chans
;
3855 { "mono", DevFmtMono
, 0 },
3856 { "stereo", DevFmtStereo
, 0 },
3857 { "quad", DevFmtQuad
, 0 },
3858 { "surround51", DevFmtX51
, 0 },
3859 { "surround61", DevFmtX61
, 0 },
3860 { "surround71", DevFmtX71
, 0 },
3861 { "surround51rear", DevFmtX51Rear
, 0 },
3862 { "ambi1", DevFmtAmbi3D
, 1 },
3863 { "ambi2", DevFmtAmbi3D
, 2 },
3864 { "ambi3", DevFmtAmbi3D
, 3 },
3868 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3870 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3872 device
->FmtChans
= chanlist
[i
].chans
;
3873 device
->AmbiOrder
= chanlist
[i
].order
;
3874 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3878 if(i
== COUNTOF(chanlist
))
3879 ERR("Unsupported channels: %s\n", fmt
);
3881 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3883 static const struct {
3884 const char name
[16];
3885 enum DevFmtType type
;
3887 { "int8", DevFmtByte
},
3888 { "uint8", DevFmtUByte
},
3889 { "int16", DevFmtShort
},
3890 { "uint16", DevFmtUShort
},
3891 { "int32", DevFmtInt
},
3892 { "uint32", DevFmtUInt
},
3893 { "float32", DevFmtFloat
},
3897 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3899 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3901 device
->FmtType
= typelist
[i
].type
;
3902 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3906 if(i
== COUNTOF(typelist
))
3907 ERR("Unsupported sample-type: %s\n", fmt
);
3910 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3912 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3913 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3914 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3915 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3918 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3919 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3921 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3922 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3923 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3924 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3926 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3927 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3929 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3930 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3932 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3933 device
->NumAuxSends
= clampi(
3934 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3937 device
->NumStereoSources
= 1;
3938 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3940 // Find a playback device to open
3941 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3943 DELETE_OBJ(device
->Backend
);
3945 alcSetError(NULL
, err
);
3948 almtx_init(&device
->BackendLock
, almtx_plain
);
3950 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3952 if(strcasecmp(fmt
, "fuma") == 0)
3954 device
->AmbiLayout
= AmbiLayout_FuMa
;
3955 device
->AmbiScale
= AmbiNorm_FuMa
;
3957 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
3959 device
->AmbiLayout
= AmbiLayout_ACN
;
3960 device
->AmbiScale
= AmbiNorm_SN3D
;
3962 else if(strcasecmp(fmt
, "acn+n3d") == 0)
3964 device
->AmbiLayout
= AmbiLayout_ACN
;
3965 device
->AmbiScale
= AmbiNorm_N3D
;
3968 ERR("Unsupported ambi-format: %s\n", fmt
);
3971 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3973 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3974 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3976 device
->DefaultSlot
= NULL
;
3977 ERR("Failed to initialize the default effect slot\n");
3981 aluInitEffectPanning(device
->DefaultSlot
);
3982 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3984 DeinitEffectSlot(device
->DefaultSlot
);
3985 device
->DefaultSlot
= NULL
;
3986 ERR("Failed to initialize the default effect\n");
3992 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
3994 device
->next
= head
;
3995 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
3998 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4004 * Closes the given device.
4006 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4008 ALCdevice
*iter
, *origdev
;
4012 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4016 } while((iter
=iter
->next
) != NULL
);
4017 if(!iter
|| iter
->Type
== Capture
)
4019 alcSetError(iter
, ALC_INVALID_DEVICE
);
4023 almtx_lock(&device
->BackendLock
);
4026 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4028 ALCdevice
*volatile*list
= &origdev
->next
;
4033 *list
= (*list
)->next
;
4036 list
= &(*list
)->next
;
4041 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4044 ALCcontext
*next
= ctx
->next
;
4045 WARN("Releasing context %p\n", ctx
);
4046 ReleaseContext(ctx
, device
);
4049 if((device
->Flags
&DEVICE_RUNNING
))
4050 V0(device
->Backend
,stop
)();
4051 device
->Flags
&= ~DEVICE_RUNNING
;
4052 almtx_unlock(&device
->BackendLock
);
4054 ALCdevice_DecRef(device
);
4060 /************************************************
4061 * ALC capture functions
4062 ************************************************/
4063 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4065 ALCdevice
*device
= NULL
;
4071 if(!CaptureBackend
.name
)
4073 alcSetError(NULL
, ALC_INVALID_VALUE
);
4079 alcSetError(NULL
, ALC_INVALID_VALUE
);
4083 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4086 device
= al_calloc(16, sizeof(ALCdevice
));
4089 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4094 InitRef(&device
->ref
, 1);
4095 device
->Connected
= ALC_TRUE
;
4096 device
->Type
= Capture
;
4098 device
->Hrtf
= NULL
;
4099 device
->HrtfHandle
= NULL
;
4100 VECTOR_INIT(device
->HrtfList
);
4101 AL_STRING_INIT(device
->HrtfName
);
4103 AL_STRING_INIT(device
->DeviceName
);
4104 device
->Dry
.Buffer
= NULL
;
4105 device
->Dry
.NumChannels
= 0;
4106 device
->FOAOut
.Buffer
= NULL
;
4107 device
->FOAOut
.NumChannels
= 0;
4108 device
->RealOut
.Buffer
= NULL
;
4109 device
->RealOut
.NumChannels
= 0;
4111 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4112 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4113 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4115 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4117 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4118 device
->ChannelDelay
[i
].Length
= 0;
4119 device
->ChannelDelay
[i
].Buffer
= NULL
;
4122 if(!CaptureBackend
.getFactory
)
4123 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4124 ALCbackend_Capture
);
4127 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4128 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4130 if(!device
->Backend
)
4133 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4137 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4138 device
->Frequency
= frequency
;
4140 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4141 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4144 alcSetError(NULL
, ALC_INVALID_ENUM
);
4147 device
->IsHeadphones
= AL_FALSE
;
4148 device
->AmbiOrder
= 0;
4149 device
->AmbiLayout
= AmbiLayout_Default
;
4150 device
->AmbiScale
= AmbiNorm_Default
;
4152 device
->UpdateSize
= samples
;
4153 device
->NumUpdates
= 1;
4155 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4156 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4157 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4159 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4162 alcSetError(NULL
, err
);
4165 almtx_init(&device
->BackendLock
, almtx_plain
);
4168 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4170 device
->next
= head
;
4171 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4174 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4178 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4180 ALCdevice
*iter
, *origdev
;
4183 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4187 } while((iter
=iter
->next
) != NULL
);
4188 if(!iter
|| iter
->Type
!= Capture
)
4190 alcSetError(iter
, ALC_INVALID_DEVICE
);
4196 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4198 ALCdevice
*volatile*list
= &origdev
->next
;
4203 *list
= (*list
)->next
;
4206 list
= &(*list
)->next
;
4211 ALCdevice_DecRef(device
);
4216 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4218 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4219 alcSetError(device
, ALC_INVALID_DEVICE
);
4222 almtx_lock(&device
->BackendLock
);
4223 if(!device
->Connected
)
4224 alcSetError(device
, ALC_INVALID_DEVICE
);
4225 else if(!(device
->Flags
&DEVICE_RUNNING
))
4227 if(V0(device
->Backend
,start
)())
4228 device
->Flags
|= DEVICE_RUNNING
;
4231 aluHandleDisconnect(device
);
4232 alcSetError(device
, ALC_INVALID_DEVICE
);
4235 almtx_unlock(&device
->BackendLock
);
4238 if(device
) ALCdevice_DecRef(device
);
4241 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4243 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4244 alcSetError(device
, ALC_INVALID_DEVICE
);
4247 almtx_lock(&device
->BackendLock
);
4248 if((device
->Flags
&DEVICE_RUNNING
))
4249 V0(device
->Backend
,stop
)();
4250 device
->Flags
&= ~DEVICE_RUNNING
;
4251 almtx_unlock(&device
->BackendLock
);
4254 if(device
) ALCdevice_DecRef(device
);
4257 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4259 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4260 alcSetError(device
, ALC_INVALID_DEVICE
);
4263 ALCenum err
= ALC_INVALID_VALUE
;
4265 almtx_lock(&device
->BackendLock
);
4266 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4267 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4268 almtx_unlock(&device
->BackendLock
);
4270 if(err
!= ALC_NO_ERROR
)
4271 alcSetError(device
, err
);
4273 if(device
) ALCdevice_DecRef(device
);
4277 /************************************************
4278 * ALC loopback functions
4279 ************************************************/
4281 /* alcLoopbackOpenDeviceSOFT
4283 * Open a loopback device, for manual rendering.
4285 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4287 ALCbackendFactory
*factory
;
4293 /* Make sure the device name, if specified, is us. */
4294 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4296 alcSetError(NULL
, ALC_INVALID_VALUE
);
4300 device
= al_calloc(16, sizeof(ALCdevice
));
4303 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4308 InitRef(&device
->ref
, 1);
4309 device
->Connected
= ALC_TRUE
;
4310 device
->Type
= Loopback
;
4311 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4314 device
->Hrtf
= NULL
;
4315 device
->HrtfHandle
= NULL
;
4316 VECTOR_INIT(device
->HrtfList
);
4317 AL_STRING_INIT(device
->HrtfName
);
4318 device
->Bs2b
= NULL
;
4319 device
->Uhj_Encoder
= NULL
;
4320 device
->Render_Mode
= NormalRender
;
4321 AL_STRING_INIT(device
->DeviceName
);
4322 device
->Dry
.Buffer
= NULL
;
4323 device
->Dry
.NumChannels
= 0;
4324 device
->FOAOut
.Buffer
= NULL
;
4325 device
->FOAOut
.NumChannels
= 0;
4326 device
->RealOut
.Buffer
= NULL
;
4327 device
->RealOut
.NumChannels
= 0;
4328 device
->AvgSpeakerDist
= 0.0f
;
4330 ATOMIC_INIT(&device
->ContextList
, NULL
);
4332 device
->ClockBase
= 0;
4333 device
->SamplesDone
= 0;
4335 device
->SourcesMax
= 256;
4336 device
->AuxiliaryEffectSlotMax
= 64;
4337 device
->NumAuxSends
= DEFAULT_SENDS
;
4339 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4340 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4341 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4343 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4345 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4346 device
->ChannelDelay
[i
].Length
= 0;
4347 device
->ChannelDelay
[i
].Buffer
= NULL
;
4350 factory
= ALCloopbackFactory_getFactory();
4351 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4352 if(!device
->Backend
)
4355 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4358 almtx_init(&device
->BackendLock
, almtx_plain
);
4361 device
->NumUpdates
= 0;
4362 device
->UpdateSize
= 0;
4364 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4365 device
->FmtChans
= DevFmtChannelsDefault
;
4366 device
->FmtType
= DevFmtTypeDefault
;
4367 device
->IsHeadphones
= AL_FALSE
;
4368 device
->AmbiLayout
= AmbiLayout_Default
;
4369 device
->AmbiScale
= AmbiNorm_Default
;
4371 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4372 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4374 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4375 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4377 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4378 device
->NumAuxSends
= clampi(
4379 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4382 device
->NumStereoSources
= 1;
4383 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4385 // Open the "backend"
4386 V(device
->Backend
,open
)("Loopback");
4389 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4391 device
->next
= head
;
4392 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4395 TRACE("Created device %p\n", device
);
4399 /* alcIsRenderFormatSupportedSOFT
4401 * Determines if the loopback device supports the given format for rendering.
4403 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4405 ALCboolean ret
= ALC_FALSE
;
4407 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4408 alcSetError(device
, ALC_INVALID_DEVICE
);
4410 alcSetError(device
, ALC_INVALID_VALUE
);
4413 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4416 if(device
) ALCdevice_DecRef(device
);
4421 /* alcRenderSamplesSOFT
4423 * Renders some samples into a buffer, using the format last set by the
4424 * attributes given to alcCreateContext.
4426 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4428 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4429 alcSetError(device
, ALC_INVALID_DEVICE
);
4430 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4431 alcSetError(device
, ALC_INVALID_VALUE
);
4434 V0(device
->Backend
,lock
)();
4435 aluMixData(device
, buffer
, samples
);
4436 V0(device
->Backend
,unlock
)();
4438 if(device
) ALCdevice_DecRef(device
);
4442 /************************************************
4443 * ALC loopback2 functions
4444 ************************************************/
4446 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4448 ALCboolean ret
= ALC_FALSE
;
4450 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4451 alcSetError(device
, ALC_INVALID_DEVICE
);
4453 alcSetError(device
, ALC_INVALID_VALUE
);
4456 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4459 if(device
) ALCdevice_DecRef(device
);
4464 /************************************************
4465 * ALC DSP pause/resume functions
4466 ************************************************/
4468 /* alcDevicePauseSOFT
4470 * Pause the DSP to stop audio processing.
4472 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4474 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4475 alcSetError(device
, ALC_INVALID_DEVICE
);
4478 almtx_lock(&device
->BackendLock
);
4479 if((device
->Flags
&DEVICE_RUNNING
))
4480 V0(device
->Backend
,stop
)();
4481 device
->Flags
&= ~DEVICE_RUNNING
;
4482 device
->Flags
|= DEVICE_PAUSED
;
4483 almtx_unlock(&device
->BackendLock
);
4485 if(device
) ALCdevice_DecRef(device
);
4488 /* alcDeviceResumeSOFT
4490 * Resume the DSP to restart audio processing.
4492 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4494 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4495 alcSetError(device
, ALC_INVALID_DEVICE
);
4498 almtx_lock(&device
->BackendLock
);
4499 if((device
->Flags
&DEVICE_PAUSED
))
4501 device
->Flags
&= ~DEVICE_PAUSED
;
4502 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4504 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4505 device
->Flags
|= DEVICE_RUNNING
;
4508 alcSetError(device
, ALC_INVALID_DEVICE
);
4509 V0(device
->Backend
,lock
)();
4510 aluHandleDisconnect(device
);
4511 V0(device
->Backend
,unlock
)();
4515 almtx_unlock(&device
->BackendLock
);
4517 if(device
) ALCdevice_DecRef(device
);
4521 /************************************************
4522 * ALC HRTF functions
4523 ************************************************/
4525 /* alcGetStringiSOFT
4527 * Gets a string parameter at the given index.
4529 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4531 const ALCchar
*str
= NULL
;
4533 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4534 alcSetError(device
, ALC_INVALID_DEVICE
);
4535 else switch(paramName
)
4537 case ALC_HRTF_SPECIFIER_SOFT
:
4538 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4539 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4541 alcSetError(device
, ALC_INVALID_VALUE
);
4545 alcSetError(device
, ALC_INVALID_ENUM
);
4548 if(device
) ALCdevice_DecRef(device
);
4553 /* alcResetDeviceSOFT
4555 * Resets the given device output, using the specified attribute list.
4557 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4562 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4565 alcSetError(device
, ALC_INVALID_DEVICE
);
4566 if(device
) ALCdevice_DecRef(device
);
4569 almtx_lock(&device
->BackendLock
);
4572 err
= UpdateDeviceParams(device
, attribs
);
4573 almtx_unlock(&device
->BackendLock
);
4575 if(err
!= ALC_NO_ERROR
)
4577 alcSetError(device
, err
);
4578 if(err
== ALC_INVALID_DEVICE
)
4580 V0(device
->Backend
,lock
)();
4581 aluHandleDisconnect(device
);
4582 V0(device
->Backend
,unlock
)();
4584 ALCdevice_DecRef(device
);
4587 ALCdevice_DecRef(device
);