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
),
291 DECL(alGetStringiSOFT
),
295 #define DECL(x) { #x, (x) }
296 static const struct {
297 const ALCchar
*enumName
;
299 } alcEnumerations
[] = {
304 DECL(ALC_MAJOR_VERSION
),
305 DECL(ALC_MINOR_VERSION
),
306 DECL(ALC_ATTRIBUTES_SIZE
),
307 DECL(ALC_ALL_ATTRIBUTES
),
308 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
309 DECL(ALC_DEVICE_SPECIFIER
),
310 DECL(ALC_ALL_DEVICES_SPECIFIER
),
311 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
312 DECL(ALC_EXTENSIONS
),
316 DECL(ALC_MONO_SOURCES
),
317 DECL(ALC_STEREO_SOURCES
),
318 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
319 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
320 DECL(ALC_CAPTURE_SAMPLES
),
323 DECL(ALC_EFX_MAJOR_VERSION
),
324 DECL(ALC_EFX_MINOR_VERSION
),
325 DECL(ALC_MAX_AUXILIARY_SENDS
),
327 DECL(ALC_FORMAT_CHANNELS_SOFT
),
328 DECL(ALC_FORMAT_TYPE_SOFT
),
331 DECL(ALC_STEREO_SOFT
),
333 DECL(ALC_5POINT1_SOFT
),
334 DECL(ALC_6POINT1_SOFT
),
335 DECL(ALC_7POINT1_SOFT
),
336 DECL(ALC_BFORMAT3D_SOFT
),
339 DECL(ALC_UNSIGNED_BYTE_SOFT
),
340 DECL(ALC_SHORT_SOFT
),
341 DECL(ALC_UNSIGNED_SHORT_SOFT
),
343 DECL(ALC_UNSIGNED_INT_SOFT
),
344 DECL(ALC_FLOAT_SOFT
),
347 DECL(ALC_DONT_CARE_SOFT
),
348 DECL(ALC_HRTF_STATUS_SOFT
),
349 DECL(ALC_HRTF_DISABLED_SOFT
),
350 DECL(ALC_HRTF_ENABLED_SOFT
),
351 DECL(ALC_HRTF_DENIED_SOFT
),
352 DECL(ALC_HRTF_REQUIRED_SOFT
),
353 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
354 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
355 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
356 DECL(ALC_HRTF_SPECIFIER_SOFT
),
357 DECL(ALC_HRTF_ID_SOFT
),
359 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
360 DECL(ALC_AMBISONIC_SCALING_SOFT
),
361 DECL(ALC_AMBISONIC_ORDER_SOFT
),
367 DECL(ALC_OUTPUT_LIMITER_SOFT
),
370 DECL(ALC_INVALID_DEVICE
),
371 DECL(ALC_INVALID_CONTEXT
),
372 DECL(ALC_INVALID_ENUM
),
373 DECL(ALC_INVALID_VALUE
),
374 DECL(ALC_OUT_OF_MEMORY
),
382 DECL(AL_SOURCE_RELATIVE
),
383 DECL(AL_CONE_INNER_ANGLE
),
384 DECL(AL_CONE_OUTER_ANGLE
),
394 DECL(AL_ORIENTATION
),
395 DECL(AL_REFERENCE_DISTANCE
),
396 DECL(AL_ROLLOFF_FACTOR
),
397 DECL(AL_CONE_OUTER_GAIN
),
398 DECL(AL_MAX_DISTANCE
),
400 DECL(AL_SAMPLE_OFFSET
),
401 DECL(AL_BYTE_OFFSET
),
402 DECL(AL_SOURCE_TYPE
),
405 DECL(AL_UNDETERMINED
),
406 DECL(AL_METERS_PER_UNIT
),
407 DECL(AL_LOOP_POINTS_SOFT
),
408 DECL(AL_DIRECT_CHANNELS_SOFT
),
410 DECL(AL_DIRECT_FILTER
),
411 DECL(AL_AUXILIARY_SEND_FILTER
),
412 DECL(AL_AIR_ABSORPTION_FACTOR
),
413 DECL(AL_ROOM_ROLLOFF_FACTOR
),
414 DECL(AL_CONE_OUTER_GAINHF
),
415 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
416 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
417 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
419 DECL(AL_SOURCE_STATE
),
425 DECL(AL_BUFFERS_QUEUED
),
426 DECL(AL_BUFFERS_PROCESSED
),
428 DECL(AL_FORMAT_MONO8
),
429 DECL(AL_FORMAT_MONO16
),
430 DECL(AL_FORMAT_MONO_FLOAT32
),
431 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
432 DECL(AL_FORMAT_STEREO8
),
433 DECL(AL_FORMAT_STEREO16
),
434 DECL(AL_FORMAT_STEREO_FLOAT32
),
435 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
436 DECL(AL_FORMAT_MONO_IMA4
),
437 DECL(AL_FORMAT_STEREO_IMA4
),
438 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
439 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
440 DECL(AL_FORMAT_QUAD8_LOKI
),
441 DECL(AL_FORMAT_QUAD16_LOKI
),
442 DECL(AL_FORMAT_QUAD8
),
443 DECL(AL_FORMAT_QUAD16
),
444 DECL(AL_FORMAT_QUAD32
),
445 DECL(AL_FORMAT_51CHN8
),
446 DECL(AL_FORMAT_51CHN16
),
447 DECL(AL_FORMAT_51CHN32
),
448 DECL(AL_FORMAT_61CHN8
),
449 DECL(AL_FORMAT_61CHN16
),
450 DECL(AL_FORMAT_61CHN32
),
451 DECL(AL_FORMAT_71CHN8
),
452 DECL(AL_FORMAT_71CHN16
),
453 DECL(AL_FORMAT_71CHN32
),
454 DECL(AL_FORMAT_REAR8
),
455 DECL(AL_FORMAT_REAR16
),
456 DECL(AL_FORMAT_REAR32
),
457 DECL(AL_FORMAT_MONO_MULAW
),
458 DECL(AL_FORMAT_MONO_MULAW_EXT
),
459 DECL(AL_FORMAT_STEREO_MULAW
),
460 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
461 DECL(AL_FORMAT_QUAD_MULAW
),
462 DECL(AL_FORMAT_51CHN_MULAW
),
463 DECL(AL_FORMAT_61CHN_MULAW
),
464 DECL(AL_FORMAT_71CHN_MULAW
),
465 DECL(AL_FORMAT_REAR_MULAW
),
466 DECL(AL_FORMAT_MONO_ALAW_EXT
),
467 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
469 DECL(AL_FORMAT_BFORMAT2D_8
),
470 DECL(AL_FORMAT_BFORMAT2D_16
),
471 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
472 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
473 DECL(AL_FORMAT_BFORMAT3D_8
),
474 DECL(AL_FORMAT_BFORMAT3D_16
),
475 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
476 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
479 DECL(AL_MONO16_SOFT
),
480 DECL(AL_MONO32F_SOFT
),
481 DECL(AL_STEREO8_SOFT
),
482 DECL(AL_STEREO16_SOFT
),
483 DECL(AL_STEREO32F_SOFT
),
485 DECL(AL_QUAD16_SOFT
),
486 DECL(AL_QUAD32F_SOFT
),
488 DECL(AL_REAR16_SOFT
),
489 DECL(AL_REAR32F_SOFT
),
490 DECL(AL_5POINT1_8_SOFT
),
491 DECL(AL_5POINT1_16_SOFT
),
492 DECL(AL_5POINT1_32F_SOFT
),
493 DECL(AL_6POINT1_8_SOFT
),
494 DECL(AL_6POINT1_16_SOFT
),
495 DECL(AL_6POINT1_32F_SOFT
),
496 DECL(AL_7POINT1_8_SOFT
),
497 DECL(AL_7POINT1_16_SOFT
),
498 DECL(AL_7POINT1_32F_SOFT
),
499 DECL(AL_BFORMAT2D_8_SOFT
),
500 DECL(AL_BFORMAT2D_16_SOFT
),
501 DECL(AL_BFORMAT2D_32F_SOFT
),
502 DECL(AL_BFORMAT3D_8_SOFT
),
503 DECL(AL_BFORMAT3D_16_SOFT
),
504 DECL(AL_BFORMAT3D_32F_SOFT
),
507 DECL(AL_STEREO_SOFT
),
510 DECL(AL_5POINT1_SOFT
),
511 DECL(AL_6POINT1_SOFT
),
512 DECL(AL_7POINT1_SOFT
),
513 DECL(AL_BFORMAT2D_SOFT
),
514 DECL(AL_BFORMAT3D_SOFT
),
517 DECL(AL_UNSIGNED_BYTE_SOFT
),
519 DECL(AL_UNSIGNED_SHORT_SOFT
),
521 DECL(AL_UNSIGNED_INT_SOFT
),
523 DECL(AL_DOUBLE_SOFT
),
525 DECL(AL_UNSIGNED_BYTE3_SOFT
),
532 DECL(AL_INTERNAL_FORMAT_SOFT
),
533 DECL(AL_BYTE_LENGTH_SOFT
),
534 DECL(AL_SAMPLE_LENGTH_SOFT
),
535 DECL(AL_SEC_LENGTH_SOFT
),
536 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
537 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
539 DECL(AL_SOURCE_RADIUS
),
541 DECL(AL_STEREO_ANGLES
),
548 DECL(AL_INVALID_NAME
),
549 DECL(AL_INVALID_ENUM
),
550 DECL(AL_INVALID_VALUE
),
551 DECL(AL_INVALID_OPERATION
),
552 DECL(AL_OUT_OF_MEMORY
),
559 DECL(AL_DOPPLER_FACTOR
),
560 DECL(AL_DOPPLER_VELOCITY
),
561 DECL(AL_DISTANCE_MODEL
),
562 DECL(AL_SPEED_OF_SOUND
),
563 DECL(AL_SOURCE_DISTANCE_MODEL
),
564 DECL(AL_DEFERRED_UPDATES_SOFT
),
565 DECL(AL_GAIN_LIMIT_SOFT
),
567 DECL(AL_INVERSE_DISTANCE
),
568 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
569 DECL(AL_LINEAR_DISTANCE
),
570 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
571 DECL(AL_EXPONENT_DISTANCE
),
572 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
574 DECL(AL_FILTER_TYPE
),
575 DECL(AL_FILTER_NULL
),
576 DECL(AL_FILTER_LOWPASS
),
577 DECL(AL_FILTER_HIGHPASS
),
578 DECL(AL_FILTER_BANDPASS
),
580 DECL(AL_LOWPASS_GAIN
),
581 DECL(AL_LOWPASS_GAINHF
),
583 DECL(AL_HIGHPASS_GAIN
),
584 DECL(AL_HIGHPASS_GAINLF
),
586 DECL(AL_BANDPASS_GAIN
),
587 DECL(AL_BANDPASS_GAINHF
),
588 DECL(AL_BANDPASS_GAINLF
),
590 DECL(AL_EFFECT_TYPE
),
591 DECL(AL_EFFECT_NULL
),
592 DECL(AL_EFFECT_REVERB
),
593 DECL(AL_EFFECT_EAXREVERB
),
594 DECL(AL_EFFECT_CHORUS
),
595 DECL(AL_EFFECT_DISTORTION
),
596 DECL(AL_EFFECT_ECHO
),
597 DECL(AL_EFFECT_FLANGER
),
599 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
600 DECL(AL_EFFECT_VOCAL_MORPHER
),
601 DECL(AL_EFFECT_PITCH_SHIFTER
),
603 DECL(AL_EFFECT_RING_MODULATOR
),
605 DECL(AL_EFFECT_AUTOWAH
),
607 DECL(AL_EFFECT_COMPRESSOR
),
608 DECL(AL_EFFECT_EQUALIZER
),
609 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
610 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
612 DECL(AL_EFFECTSLOT_EFFECT
),
613 DECL(AL_EFFECTSLOT_GAIN
),
614 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
615 DECL(AL_EFFECTSLOT_NULL
),
617 DECL(AL_EAXREVERB_DENSITY
),
618 DECL(AL_EAXREVERB_DIFFUSION
),
619 DECL(AL_EAXREVERB_GAIN
),
620 DECL(AL_EAXREVERB_GAINHF
),
621 DECL(AL_EAXREVERB_GAINLF
),
622 DECL(AL_EAXREVERB_DECAY_TIME
),
623 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
624 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
625 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
626 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
627 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
628 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
629 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
630 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
631 DECL(AL_EAXREVERB_ECHO_TIME
),
632 DECL(AL_EAXREVERB_ECHO_DEPTH
),
633 DECL(AL_EAXREVERB_MODULATION_TIME
),
634 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
635 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
636 DECL(AL_EAXREVERB_HFREFERENCE
),
637 DECL(AL_EAXREVERB_LFREFERENCE
),
638 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
639 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
641 DECL(AL_REVERB_DENSITY
),
642 DECL(AL_REVERB_DIFFUSION
),
643 DECL(AL_REVERB_GAIN
),
644 DECL(AL_REVERB_GAINHF
),
645 DECL(AL_REVERB_DECAY_TIME
),
646 DECL(AL_REVERB_DECAY_HFRATIO
),
647 DECL(AL_REVERB_REFLECTIONS_GAIN
),
648 DECL(AL_REVERB_REFLECTIONS_DELAY
),
649 DECL(AL_REVERB_LATE_REVERB_GAIN
),
650 DECL(AL_REVERB_LATE_REVERB_DELAY
),
651 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
652 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
653 DECL(AL_REVERB_DECAY_HFLIMIT
),
655 DECL(AL_CHORUS_WAVEFORM
),
656 DECL(AL_CHORUS_PHASE
),
657 DECL(AL_CHORUS_RATE
),
658 DECL(AL_CHORUS_DEPTH
),
659 DECL(AL_CHORUS_FEEDBACK
),
660 DECL(AL_CHORUS_DELAY
),
662 DECL(AL_DISTORTION_EDGE
),
663 DECL(AL_DISTORTION_GAIN
),
664 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
665 DECL(AL_DISTORTION_EQCENTER
),
666 DECL(AL_DISTORTION_EQBANDWIDTH
),
669 DECL(AL_ECHO_LRDELAY
),
670 DECL(AL_ECHO_DAMPING
),
671 DECL(AL_ECHO_FEEDBACK
),
672 DECL(AL_ECHO_SPREAD
),
674 DECL(AL_FLANGER_WAVEFORM
),
675 DECL(AL_FLANGER_PHASE
),
676 DECL(AL_FLANGER_RATE
),
677 DECL(AL_FLANGER_DEPTH
),
678 DECL(AL_FLANGER_FEEDBACK
),
679 DECL(AL_FLANGER_DELAY
),
681 DECL(AL_RING_MODULATOR_FREQUENCY
),
682 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
683 DECL(AL_RING_MODULATOR_WAVEFORM
),
685 DECL(AL_COMPRESSOR_ONOFF
),
687 DECL(AL_EQUALIZER_LOW_GAIN
),
688 DECL(AL_EQUALIZER_LOW_CUTOFF
),
689 DECL(AL_EQUALIZER_MID1_GAIN
),
690 DECL(AL_EQUALIZER_MID1_CENTER
),
691 DECL(AL_EQUALIZER_MID1_WIDTH
),
692 DECL(AL_EQUALIZER_MID2_GAIN
),
693 DECL(AL_EQUALIZER_MID2_CENTER
),
694 DECL(AL_EQUALIZER_MID2_WIDTH
),
695 DECL(AL_EQUALIZER_HIGH_GAIN
),
696 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
698 DECL(AL_DEDICATED_GAIN
),
700 DECL(AL_NUM_RESAMPLERS_SOFT
),
701 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
702 DECL(AL_SOURCE_RESAMPLER_SOFT
),
703 DECL(AL_RESAMPLER_NAME_SOFT
),
705 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
710 static const ALCchar alcNoError
[] = "No Error";
711 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
712 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
713 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
714 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
715 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
718 /************************************************
720 ************************************************/
722 /* Enumerated device names */
723 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
725 static al_string alcAllDevicesList
;
726 static al_string alcCaptureDeviceList
;
728 /* Default is always the first in the list */
729 static ALCchar
*alcDefaultAllDevicesSpecifier
;
730 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
732 /* Default context extensions */
733 static const ALchar alExtList
[] =
734 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
735 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
736 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
737 "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES "
738 "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates "
739 "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points "
740 "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length "
741 "AL_SOFT_source_resampler AL_SOFTX_source_spatialize";
743 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
745 /* Thread-local current context */
746 static altss_t LocalContext
;
747 /* Process-wide current context */
748 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
750 /* Mixing thread piority level */
755 enum LogLevel LogLevel
= LogWarning
;
757 enum LogLevel LogLevel
= LogError
;
760 /* Flag to trap ALC device errors */
761 static ALCboolean TrapALCError
= ALC_FALSE
;
763 /* One-time configuration init control */
764 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
766 /* Default effect that applies to sources that don't have an effect on send 0 */
767 static ALeffect DefaultEffect
;
769 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
772 static ALCboolean SuspendDefers
= ALC_TRUE
;
775 /************************************************
777 ************************************************/
778 static const ALCchar alcNoDeviceExtList
[] =
779 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
780 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
781 static const ALCchar alcExtensionList
[] =
782 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
783 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
784 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF "
785 "ALC_SOFT_loopback ALC_SOFTX_output_limiter ALC_SOFT_pause_device";
786 static const ALCint alcMajorVersion
= 1;
787 static const ALCint alcMinorVersion
= 1;
789 static const ALCint alcEFXMajorVersion
= 1;
790 static const ALCint alcEFXMinorVersion
= 0;
793 /************************************************
795 ************************************************/
796 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
798 static almtx_t ListLock
;
799 static inline void LockLists(void)
801 int ret
= almtx_lock(&ListLock
);
802 assert(ret
== althrd_success
);
804 static inline void UnlockLists(void)
806 int ret
= almtx_unlock(&ListLock
);
807 assert(ret
== althrd_success
);
810 /************************************************
811 * Library initialization
812 ************************************************/
814 static void alc_init(void);
815 static void alc_deinit(void);
816 static void alc_deinit_safe(void);
818 #ifndef AL_LIBTYPE_STATIC
819 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
823 case DLL_PROCESS_ATTACH
:
824 /* Pin the DLL so we won't get unloaded until the process terminates */
825 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
826 (WCHAR
*)hModule
, &hModule
);
830 case DLL_THREAD_DETACH
:
833 case DLL_PROCESS_DETACH
:
842 #elif defined(_MSC_VER)
843 #pragma section(".CRT$XCU",read)
844 static void alc_constructor(void);
845 static void alc_destructor(void);
846 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
848 static void alc_constructor(void)
850 atexit(alc_destructor
);
854 static void alc_destructor(void)
858 #elif defined(HAVE_GCC_DESTRUCTOR)
859 static void alc_init(void) __attribute__((constructor
));
860 static void alc_deinit(void) __attribute__((destructor
));
862 #error "No static initialization available on this platform!"
865 #elif defined(HAVE_GCC_DESTRUCTOR)
867 static void alc_init(void) __attribute__((constructor
));
868 static void alc_deinit(void) __attribute__((destructor
));
871 #error "No global initialization available on this platform!"
874 static void ReleaseThreadCtx(void *ptr
);
875 static void alc_init(void)
882 AL_STRING_INIT(alcAllDevicesList
);
883 AL_STRING_INIT(alcCaptureDeviceList
);
885 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
886 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
889 str
= getenv("__ALSOFT_REVERSE_Z");
890 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
893 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
894 assert(ret
== althrd_success
);
896 ret
= almtx_init(&ListLock
, almtx_recursive
);
897 assert(ret
== althrd_success
);
902 static void alc_initconfig(void)
904 const char *devs
, *str
;
909 str
= getenv("ALSOFT_LOGLEVEL");
912 long lvl
= strtol(str
, NULL
, 0);
913 if(lvl
>= NoLog
&& lvl
<= LogRef
)
917 str
= getenv("ALSOFT_LOGFILE");
920 FILE *logfile
= al_fopen(str
, "wt");
921 if(logfile
) LogFile
= logfile
;
922 else ERR("Failed to open log file '%s'\n", str
);
925 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
926 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
931 if(BackendListSize
> 0)
932 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
933 for(i
= 1;i
< BackendListSize
;i
++)
934 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
935 TRACE("Supported backends: %s\n", buf
);
939 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
942 if(strcasecmp(str
, "ignore") == 0)
944 SuspendDefers
= ALC_FALSE
;
945 TRACE("Selected context suspend behavior, \"ignore\"\n");
948 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
952 #if defined(HAVE_SSE4_1)
953 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
954 #elif defined(HAVE_SSE3)
955 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
956 #elif defined(HAVE_SSE2)
957 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
958 #elif defined(HAVE_SSE)
959 capfilter
|= CPU_CAP_SSE
;
962 capfilter
|= CPU_CAP_NEON
;
964 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
966 if(strcasecmp(str
, "all") == 0)
971 const char *next
= str
;
975 while(isspace(str
[0]))
977 next
= strchr(str
, ',');
979 if(!str
[0] || str
[0] == ',')
982 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
983 while(len
> 0 && isspace(str
[len
-1]))
985 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
986 capfilter
&= ~CPU_CAP_SSE
;
987 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
988 capfilter
&= ~CPU_CAP_SSE2
;
989 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
990 capfilter
&= ~CPU_CAP_SSE3
;
991 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
992 capfilter
&= ~CPU_CAP_SSE4_1
;
993 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
994 capfilter
&= ~CPU_CAP_NEON
;
996 WARN("Invalid CPU extension \"%s\"\n", str
);
1000 FillCPUCaps(capfilter
);
1007 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
1011 str
= getenv("ALSOFT_TRAP_ERROR");
1012 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1014 TrapALError
= AL_TRUE
;
1015 TrapALCError
= AL_TRUE
;
1019 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1020 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1021 TrapALError
= AL_TRUE
;
1022 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
1024 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1025 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1026 TrapALCError
= ALC_TRUE
;
1027 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
1030 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1031 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1033 EmulateEAXReverb
= GetConfigValueBool(NULL
, "reverb", "emulate-eax", AL_FALSE
);
1035 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1036 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1040 const char *next
= devs
;
1041 int endlist
, delitem
;
1046 while(isspace(devs
[0]))
1048 next
= strchr(devs
, ',');
1050 delitem
= (devs
[0] == '-');
1051 if(devs
[0] == '-') devs
++;
1053 if(!devs
[0] || devs
[0] == ',')
1060 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1061 while(len
> 0 && isspace(devs
[len
-1]))
1063 for(n
= i
;n
< BackendListSize
;n
++)
1065 if(len
== strlen(BackendList
[n
].name
) &&
1066 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1070 for(;n
+1 < BackendListSize
;n
++)
1071 BackendList
[n
] = BackendList
[n
+1];
1076 struct BackendInfo Bkp
= BackendList
[n
];
1078 BackendList
[n
] = BackendList
[n
-1];
1079 BackendList
[n
] = Bkp
;
1089 BackendListSize
= i
;
1092 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1094 if(BackendList
[i
].getFactory
)
1096 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1097 if(!V0(factory
,init
)())
1099 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1103 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1104 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1106 PlaybackBackend
= BackendList
[i
];
1107 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1109 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1111 CaptureBackend
= BackendList
[i
];
1112 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1118 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1120 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1124 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1125 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1127 PlaybackBackend
= BackendList
[i
];
1128 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1130 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1132 CaptureBackend
= BackendList
[i
];
1133 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1137 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1141 if(!PlaybackBackend
.name
)
1142 WARN("No playback backend available!\n");
1143 if(!CaptureBackend
.name
)
1144 WARN("No capture backend available!\n");
1146 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1149 const char *next
= str
;
1153 next
= strchr(str
, ',');
1155 if(!str
[0] || next
== str
)
1158 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1159 for(n
= 0;EffectList
[n
].name
;n
++)
1161 if(len
== strlen(EffectList
[n
].name
) &&
1162 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1163 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1168 InitEffectFactoryMap();
1170 InitEffect(&DefaultEffect
);
1171 str
= getenv("ALSOFT_DEFAULT_REVERB");
1172 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1173 LoadReverbPreset(str
, &DefaultEffect
);
1175 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1180 static JavaVM
*gJavaVM
;
1181 static pthread_key_t gJVMThreadKey
;
1183 static void CleanupJNIEnv(void* UNUSED(ptr
))
1185 JCALL0(gJavaVM
,DetachCurrentThread
)();
1188 void *Android_GetJNIEnv(void)
1192 WARN("gJavaVM is NULL!\n");
1196 /* http://developer.android.com/guide/practices/jni.html
1198 * All threads are Linux threads, scheduled by the kernel. They're usually
1199 * started from managed code (using Thread.start), but they can also be
1200 * created elsewhere and then attached to the JavaVM. For example, a thread
1201 * started with pthread_create can be attached with the JNI
1202 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1203 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1204 * Attaching a natively-created thread causes a java.lang.Thread object to
1205 * be constructed and added to the "main" ThreadGroup, making it visible to
1206 * the debugger. Calling AttachCurrentThread on an already-attached thread
1209 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1212 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1215 ERR("Failed to attach current thread\n");
1218 pthread_setspecific(gJVMThreadKey
, env
);
1223 /* Automatically called by JNI. */
1224 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1230 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1232 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1236 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1237 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1239 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1240 ERR("pthread_key_create failed: %d\n", err
);
1241 pthread_setspecific(gJVMThreadKey
, env
);
1242 return JNI_VERSION_1_4
;
1248 /************************************************
1249 * Library deinitialization
1250 ************************************************/
1251 static void alc_cleanup(void)
1255 AL_STRING_DEINIT(alcAllDevicesList
);
1256 AL_STRING_DEINIT(alcCaptureDeviceList
);
1258 free(alcDefaultAllDevicesSpecifier
);
1259 alcDefaultAllDevicesSpecifier
= NULL
;
1260 free(alcCaptureDefaultDeviceSpecifier
);
1261 alcCaptureDefaultDeviceSpecifier
= NULL
;
1263 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1268 } while((dev
=dev
->next
) != NULL
);
1269 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1272 DeinitEffectFactoryMap();
1275 static void alc_deinit_safe(void)
1283 almtx_destroy(&ListLock
);
1284 altss_delete(LocalContext
);
1286 if(LogFile
!= stderr
)
1291 static void alc_deinit(void)
1297 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1298 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1300 for(i
= 0;i
< BackendListSize
;i
++)
1302 if(!BackendList
[i
].getFactory
)
1303 BackendList
[i
].Deinit();
1306 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1307 V0(factory
,deinit
)();
1311 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1312 V0(factory
,deinit
)();
1319 /************************************************
1320 * Device enumeration
1321 ************************************************/
1322 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1329 if(backendinfo
->Probe
)
1330 backendinfo
->Probe(type
);
1331 else if(backendinfo
->getFactory
)
1333 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1334 V(factory
,probe
)(type
);
1338 static void ProbeAllDevicesList(void)
1339 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1340 static void ProbeCaptureDeviceList(void)
1341 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1343 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1345 size_t len
= strlen(name
);
1347 alstr_append_range(devnames
, name
, name
+len
+1);
1349 void AppendAllDevicesList(const ALCchar
*name
)
1350 { AppendDevice(name
, &alcAllDevicesList
); }
1351 void AppendCaptureDeviceList(const ALCchar
*name
)
1352 { AppendDevice(name
, &alcCaptureDeviceList
); }
1355 /************************************************
1356 * Device format information
1357 ************************************************/
1358 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1362 case DevFmtByte
: return "Signed Byte";
1363 case DevFmtUByte
: return "Unsigned Byte";
1364 case DevFmtShort
: return "Signed Short";
1365 case DevFmtUShort
: return "Unsigned Short";
1366 case DevFmtInt
: return "Signed Int";
1367 case DevFmtUInt
: return "Unsigned Int";
1368 case DevFmtFloat
: return "Float";
1370 return "(unknown type)";
1372 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1376 case DevFmtMono
: return "Mono";
1377 case DevFmtStereo
: return "Stereo";
1378 case DevFmtQuad
: return "Quadraphonic";
1379 case DevFmtX51
: return "5.1 Surround";
1380 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1381 case DevFmtX61
: return "6.1 Surround";
1382 case DevFmtX71
: return "7.1 Surround";
1383 case DevFmtAmbi3D
: return "Ambisonic 3D";
1385 return "(unknown channels)";
1388 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1389 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1393 case DevFmtByte
: return sizeof(ALbyte
);
1394 case DevFmtUByte
: return sizeof(ALubyte
);
1395 case DevFmtShort
: return sizeof(ALshort
);
1396 case DevFmtUShort
: return sizeof(ALushort
);
1397 case DevFmtInt
: return sizeof(ALint
);
1398 case DevFmtUInt
: return sizeof(ALuint
);
1399 case DevFmtFloat
: return sizeof(ALfloat
);
1403 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1407 case DevFmtMono
: return 1;
1408 case DevFmtStereo
: return 2;
1409 case DevFmtQuad
: return 4;
1410 case DevFmtX51
: return 6;
1411 case DevFmtX51Rear
: return 6;
1412 case DevFmtX61
: return 7;
1413 case DevFmtX71
: return 8;
1414 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1415 (ambiorder
== 2) ? 9 :
1416 (ambiorder
== 1) ? 4 : 1;
1421 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1422 enum DevFmtType
*type
)
1424 static const struct {
1426 enum DevFmtChannels channels
;
1427 enum DevFmtType type
;
1429 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1430 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1431 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1433 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1434 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1435 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1437 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1438 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1439 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1441 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1442 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1443 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1445 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1446 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1447 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1449 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1450 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1451 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1455 for(i
= 0;i
< COUNTOF(list
);i
++)
1457 if(list
[i
].format
== format
)
1459 *chans
= list
[i
].channels
;
1460 *type
= list
[i
].type
;
1468 static ALCboolean
IsValidALCType(ALCenum type
)
1473 case ALC_UNSIGNED_BYTE_SOFT
:
1474 case ALC_SHORT_SOFT
:
1475 case ALC_UNSIGNED_SHORT_SOFT
:
1477 case ALC_UNSIGNED_INT_SOFT
:
1478 case ALC_FLOAT_SOFT
:
1484 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1489 case ALC_STEREO_SOFT
:
1491 case ALC_5POINT1_SOFT
:
1492 case ALC_6POINT1_SOFT
:
1493 case ALC_7POINT1_SOFT
:
1494 case ALC_BFORMAT3D_SOFT
:
1500 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1511 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1523 /************************************************
1524 * Miscellaneous ALC helpers
1525 ************************************************/
1527 void ALCdevice_Lock(ALCdevice
*device
)
1529 V0(device
->Backend
,lock
)();
1532 void ALCdevice_Unlock(ALCdevice
*device
)
1534 V0(device
->Backend
,unlock
)();
1538 /* SetDefaultWFXChannelOrder
1540 * Sets the default channel order used by WaveFormatEx.
1542 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1546 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1547 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1549 switch(device
->FmtChans
)
1552 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1555 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1556 device
->RealOut
.ChannelName
[1] = FrontRight
;
1559 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1560 device
->RealOut
.ChannelName
[1] = FrontRight
;
1561 device
->RealOut
.ChannelName
[2] = BackLeft
;
1562 device
->RealOut
.ChannelName
[3] = BackRight
;
1565 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1566 device
->RealOut
.ChannelName
[1] = FrontRight
;
1567 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1568 device
->RealOut
.ChannelName
[3] = LFE
;
1569 device
->RealOut
.ChannelName
[4] = SideLeft
;
1570 device
->RealOut
.ChannelName
[5] = SideRight
;
1573 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1574 device
->RealOut
.ChannelName
[1] = FrontRight
;
1575 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1576 device
->RealOut
.ChannelName
[3] = LFE
;
1577 device
->RealOut
.ChannelName
[4] = BackLeft
;
1578 device
->RealOut
.ChannelName
[5] = BackRight
;
1581 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1582 device
->RealOut
.ChannelName
[1] = FrontRight
;
1583 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1584 device
->RealOut
.ChannelName
[3] = LFE
;
1585 device
->RealOut
.ChannelName
[4] = BackCenter
;
1586 device
->RealOut
.ChannelName
[5] = SideLeft
;
1587 device
->RealOut
.ChannelName
[6] = SideRight
;
1590 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1591 device
->RealOut
.ChannelName
[1] = FrontRight
;
1592 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1593 device
->RealOut
.ChannelName
[3] = LFE
;
1594 device
->RealOut
.ChannelName
[4] = BackLeft
;
1595 device
->RealOut
.ChannelName
[5] = BackRight
;
1596 device
->RealOut
.ChannelName
[6] = SideLeft
;
1597 device
->RealOut
.ChannelName
[7] = SideRight
;
1600 device
->RealOut
.ChannelName
[0] = Aux0
;
1601 if(device
->AmbiOrder
> 0)
1603 device
->RealOut
.ChannelName
[1] = Aux1
;
1604 device
->RealOut
.ChannelName
[2] = Aux2
;
1605 device
->RealOut
.ChannelName
[3] = Aux3
;
1607 if(device
->AmbiOrder
> 1)
1609 device
->RealOut
.ChannelName
[4] = Aux4
;
1610 device
->RealOut
.ChannelName
[5] = Aux5
;
1611 device
->RealOut
.ChannelName
[6] = Aux6
;
1612 device
->RealOut
.ChannelName
[7] = Aux7
;
1613 device
->RealOut
.ChannelName
[8] = Aux8
;
1615 if(device
->AmbiOrder
> 2)
1617 device
->RealOut
.ChannelName
[9] = Aux9
;
1618 device
->RealOut
.ChannelName
[10] = Aux10
;
1619 device
->RealOut
.ChannelName
[11] = Aux11
;
1620 device
->RealOut
.ChannelName
[12] = Aux12
;
1621 device
->RealOut
.ChannelName
[13] = Aux13
;
1622 device
->RealOut
.ChannelName
[14] = Aux14
;
1623 device
->RealOut
.ChannelName
[15] = Aux15
;
1629 /* SetDefaultChannelOrder
1631 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1633 void SetDefaultChannelOrder(ALCdevice
*device
)
1637 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1638 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1640 switch(device
->FmtChans
)
1643 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1644 device
->RealOut
.ChannelName
[1] = FrontRight
;
1645 device
->RealOut
.ChannelName
[2] = BackLeft
;
1646 device
->RealOut
.ChannelName
[3] = BackRight
;
1647 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1648 device
->RealOut
.ChannelName
[5] = LFE
;
1651 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1652 device
->RealOut
.ChannelName
[1] = FrontRight
;
1653 device
->RealOut
.ChannelName
[2] = BackLeft
;
1654 device
->RealOut
.ChannelName
[3] = BackRight
;
1655 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1656 device
->RealOut
.ChannelName
[5] = LFE
;
1657 device
->RealOut
.ChannelName
[6] = SideLeft
;
1658 device
->RealOut
.ChannelName
[7] = SideRight
;
1661 /* Same as WFX order */
1668 SetDefaultWFXChannelOrder(device
);
1673 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1676 /* ALCcontext_DeferUpdates
1678 * Defers/suspends updates for the given context's listener and sources. This
1679 * does *NOT* stop mixing, but rather prevents certain property changes from
1682 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1684 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1687 /* ALCcontext_ProcessUpdates
1689 * Resumes update processing after being deferred.
1691 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1693 ReadLock(&context
->PropLock
);
1694 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1696 /* Tell the mixer to stop applying updates, then wait for any active
1697 * updating to finish, before providing updates.
1699 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1700 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1703 UpdateListenerProps(context
);
1704 UpdateAllEffectSlotProps(context
);
1705 UpdateAllSourceProps(context
);
1707 /* Now with all updates declared, let the mixer continue applying them
1708 * so they all happen at once.
1710 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1712 ReadUnlock(&context
->PropLock
);
1718 * Stores the latest ALC device error
1720 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1722 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1726 /* DebugBreak() will cause an exception if there is no debugger */
1727 if(IsDebuggerPresent())
1729 #elif defined(SIGTRAP)
1735 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1737 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1743 * Updates the device's base clock time with however many samples have been
1744 * done. This is used so frequency changes on the device don't cause the time
1745 * to jump forward or back. Must not be called while the device is running/
1748 static inline void UpdateClockBase(ALCdevice
*device
)
1750 IncrementRef(&device
->MixCount
);
1751 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1752 device
->SamplesDone
= 0;
1753 IncrementRef(&device
->MixCount
);
1756 /* UpdateDeviceParams
1758 * Updates device parameters according to the attribute list (caller is
1759 * responsible for holding the list lock).
1761 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1763 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1764 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1765 ALCenum gainLimiter
= !!device
->Limiter
;
1766 const ALsizei old_sends
= device
->NumAuxSends
;
1767 ALsizei new_sends
= device
->NumAuxSends
;
1768 enum DevFmtChannels oldChans
;
1769 enum DevFmtType oldType
;
1770 ALboolean update_failed
;
1771 ALCsizei hrtf_id
= -1;
1772 ALCcontext
*context
;
1779 // Check for attributes
1780 if(device
->Type
== Loopback
)
1782 ALCsizei numMono
, numStereo
, numSends
;
1783 ALCenum alayout
= AL_NONE
;
1784 ALCenum ascale
= AL_NONE
;
1785 ALCenum schans
= AL_NONE
;
1786 ALCenum stype
= AL_NONE
;
1787 ALCsizei attrIdx
= 0;
1788 ALCsizei aorder
= 0;
1793 WARN("Missing attributes for loopback device\n");
1794 return ALC_INVALID_VALUE
;
1797 numMono
= device
->NumMonoSources
;
1798 numStereo
= device
->NumStereoSources
;
1799 numSends
= old_sends
;
1801 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1802 while(attrList
[attrIdx
])
1804 switch(attrList
[attrIdx
])
1806 case ALC_FORMAT_CHANNELS_SOFT
:
1807 schans
= attrList
[attrIdx
+ 1];
1808 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1809 if(!IsValidALCChannels(schans
))
1810 return ALC_INVALID_VALUE
;
1813 case ALC_FORMAT_TYPE_SOFT
:
1814 stype
= attrList
[attrIdx
+ 1];
1815 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1816 if(!IsValidALCType(stype
))
1817 return ALC_INVALID_VALUE
;
1821 freq
= attrList
[attrIdx
+ 1];
1822 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1823 if(freq
< MIN_OUTPUT_RATE
)
1824 return ALC_INVALID_VALUE
;
1827 case ALC_AMBISONIC_LAYOUT_SOFT
:
1828 alayout
= attrList
[attrIdx
+ 1];
1829 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1830 if(!IsValidAmbiLayout(alayout
))
1831 return ALC_INVALID_VALUE
;
1834 case ALC_AMBISONIC_SCALING_SOFT
:
1835 ascale
= attrList
[attrIdx
+ 1];
1836 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1837 if(!IsValidAmbiScaling(ascale
))
1838 return ALC_INVALID_VALUE
;
1841 case ALC_AMBISONIC_ORDER_SOFT
:
1842 aorder
= attrList
[attrIdx
+ 1];
1843 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1844 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1845 return ALC_INVALID_VALUE
;
1848 case ALC_MONO_SOURCES
:
1849 numMono
= attrList
[attrIdx
+ 1];
1850 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1851 numMono
= maxi(numMono
, 0);
1854 case ALC_STEREO_SOURCES
:
1855 numStereo
= attrList
[attrIdx
+ 1];
1856 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1857 numStereo
= maxi(numStereo
, 0);
1860 case ALC_MAX_AUXILIARY_SENDS
:
1861 numSends
= attrList
[attrIdx
+ 1];
1862 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1863 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1867 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1868 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1869 hrtf_appreq
= Hrtf_Disable
;
1870 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1871 hrtf_appreq
= Hrtf_Enable
;
1873 hrtf_appreq
= Hrtf_Default
;
1876 case ALC_HRTF_ID_SOFT
:
1877 hrtf_id
= attrList
[attrIdx
+ 1];
1878 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1881 case ALC_OUTPUT_LIMITER_SOFT
:
1882 gainLimiter
= attrList
[attrIdx
+ 1];
1883 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1887 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1888 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1896 if(!schans
|| !stype
|| !freq
)
1898 WARN("Missing format for loopback device\n");
1899 return ALC_INVALID_VALUE
;
1901 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1903 WARN("Missing ambisonic info for loopback device\n");
1904 return ALC_INVALID_VALUE
;
1907 if((device
->Flags
&DEVICE_RUNNING
))
1908 V0(device
->Backend
,stop
)();
1909 device
->Flags
&= ~DEVICE_RUNNING
;
1911 UpdateClockBase(device
);
1913 device
->Frequency
= freq
;
1914 device
->FmtChans
= schans
;
1915 device
->FmtType
= stype
;
1916 if(schans
== ALC_BFORMAT3D_SOFT
)
1918 device
->AmbiOrder
= aorder
;
1919 device
->AmbiLayout
= alayout
;
1920 device
->AmbiScale
= ascale
;
1923 if(numMono
> INT_MAX
-numStereo
)
1924 numMono
= INT_MAX
-numStereo
;
1925 numMono
+= numStereo
;
1926 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1932 numMono
= maxi(numMono
, 256);
1933 numStereo
= mini(numStereo
, numMono
);
1934 numMono
-= numStereo
;
1935 device
->SourcesMax
= numMono
+ numStereo
;
1937 device
->NumMonoSources
= numMono
;
1938 device
->NumStereoSources
= numStereo
;
1940 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1941 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1943 new_sends
= numSends
;
1945 else if(attrList
&& attrList
[0])
1947 ALCsizei numMono
, numStereo
, numSends
;
1948 ALCsizei attrIdx
= 0;
1951 /* If a context is already running on the device, stop playback so the
1952 * device attributes can be updated. */
1953 if((device
->Flags
&DEVICE_RUNNING
))
1954 V0(device
->Backend
,stop
)();
1955 device
->Flags
&= ~DEVICE_RUNNING
;
1957 UpdateClockBase(device
);
1959 freq
= device
->Frequency
;
1960 numMono
= device
->NumMonoSources
;
1961 numStereo
= device
->NumStereoSources
;
1962 numSends
= old_sends
;
1964 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1965 while(attrList
[attrIdx
])
1967 switch(attrList
[attrIdx
])
1970 freq
= attrList
[attrIdx
+ 1];
1971 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1972 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1975 case ALC_MONO_SOURCES
:
1976 numMono
= attrList
[attrIdx
+ 1];
1977 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1978 numMono
= maxi(numMono
, 0);
1981 case ALC_STEREO_SOURCES
:
1982 numStereo
= attrList
[attrIdx
+ 1];
1983 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1984 numStereo
= maxi(numStereo
, 0);
1987 case ALC_MAX_AUXILIARY_SENDS
:
1988 numSends
= attrList
[attrIdx
+ 1];
1989 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1990 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1994 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1995 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1996 hrtf_appreq
= Hrtf_Disable
;
1997 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1998 hrtf_appreq
= Hrtf_Enable
;
2000 hrtf_appreq
= Hrtf_Default
;
2003 case ALC_HRTF_ID_SOFT
:
2004 hrtf_id
= attrList
[attrIdx
+ 1];
2005 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
2008 case ALC_OUTPUT_LIMITER_SOFT
:
2009 gainLimiter
= attrList
[attrIdx
+ 1];
2010 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
2014 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
2015 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
2023 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
2024 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
2026 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
2028 /* SSE and Neon do best with the update size being a multiple of 4 */
2029 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
2030 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
2032 device
->Frequency
= freq
;
2034 if(numMono
> INT_MAX
-numStereo
)
2035 numMono
= INT_MAX
-numStereo
;
2036 numMono
+= numStereo
;
2037 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
2043 numMono
= maxi(numMono
, 256);
2044 numStereo
= mini(numStereo
, numMono
);
2045 numMono
-= numStereo
;
2046 device
->SourcesMax
= numMono
+ numStereo
;
2048 device
->NumMonoSources
= numMono
;
2049 device
->NumStereoSources
= numStereo
;
2051 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
2052 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
2054 new_sends
= numSends
;
2057 if((device
->Flags
&DEVICE_RUNNING
))
2058 return ALC_NO_ERROR
;
2060 al_free(device
->Uhj_Encoder
);
2061 device
->Uhj_Encoder
= NULL
;
2063 al_free(device
->Bs2b
);
2064 device
->Bs2b
= NULL
;
2066 al_free(device
->ChannelDelay
[0].Buffer
);
2067 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2069 device
->ChannelDelay
[i
].Length
= 0;
2070 device
->ChannelDelay
[i
].Buffer
= NULL
;
2073 al_free(device
->Dry
.Buffer
);
2074 device
->Dry
.Buffer
= NULL
;
2075 device
->Dry
.NumChannels
= 0;
2076 device
->FOAOut
.Buffer
= NULL
;
2077 device
->FOAOut
.NumChannels
= 0;
2078 device
->RealOut
.Buffer
= NULL
;
2079 device
->RealOut
.NumChannels
= 0;
2081 UpdateClockBase(device
);
2083 /*************************************************************************
2084 * Update device format request if HRTF is requested
2086 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2087 if(device
->Type
!= Loopback
)
2090 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2092 if(strcasecmp(hrtf
, "true") == 0)
2093 hrtf_userreq
= Hrtf_Enable
;
2094 else if(strcasecmp(hrtf
, "false") == 0)
2095 hrtf_userreq
= Hrtf_Disable
;
2096 else if(strcasecmp(hrtf
, "auto") != 0)
2097 ERR("Unexpected hrtf value: %s\n", hrtf
);
2100 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2102 struct Hrtf
*hrtf
= NULL
;
2103 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2105 VECTOR_DEINIT(device
->HrtfList
);
2106 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2108 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2110 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2111 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2113 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2118 device
->FmtChans
= DevFmtStereo
;
2119 device
->Frequency
= hrtf
->sampleRate
;
2120 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2121 if(device
->HrtfHandle
)
2122 Hrtf_DecRef(device
->HrtfHandle
);
2123 device
->HrtfHandle
= hrtf
;
2127 hrtf_userreq
= Hrtf_Default
;
2128 hrtf_appreq
= Hrtf_Disable
;
2129 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2134 oldFreq
= device
->Frequency
;
2135 oldChans
= device
->FmtChans
;
2136 oldType
= device
->FmtType
;
2138 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2139 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2140 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2141 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2142 device
->UpdateSize
, device
->NumUpdates
2145 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2146 return ALC_INVALID_DEVICE
;
2148 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2150 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2151 DevFmtChannelsString(device
->FmtChans
));
2152 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2154 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2156 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2157 DevFmtTypeString(device
->FmtType
));
2158 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2160 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2162 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2163 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2166 if((device
->UpdateSize
&3) != 0)
2168 if((CPUCapFlags
&CPU_CAP_SSE
))
2169 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2170 if((CPUCapFlags
&CPU_CAP_NEON
))
2171 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2174 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2175 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2176 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2179 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2180 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2181 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2183 /* Allocate extra channels for any post-filter output. */
2184 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2185 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2187 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2188 device
->Dry
.Buffer
= al_calloc(16, size
);
2189 if(!device
->Dry
.Buffer
)
2191 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2192 return ALC_INVALID_DEVICE
;
2195 if(device
->RealOut
.NumChannels
!= 0)
2196 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2197 device
->FOAOut
.NumChannels
;
2200 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2201 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2204 if(device
->FOAOut
.NumChannels
!= 0)
2205 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2208 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2209 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2212 device
->NumAuxSends
= new_sends
;
2213 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2214 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2215 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2217 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2221 if(!device
->Limiter
)
2222 device
->Limiter
= alloc_limiter();
2224 else if(device
->Limiter
)
2226 al_free(device
->Limiter
);
2227 device
->Limiter
= NULL
;
2230 /* Need to delay returning failure until replacement Send arrays have been
2231 * allocated with the appropriate size.
2233 update_failed
= AL_FALSE
;
2234 SetMixerFPUMode(&oldMode
);
2235 if(device
->DefaultSlot
)
2237 ALeffectslot
*slot
= device
->DefaultSlot
;
2238 ALeffectState
*state
= slot
->Effect
.State
;
2240 state
->OutBuffer
= device
->Dry
.Buffer
;
2241 state
->OutChannels
= device
->Dry
.NumChannels
;
2242 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2243 update_failed
= AL_TRUE
;
2245 UpdateEffectSlotProps(slot
);
2248 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2253 WriteLock(&context
->PropLock
);
2254 LockUIntMapRead(&context
->EffectSlotMap
);
2255 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2257 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2258 ALeffectState
*state
= slot
->Effect
.State
;
2260 state
->OutBuffer
= device
->Dry
.Buffer
;
2261 state
->OutChannels
= device
->Dry
.NumChannels
;
2262 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2263 update_failed
= AL_TRUE
;
2265 UpdateEffectSlotProps(slot
);
2267 UnlockUIntMapRead(&context
->EffectSlotMap
);
2269 LockUIntMapRead(&context
->SourceMap
);
2270 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2271 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2273 ALsource
*source
= context
->SourceMap
.values
[pos
];
2275 if(old_sends
!= device
->NumAuxSends
)
2277 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2280 memcpy(sends
, source
->Send
,
2281 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2283 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2285 if(source
->Send
[s
].Slot
)
2286 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2287 source
->Send
[s
].Slot
= NULL
;
2289 al_free(source
->Send
);
2290 source
->Send
= sends
;
2291 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2293 source
->Send
[s
].Slot
= NULL
;
2294 source
->Send
[s
].Gain
= 1.0f
;
2295 source
->Send
[s
].GainHF
= 1.0f
;
2296 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2297 source
->Send
[s
].GainLF
= 1.0f
;
2298 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2302 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2304 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2305 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2307 ALvoice
*voice
= context
->Voices
[pos
];
2308 struct ALvoiceProps
*props
;
2310 /* Clear any pre-existing voice property structs, in case the
2311 * number of auxiliary sends changed. Active sources will have
2312 * updates respecified in UpdateAllSourceProps.
2314 props
= ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_relaxed
);
2317 props
= ATOMIC_EXCHANGE_PTR(&voice
->FreeList
, NULL
, almemory_order_relaxed
);
2320 struct ALvoiceProps
*next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
2325 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2328 if(device
->AvgSpeakerDist
> 0.0f
)
2330 /* Reinitialize the NFC filters for new parameters. */
2331 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2332 (device
->AvgSpeakerDist
* device
->Frequency
);
2333 for(i
= 0;i
< voice
->NumChannels
;i
++)
2335 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2336 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2337 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2341 UnlockUIntMapRead(&context
->SourceMap
);
2343 UpdateListenerProps(context
);
2344 UpdateAllSourceProps(context
);
2345 WriteUnlock(&context
->PropLock
);
2347 context
= context
->next
;
2349 RestoreFPUMode(&oldMode
);
2351 return ALC_INVALID_DEVICE
;
2353 if(!(device
->Flags
&DEVICE_PAUSED
))
2355 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2356 return ALC_INVALID_DEVICE
;
2357 device
->Flags
|= DEVICE_RUNNING
;
2360 return ALC_NO_ERROR
;
2365 * Frees the device structure, and destroys any objects the app failed to
2366 * delete. Called once there's no more references on the device.
2368 static ALCvoid
FreeDevice(ALCdevice
*device
)
2372 TRACE("%p\n", device
);
2374 V0(device
->Backend
,close
)();
2375 DELETE_OBJ(device
->Backend
);
2376 device
->Backend
= NULL
;
2378 almtx_destroy(&device
->BackendLock
);
2380 if(device
->DefaultSlot
)
2382 DeinitEffectSlot(device
->DefaultSlot
);
2383 device
->DefaultSlot
= NULL
;
2386 if(device
->BufferMap
.size
> 0)
2388 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2389 (device
->BufferMap
.size
==1)?"":"s");
2390 ReleaseALBuffers(device
);
2392 ResetUIntMap(&device
->BufferMap
);
2394 if(device
->EffectMap
.size
> 0)
2396 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2397 (device
->EffectMap
.size
==1)?"":"s");
2398 ReleaseALEffects(device
);
2400 ResetUIntMap(&device
->EffectMap
);
2402 if(device
->FilterMap
.size
> 0)
2404 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2405 (device
->FilterMap
.size
==1)?"":"s");
2406 ReleaseALFilters(device
);
2408 ResetUIntMap(&device
->FilterMap
);
2410 AL_STRING_DEINIT(device
->HrtfName
);
2411 FreeHrtfList(&device
->HrtfList
);
2412 if(device
->HrtfHandle
)
2413 Hrtf_DecRef(device
->HrtfHandle
);
2414 device
->HrtfHandle
= NULL
;
2415 al_free(device
->Hrtf
);
2416 device
->Hrtf
= NULL
;
2418 al_free(device
->Bs2b
);
2419 device
->Bs2b
= NULL
;
2421 al_free(device
->Uhj_Encoder
);
2422 device
->Uhj_Encoder
= NULL
;
2424 bformatdec_free(device
->AmbiDecoder
);
2425 device
->AmbiDecoder
= NULL
;
2427 ambiup_free(device
->AmbiUp
);
2428 device
->AmbiUp
= NULL
;
2430 al_free(device
->Limiter
);
2431 device
->Limiter
= NULL
;
2433 al_free(device
->ChannelDelay
[0].Buffer
);
2434 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2436 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2437 device
->ChannelDelay
[i
].Length
= 0;
2438 device
->ChannelDelay
[i
].Buffer
= NULL
;
2441 AL_STRING_DEINIT(device
->DeviceName
);
2443 al_free(device
->Dry
.Buffer
);
2444 device
->Dry
.Buffer
= NULL
;
2445 device
->Dry
.NumChannels
= 0;
2446 device
->FOAOut
.Buffer
= NULL
;
2447 device
->FOAOut
.NumChannels
= 0;
2448 device
->RealOut
.Buffer
= NULL
;
2449 device
->RealOut
.NumChannels
= 0;
2455 void ALCdevice_IncRef(ALCdevice
*device
)
2458 ref
= IncrementRef(&device
->ref
);
2459 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2462 void ALCdevice_DecRef(ALCdevice
*device
)
2465 ref
= DecrementRef(&device
->ref
);
2466 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2467 if(ref
== 0) FreeDevice(device
);
2472 * Checks if the device handle is valid, and increments its ref count if so.
2474 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2476 ALCdevice
*tmpDevice
;
2479 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2482 if(tmpDevice
== *device
)
2484 ALCdevice_IncRef(tmpDevice
);
2488 tmpDevice
= tmpDevice
->next
;
2499 * Initializes context fields
2501 static ALvoid
InitContext(ALCcontext
*Context
)
2503 ALlistener
*listener
= Context
->Listener
;
2504 struct ALeffectslotArray
*auxslots
;
2506 //Initialise listener
2507 listener
->Gain
= 1.0f
;
2508 listener
->MetersPerUnit
= 1.0f
;
2509 listener
->Position
[0] = 0.0f
;
2510 listener
->Position
[1] = 0.0f
;
2511 listener
->Position
[2] = 0.0f
;
2512 listener
->Velocity
[0] = 0.0f
;
2513 listener
->Velocity
[1] = 0.0f
;
2514 listener
->Velocity
[2] = 0.0f
;
2515 listener
->Forward
[0] = 0.0f
;
2516 listener
->Forward
[1] = 0.0f
;
2517 listener
->Forward
[2] = -1.0f
;
2518 listener
->Up
[0] = 0.0f
;
2519 listener
->Up
[1] = 1.0f
;
2520 listener
->Up
[2] = 0.0f
;
2522 aluMatrixfSet(&listener
->Params
.Matrix
,
2523 1.0f
, 0.0f
, 0.0f
, 0.0f
,
2524 0.0f
, 1.0f
, 0.0f
, 0.0f
,
2525 0.0f
, 0.0f
, 1.0f
, 0.0f
,
2526 0.0f
, 0.0f
, 0.0f
, 1.0f
2528 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2529 listener
->Params
.Gain
= 1.0f
;
2530 listener
->Params
.MetersPerUnit
= 1.0f
;
2531 listener
->Params
.DopplerFactor
= 1.0f
;
2532 listener
->Params
.SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2534 ATOMIC_INIT(&listener
->Update
, NULL
);
2535 ATOMIC_INIT(&listener
->FreeList
, NULL
);
2538 InitRef(&Context
->UpdateCount
, 0);
2539 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2540 Context
->GainBoost
= 1.0f
;
2541 RWLockInit(&Context
->PropLock
);
2542 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2543 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2544 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2546 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2547 auxslots
->count
= 0;
2548 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2551 Context
->DistanceModel
= DefaultDistanceModel
;
2552 Context
->SourceDistanceModel
= AL_FALSE
;
2553 Context
->DopplerFactor
= 1.0f
;
2554 Context
->DopplerVelocity
= 1.0f
;
2555 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2556 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2558 Context
->ExtensionList
= alExtList
;
2564 * Cleans up the context, and destroys any remaining objects the app failed to
2565 * delete. Called once there's no more references on the context.
2567 static void FreeContext(ALCcontext
*context
)
2569 ALlistener
*listener
= context
->Listener
;
2570 struct ALeffectslotArray
*auxslots
;
2571 struct ALlistenerProps
*lprops
;
2575 TRACE("%p\n", context
);
2577 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2580 if(context
->SourceMap
.size
> 0)
2582 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2583 (context
->SourceMap
.size
==1)?"":"s");
2584 ReleaseALSources(context
);
2586 ResetUIntMap(&context
->SourceMap
);
2588 if(context
->EffectSlotMap
.size
> 0)
2590 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2591 (context
->EffectSlotMap
.size
==1)?"":"s");
2592 ReleaseALAuxiliaryEffectSlots(context
);
2594 ResetUIntMap(&context
->EffectSlotMap
);
2596 for(i
= 0;i
< context
->VoiceCount
;i
++)
2597 DeinitVoice(context
->Voices
[i
]);
2598 al_free(context
->Voices
);
2599 context
->Voices
= NULL
;
2600 context
->VoiceCount
= 0;
2601 context
->MaxVoices
= 0;
2603 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2605 TRACE("Freed unapplied listener update %p\n", lprops
);
2609 lprops
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
2612 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2617 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2619 ALCdevice_DecRef(context
->Device
);
2620 context
->Device
= NULL
;
2622 //Invalidate context
2623 memset(context
, 0, sizeof(ALCcontext
));
2629 * Removes the context reference from the given device and removes it from
2630 * being current on the running thread or globally. Returns true if other
2631 * contexts still exist on the device.
2633 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2635 ALCcontext
*origctx
, *newhead
;
2638 if(altss_get(LocalContext
) == context
)
2640 WARN("%p released while current on thread\n", context
);
2641 altss_set(LocalContext
, NULL
);
2642 ALCcontext_DecRef(context
);
2646 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2647 ALCcontext_DecRef(context
);
2649 ALCdevice_Lock(device
);
2651 newhead
= context
->next
;
2652 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2654 ALCcontext
*volatile*list
= &origctx
->next
;
2657 if(*list
== context
)
2659 *list
= (*list
)->next
;
2662 list
= &(*list
)->next
;
2667 ALCdevice_Unlock(device
);
2669 ALCcontext_DecRef(context
);
2673 void ALCcontext_IncRef(ALCcontext
*context
)
2675 uint ref
= IncrementRef(&context
->ref
);
2676 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2679 void ALCcontext_DecRef(ALCcontext
*context
)
2681 uint ref
= DecrementRef(&context
->ref
);
2682 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2683 if(ref
== 0) FreeContext(context
);
2686 static void ReleaseThreadCtx(void *ptr
)
2688 ALCcontext
*context
= ptr
;
2689 uint ref
= DecrementRef(&context
->ref
);
2690 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2691 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2696 * Checks that the given context is valid, and increments its reference count.
2698 static ALCboolean
VerifyContext(ALCcontext
**context
)
2703 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2706 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2711 ALCcontext_IncRef(ctx
);
2728 * Returns the currently active context for this thread, and adds a reference
2729 * without locking it.
2731 ALCcontext
*GetContextRef(void)
2733 ALCcontext
*context
;
2735 context
= altss_get(LocalContext
);
2737 ALCcontext_IncRef(context
);
2741 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2743 ALCcontext_IncRef(context
);
2751 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2753 ALCdevice
*device
= context
->Device
;
2754 ALsizei num_sends
= device
->NumAuxSends
;
2755 struct ALvoiceProps
*props
;
2756 size_t sizeof_props
;
2757 size_t sizeof_voice
;
2763 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2766 /* Allocate the voice pointers, voices, and the voices' stored source
2767 * property set (including the dynamically-sized Send[] array) in one
2770 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2771 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2772 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2774 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2775 /* The voice and property objects are stored interleaved since they're
2778 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2779 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2783 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2784 const ALsizei s_count
= mini(old_sends
, num_sends
);
2786 for(;v
< v_count
;v
++)
2788 ALvoice
*old_voice
= context
->Voices
[v
];
2791 /* Copy the old voice data and source property set to the new
2794 *voice
= *old_voice
;
2795 for(i
= 0;i
< s_count
;i
++)
2796 voice
->Send
[i
] = old_voice
->Send
[i
];
2797 *props
= *(old_voice
->Props
);
2798 for(i
= 0;i
< s_count
;i
++)
2799 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2801 /* Set this voice's property set pointer and voice reference. */
2802 voice
->Props
= props
;
2805 /* Increment pointers to the next storage space. */
2806 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2807 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2809 /* Deinit any left over voices that weren't copied over to the new
2810 * array. NOTE: If this does anything, v equals num_voices and
2811 * num_voices is less than VoiceCount, so the following loop won't do
2814 for(;v
< context
->VoiceCount
;v
++)
2815 DeinitVoice(context
->Voices
[v
]);
2817 /* Finish setting the voices' property set pointers and references. */
2818 for(;v
< num_voices
;v
++)
2820 ATOMIC_INIT(&voice
->Update
, NULL
);
2821 ATOMIC_INIT(&voice
->FreeList
, NULL
);
2823 voice
->Props
= props
;
2826 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2827 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2830 al_free(context
->Voices
);
2831 context
->Voices
= voices
;
2832 context
->MaxVoices
= num_voices
;
2833 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2837 /************************************************
2838 * Standard ALC functions
2839 ************************************************/
2843 * Return last ALC generated error code for the given device
2845 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2849 if(VerifyDevice(&device
))
2851 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2852 ALCdevice_DecRef(device
);
2855 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2861 /* alcSuspendContext
2863 * Suspends updates for the given context
2865 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2870 if(!VerifyContext(&context
))
2871 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2874 ALCcontext_DeferUpdates(context
);
2875 ALCcontext_DecRef(context
);
2879 /* alcProcessContext
2881 * Resumes processing updates for the given context
2883 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2888 if(!VerifyContext(&context
))
2889 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2892 ALCcontext_ProcessUpdates(context
);
2893 ALCcontext_DecRef(context
);
2900 * Returns information about the device, and error strings
2902 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2904 const ALCchar
*value
= NULL
;
2912 case ALC_INVALID_ENUM
:
2913 value
= alcErrInvalidEnum
;
2916 case ALC_INVALID_VALUE
:
2917 value
= alcErrInvalidValue
;
2920 case ALC_INVALID_DEVICE
:
2921 value
= alcErrInvalidDevice
;
2924 case ALC_INVALID_CONTEXT
:
2925 value
= alcErrInvalidContext
;
2928 case ALC_OUT_OF_MEMORY
:
2929 value
= alcErrOutOfMemory
;
2932 case ALC_DEVICE_SPECIFIER
:
2933 value
= alcDefaultName
;
2936 case ALC_ALL_DEVICES_SPECIFIER
:
2937 if(VerifyDevice(&Device
))
2939 value
= alstr_get_cstr(Device
->DeviceName
);
2940 ALCdevice_DecRef(Device
);
2944 ProbeAllDevicesList();
2945 value
= alstr_get_cstr(alcAllDevicesList
);
2949 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2950 if(VerifyDevice(&Device
))
2952 value
= alstr_get_cstr(Device
->DeviceName
);
2953 ALCdevice_DecRef(Device
);
2957 ProbeCaptureDeviceList();
2958 value
= alstr_get_cstr(alcCaptureDeviceList
);
2962 /* Default devices are always first in the list */
2963 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2964 value
= alcDefaultName
;
2967 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2968 if(alstr_empty(alcAllDevicesList
))
2969 ProbeAllDevicesList();
2971 VerifyDevice(&Device
);
2973 free(alcDefaultAllDevicesSpecifier
);
2974 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
2975 if(!alcDefaultAllDevicesSpecifier
)
2976 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2978 value
= alcDefaultAllDevicesSpecifier
;
2979 if(Device
) ALCdevice_DecRef(Device
);
2982 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2983 if(alstr_empty(alcCaptureDeviceList
))
2984 ProbeCaptureDeviceList();
2986 VerifyDevice(&Device
);
2988 free(alcCaptureDefaultDeviceSpecifier
);
2989 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
2990 if(!alcCaptureDefaultDeviceSpecifier
)
2991 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2993 value
= alcCaptureDefaultDeviceSpecifier
;
2994 if(Device
) ALCdevice_DecRef(Device
);
2997 case ALC_EXTENSIONS
:
2998 if(!VerifyDevice(&Device
))
2999 value
= alcNoDeviceExtList
;
3002 value
= alcExtensionList
;
3003 ALCdevice_DecRef(Device
);
3007 case ALC_HRTF_SPECIFIER_SOFT
:
3008 if(!VerifyDevice(&Device
))
3009 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3012 almtx_lock(&Device
->BackendLock
);
3013 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3014 almtx_unlock(&Device
->BackendLock
);
3015 ALCdevice_DecRef(Device
);
3020 VerifyDevice(&Device
);
3021 alcSetError(Device
, ALC_INVALID_ENUM
);
3022 if(Device
) ALCdevice_DecRef(Device
);
3030 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3032 if(device
->Type
== Loopback
&& device
->FmtChans
== DevFmtAmbi3D
)
3037 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3041 if(size
<= 0 || values
== NULL
)
3043 alcSetError(device
, ALC_INVALID_VALUE
);
3051 case ALC_MAJOR_VERSION
:
3052 values
[0] = alcMajorVersion
;
3054 case ALC_MINOR_VERSION
:
3055 values
[0] = alcMinorVersion
;
3058 case ALC_ATTRIBUTES_SIZE
:
3059 case ALC_ALL_ATTRIBUTES
:
3063 case ALC_MONO_SOURCES
:
3064 case ALC_STEREO_SOURCES
:
3065 case ALC_CAPTURE_SAMPLES
:
3066 case ALC_FORMAT_CHANNELS_SOFT
:
3067 case ALC_FORMAT_TYPE_SOFT
:
3068 case ALC_AMBISONIC_LAYOUT_SOFT
:
3069 case ALC_AMBISONIC_SCALING_SOFT
:
3070 case ALC_AMBISONIC_ORDER_SOFT
:
3071 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3075 alcSetError(NULL
, ALC_INVALID_ENUM
);
3081 if(device
->Type
== Capture
)
3085 case ALC_CAPTURE_SAMPLES
:
3086 almtx_lock(&device
->BackendLock
);
3087 values
[0] = V0(device
->Backend
,availableSamples
)();
3088 almtx_unlock(&device
->BackendLock
);
3092 values
[0] = device
->Connected
;
3096 alcSetError(device
, ALC_INVALID_ENUM
);
3105 case ALC_MAJOR_VERSION
:
3106 values
[0] = alcMajorVersion
;
3109 case ALC_MINOR_VERSION
:
3110 values
[0] = alcMinorVersion
;
3113 case ALC_EFX_MAJOR_VERSION
:
3114 values
[0] = alcEFXMajorVersion
;
3117 case ALC_EFX_MINOR_VERSION
:
3118 values
[0] = alcEFXMinorVersion
;
3121 case ALC_ATTRIBUTES_SIZE
:
3122 values
[0] = NumAttrsForDevice(device
);
3125 case ALC_ALL_ATTRIBUTES
:
3126 if(size
< NumAttrsForDevice(device
))
3128 alcSetError(device
, ALC_INVALID_VALUE
);
3133 almtx_lock(&device
->BackendLock
);
3134 values
[i
++] = ALC_FREQUENCY
;
3135 values
[i
++] = device
->Frequency
;
3137 if(device
->Type
!= Loopback
)
3139 values
[i
++] = ALC_REFRESH
;
3140 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3142 values
[i
++] = ALC_SYNC
;
3143 values
[i
++] = ALC_FALSE
;
3147 if(device
->FmtChans
== DevFmtAmbi3D
)
3149 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3150 values
[i
++] = device
->AmbiLayout
;
3152 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3153 values
[i
++] = device
->AmbiScale
;
3155 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3156 values
[i
++] = device
->AmbiOrder
;
3159 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3160 values
[i
++] = device
->FmtChans
;
3162 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3163 values
[i
++] = device
->FmtType
;
3166 values
[i
++] = ALC_MONO_SOURCES
;
3167 values
[i
++] = device
->NumMonoSources
;
3169 values
[i
++] = ALC_STEREO_SOURCES
;
3170 values
[i
++] = device
->NumStereoSources
;
3172 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3173 values
[i
++] = device
->NumAuxSends
;
3175 values
[i
++] = ALC_HRTF_SOFT
;
3176 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3178 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3179 values
[i
++] = device
->HrtfStatus
;
3181 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3182 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3183 almtx_unlock(&device
->BackendLock
);
3189 values
[0] = device
->Frequency
;
3193 if(device
->Type
== Loopback
)
3195 alcSetError(device
, ALC_INVALID_DEVICE
);
3198 almtx_lock(&device
->BackendLock
);
3199 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3200 almtx_unlock(&device
->BackendLock
);
3204 if(device
->Type
== Loopback
)
3206 alcSetError(device
, ALC_INVALID_DEVICE
);
3209 values
[0] = ALC_FALSE
;
3212 case ALC_FORMAT_CHANNELS_SOFT
:
3213 if(device
->Type
!= Loopback
)
3215 alcSetError(device
, ALC_INVALID_DEVICE
);
3218 values
[0] = device
->FmtChans
;
3221 case ALC_FORMAT_TYPE_SOFT
:
3222 if(device
->Type
!= Loopback
)
3224 alcSetError(device
, ALC_INVALID_DEVICE
);
3227 values
[0] = device
->FmtType
;
3230 case ALC_AMBISONIC_LAYOUT_SOFT
:
3231 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3233 alcSetError(device
, ALC_INVALID_DEVICE
);
3236 values
[0] = device
->AmbiLayout
;
3239 case ALC_AMBISONIC_SCALING_SOFT
:
3240 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3242 alcSetError(device
, ALC_INVALID_DEVICE
);
3245 values
[0] = device
->AmbiScale
;
3248 case ALC_AMBISONIC_ORDER_SOFT
:
3249 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3251 alcSetError(device
, ALC_INVALID_DEVICE
);
3254 values
[0] = device
->AmbiOrder
;
3257 case ALC_MONO_SOURCES
:
3258 values
[0] = device
->NumMonoSources
;
3261 case ALC_STEREO_SOURCES
:
3262 values
[0] = device
->NumStereoSources
;
3265 case ALC_MAX_AUXILIARY_SENDS
:
3266 values
[0] = device
->NumAuxSends
;
3270 values
[0] = device
->Connected
;
3274 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3277 case ALC_HRTF_STATUS_SOFT
:
3278 values
[0] = device
->HrtfStatus
;
3281 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3282 almtx_lock(&device
->BackendLock
);
3283 FreeHrtfList(&device
->HrtfList
);
3284 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3285 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3286 almtx_unlock(&device
->BackendLock
);
3289 case ALC_OUTPUT_LIMITER_SOFT
:
3290 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3294 alcSetError(device
, ALC_INVALID_ENUM
);
3302 * Returns information about the device and the version of OpenAL
3304 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3306 VerifyDevice(&device
);
3307 if(size
<= 0 || values
== NULL
)
3308 alcSetError(device
, ALC_INVALID_VALUE
);
3310 GetIntegerv(device
, param
, size
, values
);
3311 if(device
) ALCdevice_DecRef(device
);
3314 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3319 VerifyDevice(&device
);
3320 if(size
<= 0 || values
== NULL
)
3321 alcSetError(device
, ALC_INVALID_VALUE
);
3322 else if(!device
|| device
->Type
== Capture
)
3324 ivals
= malloc(size
* sizeof(ALCint
));
3325 size
= GetIntegerv(device
, pname
, size
, ivals
);
3326 for(i
= 0;i
< size
;i
++)
3327 values
[i
] = ivals
[i
];
3330 else /* render device */
3339 case ALC_ATTRIBUTES_SIZE
:
3340 *values
= NumAttrsForDevice(device
)+4;
3343 case ALC_ALL_ATTRIBUTES
:
3344 if(size
< NumAttrsForDevice(device
)+4)
3345 alcSetError(device
, ALC_INVALID_VALUE
);
3349 almtx_lock(&device
->BackendLock
);
3350 values
[i
++] = ALC_FREQUENCY
;
3351 values
[i
++] = device
->Frequency
;
3353 if(device
->Type
!= Loopback
)
3355 values
[i
++] = ALC_REFRESH
;
3356 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3358 values
[i
++] = ALC_SYNC
;
3359 values
[i
++] = ALC_FALSE
;
3363 if(device
->FmtChans
== DevFmtAmbi3D
)
3365 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3366 values
[i
++] = device
->AmbiLayout
;
3368 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3369 values
[i
++] = device
->AmbiScale
;
3371 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3372 values
[i
++] = device
->AmbiOrder
;
3375 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3376 values
[i
++] = device
->FmtChans
;
3378 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3379 values
[i
++] = device
->FmtType
;
3382 values
[i
++] = ALC_MONO_SOURCES
;
3383 values
[i
++] = device
->NumMonoSources
;
3385 values
[i
++] = ALC_STEREO_SOURCES
;
3386 values
[i
++] = device
->NumStereoSources
;
3388 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3389 values
[i
++] = device
->NumAuxSends
;
3391 values
[i
++] = ALC_HRTF_SOFT
;
3392 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3394 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3395 values
[i
++] = device
->HrtfStatus
;
3397 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3398 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3400 clock
= V0(device
->Backend
,getClockLatency
)();
3401 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3402 values
[i
++] = clock
.ClockTime
;
3404 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3405 values
[i
++] = clock
.Latency
;
3406 almtx_unlock(&device
->BackendLock
);
3412 case ALC_DEVICE_CLOCK_SOFT
:
3413 almtx_lock(&device
->BackendLock
);
3415 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3417 basecount
= device
->ClockBase
;
3418 samplecount
= device
->SamplesDone
;
3419 } while(refcount
!= ReadRef(&device
->MixCount
));
3420 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3421 almtx_unlock(&device
->BackendLock
);
3424 case ALC_DEVICE_LATENCY_SOFT
:
3425 almtx_lock(&device
->BackendLock
);
3426 clock
= V0(device
->Backend
,getClockLatency
)();
3427 almtx_unlock(&device
->BackendLock
);
3428 *values
= clock
.Latency
;
3431 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3433 alcSetError(device
, ALC_INVALID_VALUE
);
3436 almtx_lock(&device
->BackendLock
);
3437 clock
= V0(device
->Backend
,getClockLatency
)();
3438 almtx_unlock(&device
->BackendLock
);
3439 values
[0] = clock
.ClockTime
;
3440 values
[1] = clock
.Latency
;
3445 ivals
= malloc(size
* sizeof(ALCint
));
3446 size
= GetIntegerv(device
, pname
, size
, ivals
);
3447 for(i
= 0;i
< size
;i
++)
3448 values
[i
] = ivals
[i
];
3454 ALCdevice_DecRef(device
);
3458 /* alcIsExtensionPresent
3460 * Determines if there is support for a particular extension
3462 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3464 ALCboolean bResult
= ALC_FALSE
;
3466 VerifyDevice(&device
);
3469 alcSetError(device
, ALC_INVALID_VALUE
);
3472 size_t len
= strlen(extName
);
3473 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3476 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3477 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3482 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3486 } while(isspace(*ptr
));
3491 ALCdevice_DecRef(device
);
3496 /* alcGetProcAddress
3498 * Retrieves the function address for a particular extension function
3500 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3502 ALCvoid
*ptr
= NULL
;
3506 VerifyDevice(&device
);
3507 alcSetError(device
, ALC_INVALID_VALUE
);
3508 if(device
) ALCdevice_DecRef(device
);
3513 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3515 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3517 ptr
= alcFunctions
[i
].address
;
3529 * Get the value for a particular ALC enumeration name
3531 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3537 VerifyDevice(&device
);
3538 alcSetError(device
, ALC_INVALID_VALUE
);
3539 if(device
) ALCdevice_DecRef(device
);
3544 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3546 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3548 val
= alcEnumerations
[i
].value
;
3560 * Create and attach a context to the given device.
3562 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3564 ALCcontext
*ALContext
;
3568 /* Explicitly hold the list lock while taking the BackendLock in case the
3569 * device is asynchronously destropyed, to ensure this new context is
3570 * properly cleaned up after being made.
3573 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3576 alcSetError(device
, ALC_INVALID_DEVICE
);
3577 if(device
) ALCdevice_DecRef(device
);
3580 almtx_lock(&device
->BackendLock
);
3583 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3585 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3588 almtx_unlock(&device
->BackendLock
);
3590 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3591 ALCdevice_DecRef(device
);
3595 InitRef(&ALContext
->ref
, 1);
3596 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3598 ALContext
->Voices
= NULL
;
3599 ALContext
->VoiceCount
= 0;
3600 ALContext
->MaxVoices
= 0;
3601 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3602 ALContext
->Device
= device
;
3604 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3606 almtx_unlock(&device
->BackendLock
);
3608 al_free(ALContext
->Voices
);
3609 ALContext
->Voices
= NULL
;
3614 alcSetError(device
, err
);
3615 if(err
== ALC_INVALID_DEVICE
)
3617 V0(device
->Backend
,lock
)();
3618 aluHandleDisconnect(device
);
3619 V0(device
->Backend
,unlock
)();
3621 ALCdevice_DecRef(device
);
3624 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3626 ALCdevice_IncRef(ALContext
->Device
);
3627 InitContext(ALContext
);
3629 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3632 ERR("volume-adjust must be finite: %f\n", valf
);
3635 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3637 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3638 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3639 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3642 UpdateListenerProps(ALContext
);
3645 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3647 ALContext
->next
= head
;
3648 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3651 almtx_unlock(&device
->BackendLock
);
3653 ALCdevice_DecRef(device
);
3655 TRACE("Created context %p\n", ALContext
);
3659 /* alcDestroyContext
3661 * Remove a context from its device
3663 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3668 if(!VerifyContext(&context
))
3671 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3675 Device
= context
->Device
;
3678 almtx_lock(&Device
->BackendLock
);
3679 if(!ReleaseContext(context
, Device
))
3681 V0(Device
->Backend
,stop
)();
3682 Device
->Flags
&= ~DEVICE_RUNNING
;
3684 almtx_unlock(&Device
->BackendLock
);
3688 ALCcontext_DecRef(context
);
3692 /* alcGetCurrentContext
3694 * Returns the currently active context on the calling thread
3696 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3698 ALCcontext
*Context
= altss_get(LocalContext
);
3699 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3703 /* alcGetThreadContext
3705 * Returns the currently active thread-local context
3707 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3709 return altss_get(LocalContext
);
3713 /* alcMakeContextCurrent
3715 * Makes the given context the active process-wide context, and removes the
3716 * thread-local context for the calling thread.
3718 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3720 /* context must be valid or NULL */
3721 if(context
&& !VerifyContext(&context
))
3723 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3726 /* context's reference count is already incremented */
3727 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3728 if(context
) ALCcontext_DecRef(context
);
3730 if((context
=altss_get(LocalContext
)) != NULL
)
3732 altss_set(LocalContext
, NULL
);
3733 ALCcontext_DecRef(context
);
3739 /* alcSetThreadContext
3741 * Makes the given context the active context for the current thread
3743 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3747 /* context must be valid or NULL */
3748 if(context
&& !VerifyContext(&context
))
3750 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3753 /* context's reference count is already incremented */
3754 old
= altss_get(LocalContext
);
3755 altss_set(LocalContext
, context
);
3756 if(old
) ALCcontext_DecRef(old
);
3762 /* alcGetContextsDevice
3764 * Returns the device that a particular context is attached to
3766 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3770 if(!VerifyContext(&Context
))
3772 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3775 Device
= Context
->Device
;
3776 ALCcontext_DecRef(Context
);
3784 * Opens the named device.
3786 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3795 if(!PlaybackBackend
.name
)
3797 alcSetError(NULL
, ALC_INVALID_VALUE
);
3801 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3803 /* Some old Windows apps hardcode these expecting OpenAL to use a
3804 * specific audio API, even when they're not enumerated. Creative's
3805 * router effectively ignores them too.
3807 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3808 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3813 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3816 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3821 InitRef(&device
->ref
, 1);
3822 device
->Connected
= ALC_TRUE
;
3823 device
->Type
= Playback
;
3824 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3827 device
->Bs2b
= NULL
;
3828 device
->Uhj_Encoder
= NULL
;
3829 device
->Hrtf
= NULL
;
3830 device
->HrtfHandle
= NULL
;
3831 VECTOR_INIT(device
->HrtfList
);
3832 AL_STRING_INIT(device
->HrtfName
);
3833 device
->Render_Mode
= NormalRender
;
3834 AL_STRING_INIT(device
->DeviceName
);
3835 device
->Dry
.Buffer
= NULL
;
3836 device
->Dry
.NumChannels
= 0;
3837 device
->FOAOut
.Buffer
= NULL
;
3838 device
->FOAOut
.NumChannels
= 0;
3839 device
->RealOut
.Buffer
= NULL
;
3840 device
->RealOut
.NumChannels
= 0;
3841 device
->Limiter
= alloc_limiter();
3842 device
->AvgSpeakerDist
= 0.0f
;
3844 ATOMIC_INIT(&device
->ContextList
, NULL
);
3846 device
->ClockBase
= 0;
3847 device
->SamplesDone
= 0;
3849 device
->SourcesMax
= 256;
3850 device
->AuxiliaryEffectSlotMax
= 64;
3851 device
->NumAuxSends
= DEFAULT_SENDS
;
3853 InitUIntMap(&device
->BufferMap
, INT_MAX
);
3854 InitUIntMap(&device
->EffectMap
, INT_MAX
);
3855 InitUIntMap(&device
->FilterMap
, INT_MAX
);
3857 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3859 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3860 device
->ChannelDelay
[i
].Length
= 0;
3861 device
->ChannelDelay
[i
].Buffer
= NULL
;
3865 device
->FmtChans
= DevFmtChannelsDefault
;
3866 device
->FmtType
= DevFmtTypeDefault
;
3867 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3868 device
->IsHeadphones
= AL_FALSE
;
3869 device
->AmbiLayout
= AmbiLayout_Default
;
3870 device
->AmbiScale
= AmbiNorm_Default
;
3871 device
->NumUpdates
= 3;
3872 device
->UpdateSize
= 1024;
3874 if(!PlaybackBackend
.getFactory
)
3875 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3876 ALCbackend_Playback
);
3879 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3880 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3882 if(!device
->Backend
)
3885 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3890 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
3892 static const struct {
3893 const char name
[16];
3894 enum DevFmtChannels chans
;
3897 { "mono", DevFmtMono
, 0 },
3898 { "stereo", DevFmtStereo
, 0 },
3899 { "quad", DevFmtQuad
, 0 },
3900 { "surround51", DevFmtX51
, 0 },
3901 { "surround61", DevFmtX61
, 0 },
3902 { "surround71", DevFmtX71
, 0 },
3903 { "surround51rear", DevFmtX51Rear
, 0 },
3904 { "ambi1", DevFmtAmbi3D
, 1 },
3905 { "ambi2", DevFmtAmbi3D
, 2 },
3906 { "ambi3", DevFmtAmbi3D
, 3 },
3910 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3912 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3914 device
->FmtChans
= chanlist
[i
].chans
;
3915 device
->AmbiOrder
= chanlist
[i
].order
;
3916 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3920 if(i
== COUNTOF(chanlist
))
3921 ERR("Unsupported channels: %s\n", fmt
);
3923 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
3925 static const struct {
3926 const char name
[16];
3927 enum DevFmtType type
;
3929 { "int8", DevFmtByte
},
3930 { "uint8", DevFmtUByte
},
3931 { "int16", DevFmtShort
},
3932 { "uint16", DevFmtUShort
},
3933 { "int32", DevFmtInt
},
3934 { "uint32", DevFmtUInt
},
3935 { "float32", DevFmtFloat
},
3939 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3941 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3943 device
->FmtType
= typelist
[i
].type
;
3944 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3948 if(i
== COUNTOF(typelist
))
3949 ERR("Unsupported sample-type: %s\n", fmt
);
3952 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
3954 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3955 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3956 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3957 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3960 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
3961 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3963 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
3964 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3965 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3966 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3968 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
3969 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
3971 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3972 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
3974 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
3975 device
->NumAuxSends
= clampi(
3976 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
3979 device
->NumStereoSources
= 1;
3980 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
3982 // Find a playback device to open
3983 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3985 DELETE_OBJ(device
->Backend
);
3987 alcSetError(NULL
, err
);
3990 almtx_init(&device
->BackendLock
, almtx_plain
);
3992 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
3994 if(strcasecmp(fmt
, "fuma") == 0)
3996 device
->AmbiLayout
= AmbiLayout_FuMa
;
3997 device
->AmbiScale
= AmbiNorm_FuMa
;
3999 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4001 device
->AmbiLayout
= AmbiLayout_ACN
;
4002 device
->AmbiScale
= AmbiNorm_SN3D
;
4004 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4006 device
->AmbiLayout
= AmbiLayout_ACN
;
4007 device
->AmbiScale
= AmbiNorm_N3D
;
4010 ERR("Unsupported ambi-format: %s\n", fmt
);
4013 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
4015 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
4016 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
4018 device
->DefaultSlot
= NULL
;
4019 ERR("Failed to initialize the default effect slot\n");
4023 aluInitEffectPanning(device
->DefaultSlot
);
4024 if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
4026 DeinitEffectSlot(device
->DefaultSlot
);
4027 device
->DefaultSlot
= NULL
;
4028 ERR("Failed to initialize the default effect\n");
4034 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4036 device
->next
= head
;
4037 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4040 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4046 * Closes the given device.
4048 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4050 ALCdevice
*iter
, *origdev
;
4054 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4058 } while((iter
=iter
->next
) != NULL
);
4059 if(!iter
|| iter
->Type
== Capture
)
4061 alcSetError(iter
, ALC_INVALID_DEVICE
);
4065 almtx_lock(&device
->BackendLock
);
4068 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4070 ALCdevice
*volatile*list
= &origdev
->next
;
4075 *list
= (*list
)->next
;
4078 list
= &(*list
)->next
;
4083 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4086 ALCcontext
*next
= ctx
->next
;
4087 WARN("Releasing context %p\n", ctx
);
4088 ReleaseContext(ctx
, device
);
4091 if((device
->Flags
&DEVICE_RUNNING
))
4092 V0(device
->Backend
,stop
)();
4093 device
->Flags
&= ~DEVICE_RUNNING
;
4094 almtx_unlock(&device
->BackendLock
);
4096 ALCdevice_DecRef(device
);
4102 /************************************************
4103 * ALC capture functions
4104 ************************************************/
4105 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4107 ALCdevice
*device
= NULL
;
4113 if(!CaptureBackend
.name
)
4115 alcSetError(NULL
, ALC_INVALID_VALUE
);
4121 alcSetError(NULL
, ALC_INVALID_VALUE
);
4125 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4128 device
= al_calloc(16, sizeof(ALCdevice
));
4131 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4136 InitRef(&device
->ref
, 1);
4137 device
->Connected
= ALC_TRUE
;
4138 device
->Type
= Capture
;
4140 device
->Hrtf
= NULL
;
4141 device
->HrtfHandle
= NULL
;
4142 VECTOR_INIT(device
->HrtfList
);
4143 AL_STRING_INIT(device
->HrtfName
);
4145 AL_STRING_INIT(device
->DeviceName
);
4146 device
->Dry
.Buffer
= NULL
;
4147 device
->Dry
.NumChannels
= 0;
4148 device
->FOAOut
.Buffer
= NULL
;
4149 device
->FOAOut
.NumChannels
= 0;
4150 device
->RealOut
.Buffer
= NULL
;
4151 device
->RealOut
.NumChannels
= 0;
4153 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4154 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4155 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4157 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4159 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4160 device
->ChannelDelay
[i
].Length
= 0;
4161 device
->ChannelDelay
[i
].Buffer
= NULL
;
4164 if(!CaptureBackend
.getFactory
)
4165 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
4166 ALCbackend_Capture
);
4169 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
4170 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4172 if(!device
->Backend
)
4175 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4179 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4180 device
->Frequency
= frequency
;
4182 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4183 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4186 alcSetError(NULL
, ALC_INVALID_ENUM
);
4189 device
->IsHeadphones
= AL_FALSE
;
4190 device
->AmbiOrder
= 0;
4191 device
->AmbiLayout
= AmbiLayout_Default
;
4192 device
->AmbiScale
= AmbiNorm_Default
;
4194 device
->UpdateSize
= samples
;
4195 device
->NumUpdates
= 1;
4197 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4198 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4199 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4201 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4204 alcSetError(NULL
, err
);
4207 almtx_init(&device
->BackendLock
, almtx_plain
);
4210 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4212 device
->next
= head
;
4213 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4216 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4220 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4222 ALCdevice
*iter
, *origdev
;
4225 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4229 } while((iter
=iter
->next
) != NULL
);
4230 if(!iter
|| iter
->Type
!= Capture
)
4232 alcSetError(iter
, ALC_INVALID_DEVICE
);
4238 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4240 ALCdevice
*volatile*list
= &origdev
->next
;
4245 *list
= (*list
)->next
;
4248 list
= &(*list
)->next
;
4253 ALCdevice_DecRef(device
);
4258 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4260 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4261 alcSetError(device
, ALC_INVALID_DEVICE
);
4264 almtx_lock(&device
->BackendLock
);
4265 if(!device
->Connected
)
4266 alcSetError(device
, ALC_INVALID_DEVICE
);
4267 else if(!(device
->Flags
&DEVICE_RUNNING
))
4269 if(V0(device
->Backend
,start
)())
4270 device
->Flags
|= DEVICE_RUNNING
;
4273 aluHandleDisconnect(device
);
4274 alcSetError(device
, ALC_INVALID_DEVICE
);
4277 almtx_unlock(&device
->BackendLock
);
4280 if(device
) ALCdevice_DecRef(device
);
4283 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4285 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4286 alcSetError(device
, ALC_INVALID_DEVICE
);
4289 almtx_lock(&device
->BackendLock
);
4290 if((device
->Flags
&DEVICE_RUNNING
))
4291 V0(device
->Backend
,stop
)();
4292 device
->Flags
&= ~DEVICE_RUNNING
;
4293 almtx_unlock(&device
->BackendLock
);
4296 if(device
) ALCdevice_DecRef(device
);
4299 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4301 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4302 alcSetError(device
, ALC_INVALID_DEVICE
);
4305 ALCenum err
= ALC_INVALID_VALUE
;
4307 almtx_lock(&device
->BackendLock
);
4308 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4309 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4310 almtx_unlock(&device
->BackendLock
);
4312 if(err
!= ALC_NO_ERROR
)
4313 alcSetError(device
, err
);
4315 if(device
) ALCdevice_DecRef(device
);
4319 /************************************************
4320 * ALC loopback functions
4321 ************************************************/
4323 /* alcLoopbackOpenDeviceSOFT
4325 * Open a loopback device, for manual rendering.
4327 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4329 ALCbackendFactory
*factory
;
4335 /* Make sure the device name, if specified, is us. */
4336 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4338 alcSetError(NULL
, ALC_INVALID_VALUE
);
4342 device
= al_calloc(16, sizeof(ALCdevice
));
4345 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4350 InitRef(&device
->ref
, 1);
4351 device
->Connected
= ALC_TRUE
;
4352 device
->Type
= Loopback
;
4353 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4356 device
->Hrtf
= NULL
;
4357 device
->HrtfHandle
= NULL
;
4358 VECTOR_INIT(device
->HrtfList
);
4359 AL_STRING_INIT(device
->HrtfName
);
4360 device
->Bs2b
= NULL
;
4361 device
->Uhj_Encoder
= NULL
;
4362 device
->Render_Mode
= NormalRender
;
4363 AL_STRING_INIT(device
->DeviceName
);
4364 device
->Dry
.Buffer
= NULL
;
4365 device
->Dry
.NumChannels
= 0;
4366 device
->FOAOut
.Buffer
= NULL
;
4367 device
->FOAOut
.NumChannels
= 0;
4368 device
->RealOut
.Buffer
= NULL
;
4369 device
->RealOut
.NumChannels
= 0;
4370 device
->Limiter
= alloc_limiter();
4371 device
->AvgSpeakerDist
= 0.0f
;
4373 ATOMIC_INIT(&device
->ContextList
, NULL
);
4375 device
->ClockBase
= 0;
4376 device
->SamplesDone
= 0;
4378 device
->SourcesMax
= 256;
4379 device
->AuxiliaryEffectSlotMax
= 64;
4380 device
->NumAuxSends
= DEFAULT_SENDS
;
4382 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4383 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4384 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4386 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4388 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4389 device
->ChannelDelay
[i
].Length
= 0;
4390 device
->ChannelDelay
[i
].Buffer
= NULL
;
4393 factory
= ALCloopbackFactory_getFactory();
4394 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4395 if(!device
->Backend
)
4398 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4401 almtx_init(&device
->BackendLock
, almtx_plain
);
4404 device
->NumUpdates
= 0;
4405 device
->UpdateSize
= 0;
4407 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4408 device
->FmtChans
= DevFmtChannelsDefault
;
4409 device
->FmtType
= DevFmtTypeDefault
;
4410 device
->IsHeadphones
= AL_FALSE
;
4411 device
->AmbiLayout
= AmbiLayout_Default
;
4412 device
->AmbiScale
= AmbiNorm_Default
;
4414 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4415 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4417 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4418 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4420 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4421 device
->NumAuxSends
= clampi(
4422 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4425 device
->NumStereoSources
= 1;
4426 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4428 // Open the "backend"
4429 V(device
->Backend
,open
)("Loopback");
4432 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4434 device
->next
= head
;
4435 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4438 TRACE("Created device %p\n", device
);
4442 /* alcIsRenderFormatSupportedSOFT
4444 * Determines if the loopback device supports the given format for rendering.
4446 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
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(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4459 if(device
) ALCdevice_DecRef(device
);
4464 /* alcRenderSamplesSOFT
4466 * Renders some samples into a buffer, using the format last set by the
4467 * attributes given to alcCreateContext.
4469 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4471 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4472 alcSetError(device
, ALC_INVALID_DEVICE
);
4473 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4474 alcSetError(device
, ALC_INVALID_VALUE
);
4477 V0(device
->Backend
,lock
)();
4478 aluMixData(device
, buffer
, samples
);
4479 V0(device
->Backend
,unlock
)();
4481 if(device
) ALCdevice_DecRef(device
);
4485 /************************************************
4486 * ALC loopback2 functions
4487 ************************************************/
4489 ALC_API ALCboolean ALC_APIENTRY
alcIsAmbisonicFormatSupportedSOFT(ALCdevice
*device
, ALCenum layout
, ALCenum scaling
, ALsizei order
)
4491 ALCboolean ret
= ALC_FALSE
;
4493 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4494 alcSetError(device
, ALC_INVALID_DEVICE
);
4496 alcSetError(device
, ALC_INVALID_VALUE
);
4499 if(IsValidAmbiLayout(layout
) && IsValidAmbiScaling(scaling
) && order
<= MAX_AMBI_ORDER
)
4502 if(device
) ALCdevice_DecRef(device
);
4507 /************************************************
4508 * ALC DSP pause/resume functions
4509 ************************************************/
4511 /* alcDevicePauseSOFT
4513 * Pause the DSP to stop audio processing.
4515 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4517 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4518 alcSetError(device
, ALC_INVALID_DEVICE
);
4521 almtx_lock(&device
->BackendLock
);
4522 if((device
->Flags
&DEVICE_RUNNING
))
4523 V0(device
->Backend
,stop
)();
4524 device
->Flags
&= ~DEVICE_RUNNING
;
4525 device
->Flags
|= DEVICE_PAUSED
;
4526 almtx_unlock(&device
->BackendLock
);
4528 if(device
) ALCdevice_DecRef(device
);
4531 /* alcDeviceResumeSOFT
4533 * Resume the DSP to restart audio processing.
4535 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4537 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4538 alcSetError(device
, ALC_INVALID_DEVICE
);
4541 almtx_lock(&device
->BackendLock
);
4542 if((device
->Flags
&DEVICE_PAUSED
))
4544 device
->Flags
&= ~DEVICE_PAUSED
;
4545 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4547 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4548 device
->Flags
|= DEVICE_RUNNING
;
4551 alcSetError(device
, ALC_INVALID_DEVICE
);
4552 V0(device
->Backend
,lock
)();
4553 aluHandleDisconnect(device
);
4554 V0(device
->Backend
,unlock
)();
4558 almtx_unlock(&device
->BackendLock
);
4560 if(device
) ALCdevice_DecRef(device
);
4564 /************************************************
4565 * ALC HRTF functions
4566 ************************************************/
4568 /* alcGetStringiSOFT
4570 * Gets a string parameter at the given index.
4572 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4574 const ALCchar
*str
= NULL
;
4576 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4577 alcSetError(device
, ALC_INVALID_DEVICE
);
4578 else switch(paramName
)
4580 case ALC_HRTF_SPECIFIER_SOFT
:
4581 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4582 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4584 alcSetError(device
, ALC_INVALID_VALUE
);
4588 alcSetError(device
, ALC_INVALID_ENUM
);
4591 if(device
) ALCdevice_DecRef(device
);
4596 /* alcResetDeviceSOFT
4598 * Resets the given device output, using the specified attribute list.
4600 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4605 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4608 alcSetError(device
, ALC_INVALID_DEVICE
);
4609 if(device
) ALCdevice_DecRef(device
);
4612 almtx_lock(&device
->BackendLock
);
4615 err
= UpdateDeviceParams(device
, attribs
);
4616 almtx_unlock(&device
->BackendLock
);
4618 if(err
!= ALC_NO_ERROR
)
4620 alcSetError(device
, err
);
4621 if(err
== ALC_INVALID_DEVICE
)
4623 V0(device
->Backend
,lock
)();
4624 aluHandleDisconnect(device
);
4625 V0(device
->Backend
,unlock
)();
4627 ALCdevice_DecRef(device
);
4630 ALCdevice_DecRef(device
);