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 "mastering.h"
41 #include "bformatdec.h"
45 #include "fpu_modes.h"
52 #include "backends/base.h"
55 /************************************************
57 ************************************************/
60 ALCbackendFactory
* (*getFactory
)(void);
63 static struct BackendInfo BackendList
[] = {
65 { "jack", ALCjackBackendFactory_getFactory
},
67 #ifdef HAVE_PULSEAUDIO
68 { "pulse", ALCpulseBackendFactory_getFactory
},
71 { "alsa", ALCalsaBackendFactory_getFactory
},
74 { "core", ALCcoreAudioBackendFactory_getFactory
},
77 { "oss", ALCossBackendFactory_getFactory
},
80 { "solaris", ALCsolarisBackendFactory_getFactory
},
83 { "sndio", ALCsndioBackendFactory_getFactory
},
86 { "qsa", ALCqsaBackendFactory_getFactory
},
89 { "mmdevapi", ALCmmdevBackendFactory_getFactory
},
92 { "dsound", ALCdsoundBackendFactory_getFactory
},
95 { "winmm", ALCwinmmBackendFactory_getFactory
},
98 { "port", ALCportBackendFactory_getFactory
},
101 { "opensl", ALCopenslBackendFactory_getFactory
},
104 { "null", ALCnullBackendFactory_getFactory
},
106 { "wave", ALCwaveBackendFactory_getFactory
},
109 static ALsizei BackendListSize
= COUNTOF(BackendList
);
112 static struct BackendInfo PlaybackBackend
;
113 static struct BackendInfo CaptureBackend
;
116 /************************************************
117 * Functions, enums, and errors
118 ************************************************/
119 #define DECL(x) { #x, (ALCvoid*)(x) }
120 static const struct {
121 const ALCchar
*funcName
;
124 DECL(alcCreateContext
),
125 DECL(alcMakeContextCurrent
),
126 DECL(alcProcessContext
),
127 DECL(alcSuspendContext
),
128 DECL(alcDestroyContext
),
129 DECL(alcGetCurrentContext
),
130 DECL(alcGetContextsDevice
),
132 DECL(alcCloseDevice
),
134 DECL(alcIsExtensionPresent
),
135 DECL(alcGetProcAddress
),
136 DECL(alcGetEnumValue
),
138 DECL(alcGetIntegerv
),
139 DECL(alcCaptureOpenDevice
),
140 DECL(alcCaptureCloseDevice
),
141 DECL(alcCaptureStart
),
142 DECL(alcCaptureStop
),
143 DECL(alcCaptureSamples
),
145 DECL(alcSetThreadContext
),
146 DECL(alcGetThreadContext
),
148 DECL(alcLoopbackOpenDeviceSOFT
),
149 DECL(alcIsRenderFormatSupportedSOFT
),
150 DECL(alcRenderSamplesSOFT
),
152 DECL(alcDevicePauseSOFT
),
153 DECL(alcDeviceResumeSOFT
),
155 DECL(alcGetStringiSOFT
),
156 DECL(alcResetDeviceSOFT
),
158 DECL(alcGetInteger64vSOFT
),
173 DECL(alIsExtensionPresent
),
174 DECL(alGetProcAddress
),
175 DECL(alGetEnumValue
),
182 DECL(alGetListenerf
),
183 DECL(alGetListener3f
),
184 DECL(alGetListenerfv
),
185 DECL(alGetListeneri
),
186 DECL(alGetListener3i
),
187 DECL(alGetListeneriv
),
189 DECL(alDeleteSources
),
205 DECL(alSourceRewindv
),
206 DECL(alSourcePausev
),
209 DECL(alSourceRewind
),
211 DECL(alSourceQueueBuffers
),
212 DECL(alSourceUnqueueBuffers
),
214 DECL(alDeleteBuffers
),
229 DECL(alDopplerFactor
),
230 DECL(alDopplerVelocity
),
231 DECL(alSpeedOfSound
),
232 DECL(alDistanceModel
),
235 DECL(alDeleteFilters
),
246 DECL(alDeleteEffects
),
256 DECL(alGenAuxiliaryEffectSlots
),
257 DECL(alDeleteAuxiliaryEffectSlots
),
258 DECL(alIsAuxiliaryEffectSlot
),
259 DECL(alAuxiliaryEffectSloti
),
260 DECL(alAuxiliaryEffectSlotiv
),
261 DECL(alAuxiliaryEffectSlotf
),
262 DECL(alAuxiliaryEffectSlotfv
),
263 DECL(alGetAuxiliaryEffectSloti
),
264 DECL(alGetAuxiliaryEffectSlotiv
),
265 DECL(alGetAuxiliaryEffectSlotf
),
266 DECL(alGetAuxiliaryEffectSlotfv
),
268 DECL(alDeferUpdatesSOFT
),
269 DECL(alProcessUpdatesSOFT
),
272 DECL(alSource3dSOFT
),
273 DECL(alSourcedvSOFT
),
274 DECL(alGetSourcedSOFT
),
275 DECL(alGetSource3dSOFT
),
276 DECL(alGetSourcedvSOFT
),
277 DECL(alSourcei64SOFT
),
278 DECL(alSource3i64SOFT
),
279 DECL(alSourcei64vSOFT
),
280 DECL(alGetSourcei64SOFT
),
281 DECL(alGetSource3i64SOFT
),
282 DECL(alGetSourcei64vSOFT
),
284 DECL(alGetStringiSOFT
),
286 DECL(alMapBufferSOFT
),
287 DECL(alUnmapBufferSOFT
),
291 #define DECL(x) { #x, (x) }
292 static const struct {
293 const ALCchar
*enumName
;
295 } alcEnumerations
[] = {
300 DECL(ALC_MAJOR_VERSION
),
301 DECL(ALC_MINOR_VERSION
),
302 DECL(ALC_ATTRIBUTES_SIZE
),
303 DECL(ALC_ALL_ATTRIBUTES
),
304 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
305 DECL(ALC_DEVICE_SPECIFIER
),
306 DECL(ALC_ALL_DEVICES_SPECIFIER
),
307 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
308 DECL(ALC_EXTENSIONS
),
312 DECL(ALC_MONO_SOURCES
),
313 DECL(ALC_STEREO_SOURCES
),
314 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
315 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
316 DECL(ALC_CAPTURE_SAMPLES
),
319 DECL(ALC_EFX_MAJOR_VERSION
),
320 DECL(ALC_EFX_MINOR_VERSION
),
321 DECL(ALC_MAX_AUXILIARY_SENDS
),
323 DECL(ALC_FORMAT_CHANNELS_SOFT
),
324 DECL(ALC_FORMAT_TYPE_SOFT
),
327 DECL(ALC_STEREO_SOFT
),
329 DECL(ALC_5POINT1_SOFT
),
330 DECL(ALC_6POINT1_SOFT
),
331 DECL(ALC_7POINT1_SOFT
),
332 DECL(ALC_BFORMAT3D_SOFT
),
335 DECL(ALC_UNSIGNED_BYTE_SOFT
),
336 DECL(ALC_SHORT_SOFT
),
337 DECL(ALC_UNSIGNED_SHORT_SOFT
),
339 DECL(ALC_UNSIGNED_INT_SOFT
),
340 DECL(ALC_FLOAT_SOFT
),
343 DECL(ALC_DONT_CARE_SOFT
),
344 DECL(ALC_HRTF_STATUS_SOFT
),
345 DECL(ALC_HRTF_DISABLED_SOFT
),
346 DECL(ALC_HRTF_ENABLED_SOFT
),
347 DECL(ALC_HRTF_DENIED_SOFT
),
348 DECL(ALC_HRTF_REQUIRED_SOFT
),
349 DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT
),
350 DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
),
351 DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT
),
352 DECL(ALC_HRTF_SPECIFIER_SOFT
),
353 DECL(ALC_HRTF_ID_SOFT
),
355 DECL(ALC_AMBISONIC_LAYOUT_SOFT
),
356 DECL(ALC_AMBISONIC_SCALING_SOFT
),
357 DECL(ALC_AMBISONIC_ORDER_SOFT
),
363 DECL(ALC_OUTPUT_LIMITER_SOFT
),
366 DECL(ALC_INVALID_DEVICE
),
367 DECL(ALC_INVALID_CONTEXT
),
368 DECL(ALC_INVALID_ENUM
),
369 DECL(ALC_INVALID_VALUE
),
370 DECL(ALC_OUT_OF_MEMORY
),
378 DECL(AL_SOURCE_RELATIVE
),
379 DECL(AL_CONE_INNER_ANGLE
),
380 DECL(AL_CONE_OUTER_ANGLE
),
390 DECL(AL_ORIENTATION
),
391 DECL(AL_REFERENCE_DISTANCE
),
392 DECL(AL_ROLLOFF_FACTOR
),
393 DECL(AL_CONE_OUTER_GAIN
),
394 DECL(AL_MAX_DISTANCE
),
396 DECL(AL_SAMPLE_OFFSET
),
397 DECL(AL_BYTE_OFFSET
),
398 DECL(AL_SOURCE_TYPE
),
401 DECL(AL_UNDETERMINED
),
402 DECL(AL_METERS_PER_UNIT
),
403 DECL(AL_LOOP_POINTS_SOFT
),
404 DECL(AL_DIRECT_CHANNELS_SOFT
),
406 DECL(AL_DIRECT_FILTER
),
407 DECL(AL_AUXILIARY_SEND_FILTER
),
408 DECL(AL_AIR_ABSORPTION_FACTOR
),
409 DECL(AL_ROOM_ROLLOFF_FACTOR
),
410 DECL(AL_CONE_OUTER_GAINHF
),
411 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
412 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
413 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
415 DECL(AL_SOURCE_STATE
),
421 DECL(AL_BUFFERS_QUEUED
),
422 DECL(AL_BUFFERS_PROCESSED
),
424 DECL(AL_FORMAT_MONO8
),
425 DECL(AL_FORMAT_MONO16
),
426 DECL(AL_FORMAT_MONO_FLOAT32
),
427 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
428 DECL(AL_FORMAT_STEREO8
),
429 DECL(AL_FORMAT_STEREO16
),
430 DECL(AL_FORMAT_STEREO_FLOAT32
),
431 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
432 DECL(AL_FORMAT_MONO_IMA4
),
433 DECL(AL_FORMAT_STEREO_IMA4
),
434 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
435 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
436 DECL(AL_FORMAT_QUAD8_LOKI
),
437 DECL(AL_FORMAT_QUAD16_LOKI
),
438 DECL(AL_FORMAT_QUAD8
),
439 DECL(AL_FORMAT_QUAD16
),
440 DECL(AL_FORMAT_QUAD32
),
441 DECL(AL_FORMAT_51CHN8
),
442 DECL(AL_FORMAT_51CHN16
),
443 DECL(AL_FORMAT_51CHN32
),
444 DECL(AL_FORMAT_61CHN8
),
445 DECL(AL_FORMAT_61CHN16
),
446 DECL(AL_FORMAT_61CHN32
),
447 DECL(AL_FORMAT_71CHN8
),
448 DECL(AL_FORMAT_71CHN16
),
449 DECL(AL_FORMAT_71CHN32
),
450 DECL(AL_FORMAT_REAR8
),
451 DECL(AL_FORMAT_REAR16
),
452 DECL(AL_FORMAT_REAR32
),
453 DECL(AL_FORMAT_MONO_MULAW
),
454 DECL(AL_FORMAT_MONO_MULAW_EXT
),
455 DECL(AL_FORMAT_STEREO_MULAW
),
456 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
457 DECL(AL_FORMAT_QUAD_MULAW
),
458 DECL(AL_FORMAT_51CHN_MULAW
),
459 DECL(AL_FORMAT_61CHN_MULAW
),
460 DECL(AL_FORMAT_71CHN_MULAW
),
461 DECL(AL_FORMAT_REAR_MULAW
),
462 DECL(AL_FORMAT_MONO_ALAW_EXT
),
463 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
465 DECL(AL_FORMAT_BFORMAT2D_8
),
466 DECL(AL_FORMAT_BFORMAT2D_16
),
467 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
468 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
469 DECL(AL_FORMAT_BFORMAT3D_8
),
470 DECL(AL_FORMAT_BFORMAT3D_16
),
471 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
472 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
478 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
479 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
481 DECL(AL_SOURCE_RADIUS
),
483 DECL(AL_STEREO_ANGLES
),
490 DECL(AL_INVALID_NAME
),
491 DECL(AL_INVALID_ENUM
),
492 DECL(AL_INVALID_VALUE
),
493 DECL(AL_INVALID_OPERATION
),
494 DECL(AL_OUT_OF_MEMORY
),
501 DECL(AL_DOPPLER_FACTOR
),
502 DECL(AL_DOPPLER_VELOCITY
),
503 DECL(AL_DISTANCE_MODEL
),
504 DECL(AL_SPEED_OF_SOUND
),
505 DECL(AL_SOURCE_DISTANCE_MODEL
),
506 DECL(AL_DEFERRED_UPDATES_SOFT
),
507 DECL(AL_GAIN_LIMIT_SOFT
),
509 DECL(AL_INVERSE_DISTANCE
),
510 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
511 DECL(AL_LINEAR_DISTANCE
),
512 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
513 DECL(AL_EXPONENT_DISTANCE
),
514 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
516 DECL(AL_FILTER_TYPE
),
517 DECL(AL_FILTER_NULL
),
518 DECL(AL_FILTER_LOWPASS
),
519 DECL(AL_FILTER_HIGHPASS
),
520 DECL(AL_FILTER_BANDPASS
),
522 DECL(AL_LOWPASS_GAIN
),
523 DECL(AL_LOWPASS_GAINHF
),
525 DECL(AL_HIGHPASS_GAIN
),
526 DECL(AL_HIGHPASS_GAINLF
),
528 DECL(AL_BANDPASS_GAIN
),
529 DECL(AL_BANDPASS_GAINHF
),
530 DECL(AL_BANDPASS_GAINLF
),
532 DECL(AL_EFFECT_TYPE
),
533 DECL(AL_EFFECT_NULL
),
534 DECL(AL_EFFECT_REVERB
),
535 DECL(AL_EFFECT_EAXREVERB
),
536 DECL(AL_EFFECT_CHORUS
),
537 DECL(AL_EFFECT_DISTORTION
),
538 DECL(AL_EFFECT_ECHO
),
539 DECL(AL_EFFECT_FLANGER
),
541 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
542 DECL(AL_EFFECT_VOCAL_MORPHER
),
543 DECL(AL_EFFECT_PITCH_SHIFTER
),
545 DECL(AL_EFFECT_RING_MODULATOR
),
547 DECL(AL_EFFECT_AUTOWAH
),
549 DECL(AL_EFFECT_COMPRESSOR
),
550 DECL(AL_EFFECT_EQUALIZER
),
551 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
552 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
554 DECL(AL_EFFECTSLOT_EFFECT
),
555 DECL(AL_EFFECTSLOT_GAIN
),
556 DECL(AL_EFFECTSLOT_AUXILIARY_SEND_AUTO
),
557 DECL(AL_EFFECTSLOT_NULL
),
559 DECL(AL_EAXREVERB_DENSITY
),
560 DECL(AL_EAXREVERB_DIFFUSION
),
561 DECL(AL_EAXREVERB_GAIN
),
562 DECL(AL_EAXREVERB_GAINHF
),
563 DECL(AL_EAXREVERB_GAINLF
),
564 DECL(AL_EAXREVERB_DECAY_TIME
),
565 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
566 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
567 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
568 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
569 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
570 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
571 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
572 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
573 DECL(AL_EAXREVERB_ECHO_TIME
),
574 DECL(AL_EAXREVERB_ECHO_DEPTH
),
575 DECL(AL_EAXREVERB_MODULATION_TIME
),
576 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
577 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
578 DECL(AL_EAXREVERB_HFREFERENCE
),
579 DECL(AL_EAXREVERB_LFREFERENCE
),
580 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
581 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
583 DECL(AL_REVERB_DENSITY
),
584 DECL(AL_REVERB_DIFFUSION
),
585 DECL(AL_REVERB_GAIN
),
586 DECL(AL_REVERB_GAINHF
),
587 DECL(AL_REVERB_DECAY_TIME
),
588 DECL(AL_REVERB_DECAY_HFRATIO
),
589 DECL(AL_REVERB_REFLECTIONS_GAIN
),
590 DECL(AL_REVERB_REFLECTIONS_DELAY
),
591 DECL(AL_REVERB_LATE_REVERB_GAIN
),
592 DECL(AL_REVERB_LATE_REVERB_DELAY
),
593 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
594 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
595 DECL(AL_REVERB_DECAY_HFLIMIT
),
597 DECL(AL_CHORUS_WAVEFORM
),
598 DECL(AL_CHORUS_PHASE
),
599 DECL(AL_CHORUS_RATE
),
600 DECL(AL_CHORUS_DEPTH
),
601 DECL(AL_CHORUS_FEEDBACK
),
602 DECL(AL_CHORUS_DELAY
),
604 DECL(AL_DISTORTION_EDGE
),
605 DECL(AL_DISTORTION_GAIN
),
606 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
607 DECL(AL_DISTORTION_EQCENTER
),
608 DECL(AL_DISTORTION_EQBANDWIDTH
),
611 DECL(AL_ECHO_LRDELAY
),
612 DECL(AL_ECHO_DAMPING
),
613 DECL(AL_ECHO_FEEDBACK
),
614 DECL(AL_ECHO_SPREAD
),
616 DECL(AL_FLANGER_WAVEFORM
),
617 DECL(AL_FLANGER_PHASE
),
618 DECL(AL_FLANGER_RATE
),
619 DECL(AL_FLANGER_DEPTH
),
620 DECL(AL_FLANGER_FEEDBACK
),
621 DECL(AL_FLANGER_DELAY
),
623 DECL(AL_RING_MODULATOR_FREQUENCY
),
624 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
625 DECL(AL_RING_MODULATOR_WAVEFORM
),
627 DECL(AL_COMPRESSOR_ONOFF
),
629 DECL(AL_EQUALIZER_LOW_GAIN
),
630 DECL(AL_EQUALIZER_LOW_CUTOFF
),
631 DECL(AL_EQUALIZER_MID1_GAIN
),
632 DECL(AL_EQUALIZER_MID1_CENTER
),
633 DECL(AL_EQUALIZER_MID1_WIDTH
),
634 DECL(AL_EQUALIZER_MID2_GAIN
),
635 DECL(AL_EQUALIZER_MID2_CENTER
),
636 DECL(AL_EQUALIZER_MID2_WIDTH
),
637 DECL(AL_EQUALIZER_HIGH_GAIN
),
638 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
640 DECL(AL_DEDICATED_GAIN
),
642 DECL(AL_NUM_RESAMPLERS_SOFT
),
643 DECL(AL_DEFAULT_RESAMPLER_SOFT
),
644 DECL(AL_SOURCE_RESAMPLER_SOFT
),
645 DECL(AL_RESAMPLER_NAME_SOFT
),
647 DECL(AL_SOURCE_SPATIALIZE_SOFT
),
650 DECL(AL_MAP_READ_BIT_SOFT
),
651 DECL(AL_MAP_WRITE_BIT_SOFT
),
655 static const ALCchar alcNoError
[] = "No Error";
656 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
657 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
658 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
659 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
660 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
663 /************************************************
665 ************************************************/
667 /* Enumerated device names */
668 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
670 static al_string alcAllDevicesList
;
671 static al_string alcCaptureDeviceList
;
673 /* Default is always the first in the list */
674 static ALCchar
*alcDefaultAllDevicesSpecifier
;
675 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
677 /* Default context extensions */
678 static const ALchar alExtList
[] =
682 "AL_EXT_EXPONENT_DISTANCE "
685 "AL_EXT_LINEAR_DISTANCE "
688 "AL_EXT_MULAW_BFORMAT "
689 "AL_EXT_MULAW_MCFORMATS "
691 "AL_EXT_source_distance_model "
692 "AL_EXT_SOURCE_RADIUS "
693 "AL_EXT_STEREO_ANGLES "
694 "AL_LOKI_quadriphonic "
695 "AL_SOFT_block_alignment "
696 "AL_SOFT_deferred_updates "
697 "AL_SOFT_direct_channels "
698 "AL_SOFT_gain_clamp_ex "
699 "AL_SOFT_loop_points "
700 "AL_SOFTX_map_buffer "
702 "AL_SOFT_source_latency "
703 "AL_SOFT_source_length "
704 "AL_SOFT_source_resampler "
705 "AL_SOFT_source_spatialize";
707 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
709 /* Thread-local current context */
710 static altss_t LocalContext
;
711 /* Process-wide current context */
712 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
714 /* Mixing thread piority level */
719 enum LogLevel LogLevel
= LogWarning
;
721 enum LogLevel LogLevel
= LogError
;
724 /* Flag to trap ALC device errors */
725 static ALCboolean TrapALCError
= ALC_FALSE
;
727 /* One-time configuration init control */
728 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
730 /* Default effect that applies to sources that don't have an effect on send 0 */
731 static ALeffect DefaultEffect
;
733 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
736 static ALCboolean SuspendDefers
= ALC_TRUE
;
739 /************************************************
741 ************************************************/
742 static const ALCchar alcNoDeviceExtList
[] =
743 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
744 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
745 static const ALCchar alcExtensionList
[] =
746 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
747 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
748 "ALC_EXT_thread_local_context ALC_SOFT_device_clock ALC_SOFT_HRTF "
749 "ALC_SOFT_loopback ALC_SOFT_output_limiter ALC_SOFT_pause_device";
750 static const ALCint alcMajorVersion
= 1;
751 static const ALCint alcMinorVersion
= 1;
753 static const ALCint alcEFXMajorVersion
= 1;
754 static const ALCint alcEFXMinorVersion
= 0;
757 /************************************************
759 ************************************************/
760 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
762 static almtx_t ListLock
;
763 static inline void LockLists(void)
765 int ret
= almtx_lock(&ListLock
);
766 assert(ret
== althrd_success
);
768 static inline void UnlockLists(void)
770 int ret
= almtx_unlock(&ListLock
);
771 assert(ret
== althrd_success
);
774 /************************************************
775 * Library initialization
776 ************************************************/
778 static void alc_init(void);
779 static void alc_deinit(void);
780 static void alc_deinit_safe(void);
782 #ifndef AL_LIBTYPE_STATIC
783 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
787 case DLL_PROCESS_ATTACH
:
788 /* Pin the DLL so we won't get unloaded until the process terminates */
789 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
790 (WCHAR
*)hModule
, &hModule
);
794 case DLL_THREAD_DETACH
:
797 case DLL_PROCESS_DETACH
:
806 #elif defined(_MSC_VER)
807 #pragma section(".CRT$XCU",read)
808 static void alc_constructor(void);
809 static void alc_destructor(void);
810 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
812 static void alc_constructor(void)
814 atexit(alc_destructor
);
818 static void alc_destructor(void)
822 #elif defined(HAVE_GCC_DESTRUCTOR)
823 static void alc_init(void) __attribute__((constructor
));
824 static void alc_deinit(void) __attribute__((destructor
));
826 #error "No static initialization available on this platform!"
829 #elif defined(HAVE_GCC_DESTRUCTOR)
831 static void alc_init(void) __attribute__((constructor
));
832 static void alc_deinit(void) __attribute__((destructor
));
835 #error "No global initialization available on this platform!"
838 static void ReleaseThreadCtx(void *ptr
);
839 static void alc_init(void)
846 AL_STRING_INIT(alcAllDevicesList
);
847 AL_STRING_INIT(alcCaptureDeviceList
);
849 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
850 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
853 str
= getenv("__ALSOFT_REVERSE_Z");
854 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
857 str
= getenv("__ALSOFT_REVERB_IGNORES_SOUND_SPEED");
858 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
859 OverrideReverbSpeedOfSound
= AL_TRUE
;
861 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
862 assert(ret
== althrd_success
);
864 ret
= almtx_init(&ListLock
, almtx_recursive
);
865 assert(ret
== althrd_success
);
870 static void alc_initconfig(void)
872 const char *devs
, *str
;
877 str
= getenv("ALSOFT_LOGLEVEL");
880 long lvl
= strtol(str
, NULL
, 0);
881 if(lvl
>= NoLog
&& lvl
<= LogRef
)
885 str
= getenv("ALSOFT_LOGFILE");
888 FILE *logfile
= al_fopen(str
, "wt");
889 if(logfile
) LogFile
= logfile
;
890 else ERR("Failed to open log file '%s'\n", str
);
893 TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION
,
894 ALSOFT_GIT_COMMIT_HASH
, ALSOFT_GIT_BRANCH
);
899 if(BackendListSize
> 0)
900 len
+= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
901 for(i
= 1;i
< BackendListSize
;i
++)
902 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
903 TRACE("Supported backends: %s\n", buf
);
907 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
910 if(strcasecmp(str
, "ignore") == 0)
912 SuspendDefers
= ALC_FALSE
;
913 TRACE("Selected context suspend behavior, \"ignore\"\n");
916 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
920 #if defined(HAVE_SSE4_1)
921 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
| CPU_CAP_SSE4_1
;
922 #elif defined(HAVE_SSE3)
923 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE3
;
924 #elif defined(HAVE_SSE2)
925 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
926 #elif defined(HAVE_SSE)
927 capfilter
|= CPU_CAP_SSE
;
930 capfilter
|= CPU_CAP_NEON
;
932 if(ConfigValueStr(NULL
, NULL
, "disable-cpu-exts", &str
))
934 if(strcasecmp(str
, "all") == 0)
939 const char *next
= str
;
943 while(isspace(str
[0]))
945 next
= strchr(str
, ',');
947 if(!str
[0] || str
[0] == ',')
950 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
951 while(len
> 0 && isspace(str
[len
-1]))
953 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
954 capfilter
&= ~CPU_CAP_SSE
;
955 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
956 capfilter
&= ~CPU_CAP_SSE2
;
957 else if(len
== 4 && strncasecmp(str
, "sse3", len
) == 0)
958 capfilter
&= ~CPU_CAP_SSE3
;
959 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
960 capfilter
&= ~CPU_CAP_SSE4_1
;
961 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
962 capfilter
&= ~CPU_CAP_NEON
;
964 WARN("Invalid CPU extension \"%s\"\n", str
);
968 FillCPUCaps(capfilter
);
975 ConfigValueInt(NULL
, NULL
, "rt-prio", &RTPrioLevel
);
980 str
= getenv("ALSOFT_TRAP_ERROR");
981 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
983 TrapALError
= AL_TRUE
;
984 TrapALCError
= AL_TRUE
;
988 str
= getenv("ALSOFT_TRAP_AL_ERROR");
989 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
990 TrapALError
= AL_TRUE
;
991 TrapALError
= GetConfigValueBool(NULL
, NULL
, "trap-al-error", TrapALError
);
993 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
994 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
995 TrapALCError
= ALC_TRUE
;
996 TrapALCError
= GetConfigValueBool(NULL
, NULL
, "trap-alc-error", TrapALCError
);
999 if(ConfigValueFloat(NULL
, "reverb", "boost", &valf
))
1000 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1002 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1003 ConfigValueStr(NULL
, NULL
, "drivers", &devs
))
1007 const char *next
= devs
;
1008 int endlist
, delitem
;
1013 while(isspace(devs
[0]))
1015 next
= strchr(devs
, ',');
1017 delitem
= (devs
[0] == '-');
1018 if(devs
[0] == '-') devs
++;
1020 if(!devs
[0] || devs
[0] == ',')
1027 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1028 while(len
> 0 && isspace(devs
[len
-1]))
1030 for(n
= i
;n
< BackendListSize
;n
++)
1032 if(len
== strlen(BackendList
[n
].name
) &&
1033 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1037 for(;n
+1 < BackendListSize
;n
++)
1038 BackendList
[n
] = BackendList
[n
+1];
1043 struct BackendInfo Bkp
= BackendList
[n
];
1045 BackendList
[n
] = BackendList
[n
-1];
1046 BackendList
[n
] = Bkp
;
1056 BackendListSize
= i
;
1059 for(i
= 0;i
< BackendListSize
&& (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1061 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1062 if(!V0(factory
,init
)())
1064 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1068 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1069 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1071 PlaybackBackend
= BackendList
[i
];
1072 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1074 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1076 CaptureBackend
= BackendList
[i
];
1077 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1081 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1085 if(!PlaybackBackend
.name
)
1086 WARN("No playback backend available!\n");
1087 if(!CaptureBackend
.name
)
1088 WARN("No capture backend available!\n");
1090 if(ConfigValueStr(NULL
, NULL
, "excludefx", &str
))
1093 const char *next
= str
;
1097 next
= strchr(str
, ',');
1099 if(!str
[0] || next
== str
)
1102 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1103 for(n
= 0;n
< EFFECTLIST_SIZE
;n
++)
1105 if(len
== strlen(EffectList
[n
].name
) &&
1106 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1107 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1112 InitEffectFactoryMap();
1114 InitEffect(&DefaultEffect
);
1115 str
= getenv("ALSOFT_DEFAULT_REVERB");
1116 if((str
&& str
[0]) || ConfigValueStr(NULL
, NULL
, "default-reverb", &str
))
1117 LoadReverbPreset(str
, &DefaultEffect
);
1119 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1124 static JavaVM
*gJavaVM
;
1125 static pthread_key_t gJVMThreadKey
;
1127 static void CleanupJNIEnv(void* UNUSED(ptr
))
1129 JCALL0(gJavaVM
,DetachCurrentThread
)();
1132 void *Android_GetJNIEnv(void)
1136 WARN("gJavaVM is NULL!\n");
1140 /* http://developer.android.com/guide/practices/jni.html
1142 * All threads are Linux threads, scheduled by the kernel. They're usually
1143 * started from managed code (using Thread.start), but they can also be
1144 * created elsewhere and then attached to the JavaVM. For example, a thread
1145 * started with pthread_create can be attached with the JNI
1146 * AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a
1147 * thread is attached, it has no JNIEnv, and cannot make JNI calls.
1148 * Attaching a natively-created thread causes a java.lang.Thread object to
1149 * be constructed and added to the "main" ThreadGroup, making it visible to
1150 * the debugger. Calling AttachCurrentThread on an already-attached thread
1153 JNIEnv
*env
= pthread_getspecific(gJVMThreadKey
);
1156 int status
= JCALL(gJavaVM
,AttachCurrentThread
)(&env
, NULL
);
1159 ERR("Failed to attach current thread\n");
1162 pthread_setspecific(gJVMThreadKey
, env
);
1167 /* Automatically called by JNI. */
1168 JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM
*jvm
, void* UNUSED(reserved
))
1174 if(JCALL(gJavaVM
,GetEnv
)(&env
, JNI_VERSION_1_4
) != JNI_OK
)
1176 ERR("Failed to get JNIEnv with JNI_VERSION_1_4\n");
1180 /* Create gJVMThreadKey so we can keep track of the JNIEnv assigned to each
1181 * thread. The JNIEnv *must* be detached before the thread is destroyed.
1183 if((err
=pthread_key_create(&gJVMThreadKey
, CleanupJNIEnv
)) != 0)
1184 ERR("pthread_key_create failed: %d\n", err
);
1185 pthread_setspecific(gJVMThreadKey
, env
);
1186 return JNI_VERSION_1_4
;
1191 /************************************************
1192 * Library deinitialization
1193 ************************************************/
1194 static void alc_cleanup(void)
1198 AL_STRING_DEINIT(alcAllDevicesList
);
1199 AL_STRING_DEINIT(alcCaptureDeviceList
);
1201 free(alcDefaultAllDevicesSpecifier
);
1202 alcDefaultAllDevicesSpecifier
= NULL
;
1203 free(alcCaptureDefaultDeviceSpecifier
);
1204 alcCaptureDefaultDeviceSpecifier
= NULL
;
1206 if((dev
=ATOMIC_EXCHANGE_PTR_SEQ(&DeviceList
, NULL
)) != NULL
)
1211 } while((dev
=dev
->next
) != NULL
);
1212 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1215 DeinitEffectFactoryMap();
1218 static void alc_deinit_safe(void)
1226 almtx_destroy(&ListLock
);
1227 altss_delete(LocalContext
);
1229 if(LogFile
!= stderr
)
1234 static void alc_deinit(void)
1240 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1241 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1243 for(i
= 0;i
< BackendListSize
;i
++)
1245 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1246 V0(factory
,deinit
)();
1249 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1250 V0(factory
,deinit
)();
1257 /************************************************
1258 * Device enumeration
1259 ************************************************/
1260 static void ProbeDevices(al_string
*list
, struct BackendInfo
*backendinfo
, enum DevProbe type
)
1267 if(backendinfo
->getFactory
)
1269 ALCbackendFactory
*factory
= backendinfo
->getFactory();
1270 V(factory
,probe
)(type
);
1275 static void ProbeAllDevicesList(void)
1276 { ProbeDevices(&alcAllDevicesList
, &PlaybackBackend
, ALL_DEVICE_PROBE
); }
1277 static void ProbeCaptureDeviceList(void)
1278 { ProbeDevices(&alcCaptureDeviceList
, &CaptureBackend
, CAPTURE_DEVICE_PROBE
); }
1280 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1282 size_t len
= strlen(name
);
1284 alstr_append_range(devnames
, name
, name
+len
+1);
1286 void AppendAllDevicesList(const ALCchar
*name
)
1287 { AppendDevice(name
, &alcAllDevicesList
); }
1288 void AppendCaptureDeviceList(const ALCchar
*name
)
1289 { AppendDevice(name
, &alcCaptureDeviceList
); }
1292 /************************************************
1293 * Device format information
1294 ************************************************/
1295 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1299 case DevFmtByte
: return "Signed Byte";
1300 case DevFmtUByte
: return "Unsigned Byte";
1301 case DevFmtShort
: return "Signed Short";
1302 case DevFmtUShort
: return "Unsigned Short";
1303 case DevFmtInt
: return "Signed Int";
1304 case DevFmtUInt
: return "Unsigned Int";
1305 case DevFmtFloat
: return "Float";
1307 return "(unknown type)";
1309 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1313 case DevFmtMono
: return "Mono";
1314 case DevFmtStereo
: return "Stereo";
1315 case DevFmtQuad
: return "Quadraphonic";
1316 case DevFmtX51
: return "5.1 Surround";
1317 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1318 case DevFmtX61
: return "6.1 Surround";
1319 case DevFmtX71
: return "7.1 Surround";
1320 case DevFmtAmbi3D
: return "Ambisonic 3D";
1322 return "(unknown channels)";
1325 extern inline ALsizei
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
, ALsizei ambiorder
);
1326 ALsizei
BytesFromDevFmt(enum DevFmtType type
)
1330 case DevFmtByte
: return sizeof(ALbyte
);
1331 case DevFmtUByte
: return sizeof(ALubyte
);
1332 case DevFmtShort
: return sizeof(ALshort
);
1333 case DevFmtUShort
: return sizeof(ALushort
);
1334 case DevFmtInt
: return sizeof(ALint
);
1335 case DevFmtUInt
: return sizeof(ALuint
);
1336 case DevFmtFloat
: return sizeof(ALfloat
);
1340 ALsizei
ChannelsFromDevFmt(enum DevFmtChannels chans
, ALsizei ambiorder
)
1344 case DevFmtMono
: return 1;
1345 case DevFmtStereo
: return 2;
1346 case DevFmtQuad
: return 4;
1347 case DevFmtX51
: return 6;
1348 case DevFmtX51Rear
: return 6;
1349 case DevFmtX61
: return 7;
1350 case DevFmtX71
: return 8;
1351 case DevFmtAmbi3D
: return (ambiorder
>= 3) ? 16 :
1352 (ambiorder
== 2) ? 9 :
1353 (ambiorder
== 1) ? 4 : 1;
1358 static ALboolean
DecomposeDevFormat(ALenum format
, enum DevFmtChannels
*chans
,
1359 enum DevFmtType
*type
)
1361 static const struct {
1363 enum DevFmtChannels channels
;
1364 enum DevFmtType type
;
1366 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1367 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1368 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1370 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1371 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1372 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1374 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1375 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1376 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1378 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1379 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1380 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1382 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1383 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1384 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1386 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1387 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1388 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1392 for(i
= 0;i
< COUNTOF(list
);i
++)
1394 if(list
[i
].format
== format
)
1396 *chans
= list
[i
].channels
;
1397 *type
= list
[i
].type
;
1405 static ALCboolean
IsValidALCType(ALCenum type
)
1410 case ALC_UNSIGNED_BYTE_SOFT
:
1411 case ALC_SHORT_SOFT
:
1412 case ALC_UNSIGNED_SHORT_SOFT
:
1414 case ALC_UNSIGNED_INT_SOFT
:
1415 case ALC_FLOAT_SOFT
:
1421 static ALCboolean
IsValidALCChannels(ALCenum channels
)
1426 case ALC_STEREO_SOFT
:
1428 case ALC_5POINT1_SOFT
:
1429 case ALC_6POINT1_SOFT
:
1430 case ALC_7POINT1_SOFT
:
1431 case ALC_BFORMAT3D_SOFT
:
1437 static ALCboolean
IsValidAmbiLayout(ALCenum layout
)
1448 static ALCboolean
IsValidAmbiScaling(ALCenum scaling
)
1460 /************************************************
1461 * Miscellaneous ALC helpers
1462 ************************************************/
1464 /* SetDefaultWFXChannelOrder
1466 * Sets the default channel order used by WaveFormatEx.
1468 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1472 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1473 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1475 switch(device
->FmtChans
)
1478 device
->RealOut
.ChannelName
[0] = FrontCenter
;
1481 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1482 device
->RealOut
.ChannelName
[1] = FrontRight
;
1485 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1486 device
->RealOut
.ChannelName
[1] = FrontRight
;
1487 device
->RealOut
.ChannelName
[2] = BackLeft
;
1488 device
->RealOut
.ChannelName
[3] = BackRight
;
1491 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1492 device
->RealOut
.ChannelName
[1] = FrontRight
;
1493 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1494 device
->RealOut
.ChannelName
[3] = LFE
;
1495 device
->RealOut
.ChannelName
[4] = SideLeft
;
1496 device
->RealOut
.ChannelName
[5] = SideRight
;
1499 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1500 device
->RealOut
.ChannelName
[1] = FrontRight
;
1501 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1502 device
->RealOut
.ChannelName
[3] = LFE
;
1503 device
->RealOut
.ChannelName
[4] = BackLeft
;
1504 device
->RealOut
.ChannelName
[5] = BackRight
;
1507 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1508 device
->RealOut
.ChannelName
[1] = FrontRight
;
1509 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1510 device
->RealOut
.ChannelName
[3] = LFE
;
1511 device
->RealOut
.ChannelName
[4] = BackCenter
;
1512 device
->RealOut
.ChannelName
[5] = SideLeft
;
1513 device
->RealOut
.ChannelName
[6] = SideRight
;
1516 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1517 device
->RealOut
.ChannelName
[1] = FrontRight
;
1518 device
->RealOut
.ChannelName
[2] = FrontCenter
;
1519 device
->RealOut
.ChannelName
[3] = LFE
;
1520 device
->RealOut
.ChannelName
[4] = BackLeft
;
1521 device
->RealOut
.ChannelName
[5] = BackRight
;
1522 device
->RealOut
.ChannelName
[6] = SideLeft
;
1523 device
->RealOut
.ChannelName
[7] = SideRight
;
1526 device
->RealOut
.ChannelName
[0] = Aux0
;
1527 if(device
->AmbiOrder
> 0)
1529 device
->RealOut
.ChannelName
[1] = Aux1
;
1530 device
->RealOut
.ChannelName
[2] = Aux2
;
1531 device
->RealOut
.ChannelName
[3] = Aux3
;
1533 if(device
->AmbiOrder
> 1)
1535 device
->RealOut
.ChannelName
[4] = Aux4
;
1536 device
->RealOut
.ChannelName
[5] = Aux5
;
1537 device
->RealOut
.ChannelName
[6] = Aux6
;
1538 device
->RealOut
.ChannelName
[7] = Aux7
;
1539 device
->RealOut
.ChannelName
[8] = Aux8
;
1541 if(device
->AmbiOrder
> 2)
1543 device
->RealOut
.ChannelName
[9] = Aux9
;
1544 device
->RealOut
.ChannelName
[10] = Aux10
;
1545 device
->RealOut
.ChannelName
[11] = Aux11
;
1546 device
->RealOut
.ChannelName
[12] = Aux12
;
1547 device
->RealOut
.ChannelName
[13] = Aux13
;
1548 device
->RealOut
.ChannelName
[14] = Aux14
;
1549 device
->RealOut
.ChannelName
[15] = Aux15
;
1555 /* SetDefaultChannelOrder
1557 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1559 void SetDefaultChannelOrder(ALCdevice
*device
)
1563 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1564 device
->RealOut
.ChannelName
[i
] = InvalidChannel
;
1566 switch(device
->FmtChans
)
1569 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1570 device
->RealOut
.ChannelName
[1] = FrontRight
;
1571 device
->RealOut
.ChannelName
[2] = BackLeft
;
1572 device
->RealOut
.ChannelName
[3] = BackRight
;
1573 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1574 device
->RealOut
.ChannelName
[5] = LFE
;
1577 device
->RealOut
.ChannelName
[0] = FrontLeft
;
1578 device
->RealOut
.ChannelName
[1] = FrontRight
;
1579 device
->RealOut
.ChannelName
[2] = BackLeft
;
1580 device
->RealOut
.ChannelName
[3] = BackRight
;
1581 device
->RealOut
.ChannelName
[4] = FrontCenter
;
1582 device
->RealOut
.ChannelName
[5] = LFE
;
1583 device
->RealOut
.ChannelName
[6] = SideLeft
;
1584 device
->RealOut
.ChannelName
[7] = SideRight
;
1587 /* Same as WFX order */
1594 SetDefaultWFXChannelOrder(device
);
1599 extern inline ALint
GetChannelIndex(const enum Channel names
[MAX_OUTPUT_CHANNELS
], enum Channel chan
);
1600 extern inline ALint
GetChannelIdxByName(const RealMixParams
*real
, enum Channel chan
);
1603 /* ALCcontext_DeferUpdates
1605 * Defers/suspends updates for the given context's listener and sources. This
1606 * does *NOT* stop mixing, but rather prevents certain property changes from
1609 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1611 ATOMIC_STORE_SEQ(&context
->DeferUpdates
, AL_TRUE
);
1614 /* ALCcontext_ProcessUpdates
1616 * Resumes update processing after being deferred.
1618 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1620 ReadLock(&context
->PropLock
);
1621 if(ATOMIC_EXCHANGE_SEQ(&context
->DeferUpdates
, AL_FALSE
))
1623 /* Tell the mixer to stop applying updates, then wait for any active
1624 * updating to finish, before providing updates.
1626 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_TRUE
);
1627 while((ATOMIC_LOAD(&context
->UpdateCount
, almemory_order_acquire
)&1) != 0)
1630 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_acq_rel
))
1631 UpdateContextProps(context
);
1632 if(!ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_acq_rel
))
1633 UpdateListenerProps(context
);
1634 UpdateAllEffectSlotProps(context
);
1635 UpdateAllSourceProps(context
);
1637 /* Now with all updates declared, let the mixer continue applying them
1638 * so they all happen at once.
1640 ATOMIC_STORE_SEQ(&context
->HoldUpdates
, AL_FALSE
);
1642 ReadUnlock(&context
->PropLock
);
1648 * Stores the latest ALC device error
1650 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1652 WARN("Error generated on device %p, code 0x%04x\n", device
, errorCode
);
1656 /* DebugBreak() will cause an exception if there is no debugger */
1657 if(IsDebuggerPresent())
1659 #elif defined(SIGTRAP)
1665 ATOMIC_STORE_SEQ(&device
->LastError
, errorCode
);
1667 ATOMIC_STORE_SEQ(&LastNullDeviceError
, errorCode
);
1671 struct Compressor
*CreateDeviceLimiter(const ALCdevice
*device
)
1673 return CompressorInit(0.0f
, 0.0f
, AL_FALSE
, AL_TRUE
, 0.0f
, 0.0f
, 0.5f
, 2.0f
,
1674 0.0f
, -3.0f
, 3.0f
, device
->Frequency
);
1679 * Updates the device's base clock time with however many samples have been
1680 * done. This is used so frequency changes on the device don't cause the time
1681 * to jump forward or back. Must not be called while the device is running/
1684 static inline void UpdateClockBase(ALCdevice
*device
)
1686 IncrementRef(&device
->MixCount
);
1687 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1688 device
->SamplesDone
= 0;
1689 IncrementRef(&device
->MixCount
);
1692 /* UpdateDeviceParams
1694 * Updates device parameters according to the attribute list (caller is
1695 * responsible for holding the list lock).
1697 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1699 enum HrtfRequestMode hrtf_userreq
= Hrtf_Default
;
1700 enum HrtfRequestMode hrtf_appreq
= Hrtf_Default
;
1701 ALCenum gainLimiter
= device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
1702 const ALsizei old_sends
= device
->NumAuxSends
;
1703 ALsizei new_sends
= device
->NumAuxSends
;
1704 enum DevFmtChannels oldChans
;
1705 enum DevFmtType oldType
;
1706 ALboolean update_failed
;
1707 ALCsizei hrtf_id
= -1;
1708 ALCcontext
*context
;
1714 // Check for attributes
1715 if(device
->Type
== Loopback
)
1717 ALCsizei numMono
, numStereo
, numSends
;
1718 ALCenum alayout
= AL_NONE
;
1719 ALCenum ascale
= AL_NONE
;
1720 ALCenum schans
= AL_NONE
;
1721 ALCenum stype
= AL_NONE
;
1722 ALCsizei attrIdx
= 0;
1723 ALCsizei aorder
= 0;
1728 WARN("Missing attributes for loopback device\n");
1729 return ALC_INVALID_VALUE
;
1732 numMono
= device
->NumMonoSources
;
1733 numStereo
= device
->NumStereoSources
;
1734 numSends
= old_sends
;
1736 #define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v)
1737 while(attrList
[attrIdx
])
1739 switch(attrList
[attrIdx
])
1741 case ALC_FORMAT_CHANNELS_SOFT
:
1742 schans
= attrList
[attrIdx
+ 1];
1743 TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT
, schans
);
1744 if(!IsValidALCChannels(schans
))
1745 return ALC_INVALID_VALUE
;
1748 case ALC_FORMAT_TYPE_SOFT
:
1749 stype
= attrList
[attrIdx
+ 1];
1750 TRACE_ATTR(ALC_FORMAT_TYPE_SOFT
, stype
);
1751 if(!IsValidALCType(stype
))
1752 return ALC_INVALID_VALUE
;
1756 freq
= attrList
[attrIdx
+ 1];
1757 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1758 if(freq
< MIN_OUTPUT_RATE
)
1759 return ALC_INVALID_VALUE
;
1762 case ALC_AMBISONIC_LAYOUT_SOFT
:
1763 alayout
= attrList
[attrIdx
+ 1];
1764 TRACE_ATTR(ALC_AMBISONIC_LAYOUT_SOFT
, alayout
);
1765 if(!IsValidAmbiLayout(alayout
))
1766 return ALC_INVALID_VALUE
;
1769 case ALC_AMBISONIC_SCALING_SOFT
:
1770 ascale
= attrList
[attrIdx
+ 1];
1771 TRACE_ATTR(ALC_AMBISONIC_SCALING_SOFT
, ascale
);
1772 if(!IsValidAmbiScaling(ascale
))
1773 return ALC_INVALID_VALUE
;
1776 case ALC_AMBISONIC_ORDER_SOFT
:
1777 aorder
= attrList
[attrIdx
+ 1];
1778 TRACE_ATTR(ALC_AMBISONIC_ORDER_SOFT
, aorder
);
1779 if(aorder
< 1 || aorder
> MAX_AMBI_ORDER
)
1780 return ALC_INVALID_VALUE
;
1783 case ALC_MONO_SOURCES
:
1784 numMono
= attrList
[attrIdx
+ 1];
1785 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1786 numMono
= maxi(numMono
, 0);
1789 case ALC_STEREO_SOURCES
:
1790 numStereo
= attrList
[attrIdx
+ 1];
1791 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1792 numStereo
= maxi(numStereo
, 0);
1795 case ALC_MAX_AUXILIARY_SENDS
:
1796 numSends
= attrList
[attrIdx
+ 1];
1797 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1798 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1802 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1803 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1804 hrtf_appreq
= Hrtf_Disable
;
1805 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1806 hrtf_appreq
= Hrtf_Enable
;
1808 hrtf_appreq
= Hrtf_Default
;
1811 case ALC_HRTF_ID_SOFT
:
1812 hrtf_id
= attrList
[attrIdx
+ 1];
1813 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1816 case ALC_OUTPUT_LIMITER_SOFT
:
1817 gainLimiter
= attrList
[attrIdx
+ 1];
1818 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1822 TRACE("Loopback 0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1823 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1831 if(!schans
|| !stype
|| !freq
)
1833 WARN("Missing format for loopback device\n");
1834 return ALC_INVALID_VALUE
;
1836 if(schans
== ALC_BFORMAT3D_SOFT
&& (!alayout
|| !ascale
|| !aorder
))
1838 WARN("Missing ambisonic info for loopback device\n");
1839 return ALC_INVALID_VALUE
;
1842 if((device
->Flags
&DEVICE_RUNNING
))
1843 V0(device
->Backend
,stop
)();
1844 device
->Flags
&= ~DEVICE_RUNNING
;
1846 UpdateClockBase(device
);
1848 device
->Frequency
= freq
;
1849 device
->FmtChans
= schans
;
1850 device
->FmtType
= stype
;
1851 if(schans
== ALC_BFORMAT3D_SOFT
)
1853 device
->AmbiOrder
= aorder
;
1854 device
->AmbiLayout
= alayout
;
1855 device
->AmbiScale
= ascale
;
1858 if(numMono
> INT_MAX
-numStereo
)
1859 numMono
= INT_MAX
-numStereo
;
1860 numMono
+= numStereo
;
1861 if(ConfigValueInt(NULL
, NULL
, "sources", &numMono
))
1867 numMono
= maxi(numMono
, 256);
1868 numStereo
= mini(numStereo
, numMono
);
1869 numMono
-= numStereo
;
1870 device
->SourcesMax
= numMono
+ numStereo
;
1872 device
->NumMonoSources
= numMono
;
1873 device
->NumStereoSources
= numStereo
;
1875 if(ConfigValueInt(NULL
, NULL
, "sends", &new_sends
))
1876 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1878 new_sends
= numSends
;
1880 else if(attrList
&& attrList
[0])
1882 ALCsizei numMono
, numStereo
, numSends
;
1883 ALCsizei attrIdx
= 0;
1886 /* If a context is already running on the device, stop playback so the
1887 * device attributes can be updated. */
1888 if((device
->Flags
&DEVICE_RUNNING
))
1889 V0(device
->Backend
,stop
)();
1890 device
->Flags
&= ~DEVICE_RUNNING
;
1892 UpdateClockBase(device
);
1894 freq
= device
->Frequency
;
1895 numMono
= device
->NumMonoSources
;
1896 numStereo
= device
->NumStereoSources
;
1897 numSends
= old_sends
;
1899 #define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v)
1900 while(attrList
[attrIdx
])
1902 switch(attrList
[attrIdx
])
1905 freq
= attrList
[attrIdx
+ 1];
1906 TRACE_ATTR(ALC_FREQUENCY
, freq
);
1907 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1910 case ALC_MONO_SOURCES
:
1911 numMono
= attrList
[attrIdx
+ 1];
1912 TRACE_ATTR(ALC_MONO_SOURCES
, numMono
);
1913 numMono
= maxi(numMono
, 0);
1916 case ALC_STEREO_SOURCES
:
1917 numStereo
= attrList
[attrIdx
+ 1];
1918 TRACE_ATTR(ALC_STEREO_SOURCES
, numStereo
);
1919 numStereo
= maxi(numStereo
, 0);
1922 case ALC_MAX_AUXILIARY_SENDS
:
1923 numSends
= attrList
[attrIdx
+ 1];
1924 TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS
, numSends
);
1925 numSends
= clampi(numSends
, 0, MAX_SENDS
);
1929 TRACE_ATTR(ALC_HRTF_SOFT
, attrList
[attrIdx
+ 1]);
1930 if(attrList
[attrIdx
+ 1] == ALC_FALSE
)
1931 hrtf_appreq
= Hrtf_Disable
;
1932 else if(attrList
[attrIdx
+ 1] == ALC_TRUE
)
1933 hrtf_appreq
= Hrtf_Enable
;
1935 hrtf_appreq
= Hrtf_Default
;
1938 case ALC_HRTF_ID_SOFT
:
1939 hrtf_id
= attrList
[attrIdx
+ 1];
1940 TRACE_ATTR(ALC_HRTF_ID_SOFT
, hrtf_id
);
1943 case ALC_OUTPUT_LIMITER_SOFT
:
1944 gainLimiter
= attrList
[attrIdx
+ 1];
1945 TRACE_ATTR(ALC_OUTPUT_LIMITER_SOFT
, gainLimiter
);
1949 TRACE("0x%04X = %d (0x%x)\n", attrList
[attrIdx
],
1950 attrList
[attrIdx
+ 1], attrList
[attrIdx
+ 1]);
1958 ConfigValueUInt(alstr_get_cstr(device
->DeviceName
), NULL
, "frequency", &freq
);
1959 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1961 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1963 /* SSE and Neon do best with the update size being a multiple of 4 */
1964 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1965 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1967 device
->Frequency
= freq
;
1969 if(numMono
> INT_MAX
-numStereo
)
1970 numMono
= INT_MAX
-numStereo
;
1971 numMono
+= numStereo
;
1972 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sources", &numMono
))
1978 numMono
= maxi(numMono
, 256);
1979 numStereo
= mini(numStereo
, numMono
);
1980 numMono
-= numStereo
;
1981 device
->SourcesMax
= numMono
+ numStereo
;
1983 device
->NumMonoSources
= numMono
;
1984 device
->NumStereoSources
= numStereo
;
1986 if(ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "sends", &new_sends
))
1987 new_sends
= mini(numSends
, clampi(new_sends
, 0, MAX_SENDS
));
1989 new_sends
= numSends
;
1992 if((device
->Flags
&DEVICE_RUNNING
))
1993 return ALC_NO_ERROR
;
1995 al_free(device
->Uhj_Encoder
);
1996 device
->Uhj_Encoder
= NULL
;
1998 al_free(device
->Bs2b
);
1999 device
->Bs2b
= NULL
;
2001 al_free(device
->ChannelDelay
[0].Buffer
);
2002 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2004 device
->ChannelDelay
[i
].Length
= 0;
2005 device
->ChannelDelay
[i
].Buffer
= NULL
;
2008 al_free(device
->Dry
.Buffer
);
2009 device
->Dry
.Buffer
= NULL
;
2010 device
->Dry
.NumChannels
= 0;
2011 device
->FOAOut
.Buffer
= NULL
;
2012 device
->FOAOut
.NumChannels
= 0;
2013 device
->RealOut
.Buffer
= NULL
;
2014 device
->RealOut
.NumChannels
= 0;
2016 UpdateClockBase(device
);
2018 device
->DitherSeed
= DITHER_RNG_SEED
;
2020 /*************************************************************************
2021 * Update device format request if HRTF is requested
2023 device
->HrtfStatus
= ALC_HRTF_DISABLED_SOFT
;
2024 if(device
->Type
!= Loopback
)
2027 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "hrtf", &hrtf
))
2029 if(strcasecmp(hrtf
, "true") == 0)
2030 hrtf_userreq
= Hrtf_Enable
;
2031 else if(strcasecmp(hrtf
, "false") == 0)
2032 hrtf_userreq
= Hrtf_Disable
;
2033 else if(strcasecmp(hrtf
, "auto") != 0)
2034 ERR("Unexpected hrtf value: %s\n", hrtf
);
2037 if(hrtf_userreq
== Hrtf_Enable
|| (hrtf_userreq
!= Hrtf_Disable
&& hrtf_appreq
== Hrtf_Enable
))
2039 struct Hrtf
*hrtf
= NULL
;
2040 if(VECTOR_SIZE(device
->HrtfList
) == 0)
2042 VECTOR_DEINIT(device
->HrtfList
);
2043 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
2045 if(VECTOR_SIZE(device
->HrtfList
) > 0)
2047 if(hrtf_id
>= 0 && (size_t)hrtf_id
< VECTOR_SIZE(device
->HrtfList
))
2048 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, hrtf_id
).hrtf
);
2050 hrtf
= GetLoadedHrtf(VECTOR_ELEM(device
->HrtfList
, 0).hrtf
);
2055 device
->FmtChans
= DevFmtStereo
;
2056 device
->Frequency
= hrtf
->sampleRate
;
2057 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_FREQUENCY_REQUEST
;
2058 if(device
->HrtfHandle
)
2059 Hrtf_DecRef(device
->HrtfHandle
);
2060 device
->HrtfHandle
= hrtf
;
2064 hrtf_userreq
= Hrtf_Default
;
2065 hrtf_appreq
= Hrtf_Disable
;
2066 device
->HrtfStatus
= ALC_HRTF_UNSUPPORTED_FORMAT_SOFT
;
2071 oldFreq
= device
->Frequency
;
2072 oldChans
= device
->FmtChans
;
2073 oldType
= device
->FmtType
;
2075 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
2076 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"", DevFmtChannelsString(device
->FmtChans
),
2077 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"", DevFmtTypeString(device
->FmtType
),
2078 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"", device
->Frequency
,
2079 device
->UpdateSize
, device
->NumUpdates
2082 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
2083 return ALC_INVALID_DEVICE
;
2085 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
2087 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
2088 DevFmtChannelsString(device
->FmtChans
));
2089 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
2091 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
2093 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
2094 DevFmtTypeString(device
->FmtType
));
2095 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
2097 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
2099 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
2100 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
2103 if((device
->UpdateSize
&3) != 0)
2105 if((CPUCapFlags
&CPU_CAP_SSE
))
2106 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2107 if((CPUCapFlags
&CPU_CAP_NEON
))
2108 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
2111 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
2112 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
2113 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
2116 aluInitRenderer(device
, hrtf_id
, hrtf_appreq
, hrtf_userreq
);
2117 TRACE("Channel config, Dry: %d, FOA: %d, Real: %d\n", device
->Dry
.NumChannels
,
2118 device
->FOAOut
.NumChannels
, device
->RealOut
.NumChannels
);
2120 /* Allocate extra channels for any post-filter output. */
2121 size
= (device
->Dry
.NumChannels
+ device
->FOAOut
.NumChannels
+
2122 device
->RealOut
.NumChannels
)*sizeof(device
->Dry
.Buffer
[0]);
2124 TRACE("Allocating "SZFMT
" channels, "SZFMT
" bytes\n", size
/sizeof(device
->Dry
.Buffer
[0]), size
);
2125 device
->Dry
.Buffer
= al_calloc(16, size
);
2126 if(!device
->Dry
.Buffer
)
2128 ERR("Failed to allocate "SZFMT
" bytes for mix buffer\n", size
);
2129 return ALC_INVALID_DEVICE
;
2132 if(device
->RealOut
.NumChannels
!= 0)
2133 device
->RealOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
+
2134 device
->FOAOut
.NumChannels
;
2137 device
->RealOut
.Buffer
= device
->Dry
.Buffer
;
2138 device
->RealOut
.NumChannels
= device
->Dry
.NumChannels
;
2141 if(device
->FOAOut
.NumChannels
!= 0)
2142 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
+ device
->Dry
.NumChannels
;
2145 device
->FOAOut
.Buffer
= device
->Dry
.Buffer
;
2146 device
->FOAOut
.NumChannels
= device
->Dry
.NumChannels
;
2149 device
->NumAuxSends
= new_sends
;
2150 TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n",
2151 device
->SourcesMax
, device
->NumMonoSources
, device
->NumStereoSources
,
2152 device
->AuxiliaryEffectSlotMax
, device
->NumAuxSends
);
2154 device
->DitherDepth
= 0.0f
;
2155 if(GetConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "dither", 1))
2158 ConfigValueInt(alstr_get_cstr(device
->DeviceName
), NULL
, "dither-depth", &depth
);
2161 switch(device
->FmtType
)
2179 device
->DitherDepth
= (depth
> 0) ? powf(2.0f
, (ALfloat
)(depth
-1)) : 0.0f
;
2181 if(!(device
->DitherDepth
> 0.0f
))
2182 TRACE("Dithering disabled\n");
2184 TRACE("Dithering enabled (%g-bit, %g)\n", log2f(device
->DitherDepth
)+1.0f
,
2185 device
->DitherDepth
);
2187 if(ConfigValueBool(alstr_get_cstr(device
->DeviceName
), NULL
, "output-limiter", &val
))
2188 gainLimiter
= val
? ALC_TRUE
: ALC_FALSE
;
2189 /* Valid values for gainLimiter are ALC_DONT_CARE_SOFT, ALC_TRUE, and
2190 * ALC_FALSE. We default to on, so ALC_DONT_CARE_SOFT is the same as
2193 if(gainLimiter
!= ALC_FALSE
)
2195 if(!device
->Limiter
|| device
->Frequency
!= GetCompressorSampleRate(device
->Limiter
))
2197 al_free(device
->Limiter
);
2198 device
->Limiter
= CreateDeviceLimiter(device
);
2203 al_free(device
->Limiter
);
2204 device
->Limiter
= NULL
;
2206 TRACE("Output limiter %s\n", device
->Limiter
? "enabled" : "disabled");
2208 /* Need to delay returning failure until replacement Send arrays have been
2209 * allocated with the appropriate size.
2211 update_failed
= AL_FALSE
;
2213 context
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
2216 struct ALvoiceProps
*vprops
;
2219 if(context
->DefaultSlot
)
2221 ALeffectslot
*slot
= context
->DefaultSlot
;
2222 ALeffectState
*state
= slot
->Effect
.State
;
2224 state
->OutBuffer
= device
->Dry
.Buffer
;
2225 state
->OutChannels
= device
->Dry
.NumChannels
;
2226 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2227 update_failed
= AL_TRUE
;
2229 UpdateEffectSlotProps(slot
, context
);
2232 WriteLock(&context
->PropLock
);
2233 LockUIntMapRead(&context
->EffectSlotMap
);
2234 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2236 ALeffectslot
*slot
= context
->EffectSlotMap
.values
[pos
];
2237 ALeffectState
*state
= slot
->Effect
.State
;
2239 state
->OutBuffer
= device
->Dry
.Buffer
;
2240 state
->OutChannels
= device
->Dry
.NumChannels
;
2241 if(V(state
,deviceUpdate
)(device
) == AL_FALSE
)
2242 update_failed
= AL_TRUE
;
2244 UpdateEffectSlotProps(slot
, context
);
2246 UnlockUIntMapRead(&context
->EffectSlotMap
);
2248 LockUIntMapRead(&context
->SourceMap
);
2249 RelimitUIntMapNoLock(&context
->SourceMap
, device
->SourcesMax
);
2250 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2252 ALsource
*source
= context
->SourceMap
.values
[pos
];
2254 if(old_sends
!= device
->NumAuxSends
)
2256 ALvoid
*sends
= al_calloc(16, device
->NumAuxSends
*sizeof(source
->Send
[0]));
2259 memcpy(sends
, source
->Send
,
2260 mini(device
->NumAuxSends
, old_sends
)*sizeof(source
->Send
[0])
2262 for(s
= device
->NumAuxSends
;s
< old_sends
;s
++)
2264 if(source
->Send
[s
].Slot
)
2265 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2266 source
->Send
[s
].Slot
= NULL
;
2268 al_free(source
->Send
);
2269 source
->Send
= sends
;
2270 for(s
= old_sends
;s
< device
->NumAuxSends
;s
++)
2272 source
->Send
[s
].Slot
= NULL
;
2273 source
->Send
[s
].Gain
= 1.0f
;
2274 source
->Send
[s
].GainHF
= 1.0f
;
2275 source
->Send
[s
].HFReference
= LOWPASSFREQREF
;
2276 source
->Send
[s
].GainLF
= 1.0f
;
2277 source
->Send
[s
].LFReference
= HIGHPASSFREQREF
;
2281 ATOMIC_FLAG_CLEAR(&source
->PropsClean
, almemory_order_release
);
2284 /* Clear any pre-existing voice property structs, in case the number of
2285 * auxiliary sends is changing. Active sources will have updates
2286 * respecified in UpdateAllSourceProps.
2288 vprops
= ATOMIC_EXCHANGE_PTR(&context
->FreeVoiceProps
, NULL
, almemory_order_acq_rel
);
2291 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2296 AllocateVoices(context
, context
->MaxVoices
, old_sends
);
2297 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2299 ALvoice
*voice
= context
->Voices
[pos
];
2301 al_free(ATOMIC_EXCHANGE_PTR(&voice
->Update
, NULL
, almemory_order_acq_rel
));
2303 if(ATOMIC_LOAD(&voice
->Source
, almemory_order_acquire
) == NULL
)
2306 if(device
->AvgSpeakerDist
> 0.0f
)
2308 /* Reinitialize the NFC filters for new parameters. */
2309 ALfloat w1
= SPEEDOFSOUNDMETRESPERSEC
/
2310 (device
->AvgSpeakerDist
* device
->Frequency
);
2311 for(i
= 0;i
< voice
->NumChannels
;i
++)
2313 NfcFilterCreate1(&voice
->Direct
.Params
[i
].NFCtrlFilter
[0], 0.0f
, w1
);
2314 NfcFilterCreate2(&voice
->Direct
.Params
[i
].NFCtrlFilter
[1], 0.0f
, w1
);
2315 NfcFilterCreate3(&voice
->Direct
.Params
[i
].NFCtrlFilter
[2], 0.0f
, w1
);
2319 UnlockUIntMapRead(&context
->SourceMap
);
2321 ATOMIC_FLAG_TEST_AND_SET(&context
->PropsClean
, almemory_order_release
);
2322 UpdateContextProps(context
);
2323 ATOMIC_FLAG_TEST_AND_SET(&context
->Listener
->PropsClean
, almemory_order_release
);
2324 UpdateListenerProps(context
);
2325 UpdateAllSourceProps(context
);
2326 WriteUnlock(&context
->PropLock
);
2328 context
= context
->next
;
2332 return ALC_INVALID_DEVICE
;
2334 if(!(device
->Flags
&DEVICE_PAUSED
))
2336 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2337 return ALC_INVALID_DEVICE
;
2338 device
->Flags
|= DEVICE_RUNNING
;
2341 return ALC_NO_ERROR
;
2346 * Frees the device structure, and destroys any objects the app failed to
2347 * delete. Called once there's no more references on the device.
2349 static ALCvoid
FreeDevice(ALCdevice
*device
)
2353 TRACE("%p\n", device
);
2355 V0(device
->Backend
,close
)();
2356 DELETE_OBJ(device
->Backend
);
2357 device
->Backend
= NULL
;
2359 almtx_destroy(&device
->BackendLock
);
2361 if(device
->BufferMap
.size
> 0)
2363 WARN("(%p) Deleting %d Buffer%s\n", device
, device
->BufferMap
.size
,
2364 (device
->BufferMap
.size
==1)?"":"s");
2365 ReleaseALBuffers(device
);
2367 ResetUIntMap(&device
->BufferMap
);
2369 if(device
->EffectMap
.size
> 0)
2371 WARN("(%p) Deleting %d Effect%s\n", device
, device
->EffectMap
.size
,
2372 (device
->EffectMap
.size
==1)?"":"s");
2373 ReleaseALEffects(device
);
2375 ResetUIntMap(&device
->EffectMap
);
2377 if(device
->FilterMap
.size
> 0)
2379 WARN("(%p) Deleting %d Filter%s\n", device
, device
->FilterMap
.size
,
2380 (device
->FilterMap
.size
==1)?"":"s");
2381 ReleaseALFilters(device
);
2383 ResetUIntMap(&device
->FilterMap
);
2385 AL_STRING_DEINIT(device
->HrtfName
);
2386 FreeHrtfList(&device
->HrtfList
);
2387 if(device
->HrtfHandle
)
2388 Hrtf_DecRef(device
->HrtfHandle
);
2389 device
->HrtfHandle
= NULL
;
2390 al_free(device
->Hrtf
);
2391 device
->Hrtf
= NULL
;
2393 al_free(device
->Bs2b
);
2394 device
->Bs2b
= NULL
;
2396 al_free(device
->Uhj_Encoder
);
2397 device
->Uhj_Encoder
= NULL
;
2399 bformatdec_free(device
->AmbiDecoder
);
2400 device
->AmbiDecoder
= NULL
;
2402 ambiup_free(device
->AmbiUp
);
2403 device
->AmbiUp
= NULL
;
2405 al_free(device
->Stablizer
);
2406 device
->Stablizer
= NULL
;
2408 al_free(device
->Limiter
);
2409 device
->Limiter
= NULL
;
2411 al_free(device
->ChannelDelay
[0].Buffer
);
2412 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
2414 device
->ChannelDelay
[i
].Gain
= 1.0f
;
2415 device
->ChannelDelay
[i
].Length
= 0;
2416 device
->ChannelDelay
[i
].Buffer
= NULL
;
2419 AL_STRING_DEINIT(device
->DeviceName
);
2421 al_free(device
->Dry
.Buffer
);
2422 device
->Dry
.Buffer
= NULL
;
2423 device
->Dry
.NumChannels
= 0;
2424 device
->FOAOut
.Buffer
= NULL
;
2425 device
->FOAOut
.NumChannels
= 0;
2426 device
->RealOut
.Buffer
= NULL
;
2427 device
->RealOut
.NumChannels
= 0;
2433 void ALCdevice_IncRef(ALCdevice
*device
)
2436 ref
= IncrementRef(&device
->ref
);
2437 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2440 void ALCdevice_DecRef(ALCdevice
*device
)
2443 ref
= DecrementRef(&device
->ref
);
2444 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2445 if(ref
== 0) FreeDevice(device
);
2450 * Checks if the device handle is valid, and increments its ref count if so.
2452 static ALCboolean
VerifyDevice(ALCdevice
**device
)
2454 ALCdevice
*tmpDevice
;
2457 tmpDevice
= ATOMIC_LOAD_SEQ(&DeviceList
);
2460 if(tmpDevice
== *device
)
2462 ALCdevice_IncRef(tmpDevice
);
2466 tmpDevice
= tmpDevice
->next
;
2477 * Initializes context fields
2479 static ALvoid
InitContext(ALCcontext
*Context
)
2481 ALlistener
*listener
= Context
->Listener
;
2482 struct ALeffectslotArray
*auxslots
;
2484 //Initialise listener
2485 listener
->Gain
= 1.0f
;
2486 listener
->Position
[0] = 0.0f
;
2487 listener
->Position
[1] = 0.0f
;
2488 listener
->Position
[2] = 0.0f
;
2489 listener
->Velocity
[0] = 0.0f
;
2490 listener
->Velocity
[1] = 0.0f
;
2491 listener
->Velocity
[2] = 0.0f
;
2492 listener
->Forward
[0] = 0.0f
;
2493 listener
->Forward
[1] = 0.0f
;
2494 listener
->Forward
[2] = -1.0f
;
2495 listener
->Up
[0] = 0.0f
;
2496 listener
->Up
[1] = 1.0f
;
2497 listener
->Up
[2] = 0.0f
;
2498 ATOMIC_FLAG_TEST_AND_SET(&listener
->PropsClean
, almemory_order_relaxed
);
2500 ATOMIC_INIT(&listener
->Update
, NULL
);
2503 InitRef(&Context
->UpdateCount
, 0);
2504 ATOMIC_INIT(&Context
->HoldUpdates
, AL_FALSE
);
2505 Context
->GainBoost
= 1.0f
;
2506 RWLockInit(&Context
->PropLock
);
2507 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2508 InitUIntMap(&Context
->SourceMap
, Context
->Device
->SourcesMax
);
2509 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2511 if(Context
->DefaultSlot
)
2513 auxslots
= al_calloc(DEF_ALIGN
, FAM_SIZE(struct ALeffectslotArray
, slot
, 1));
2514 auxslots
->count
= 1;
2515 auxslots
->slot
[0] = Context
->DefaultSlot
;
2519 auxslots
= al_calloc(DEF_ALIGN
, sizeof(struct ALeffectslotArray
));
2520 auxslots
->count
= 0;
2522 ATOMIC_INIT(&Context
->ActiveAuxSlots
, auxslots
);
2525 Context
->DistanceModel
= DefaultDistanceModel
;
2526 Context
->SourceDistanceModel
= AL_FALSE
;
2527 Context
->DopplerFactor
= 1.0f
;
2528 Context
->DopplerVelocity
= 1.0f
;
2529 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2530 Context
->MetersPerUnit
= AL_DEFAULT_METERS_PER_UNIT
;
2531 ATOMIC_FLAG_TEST_AND_SET(&Context
->PropsClean
, almemory_order_relaxed
);
2532 ATOMIC_INIT(&Context
->DeferUpdates
, AL_FALSE
);
2534 ATOMIC_INIT(&Context
->Update
, NULL
);
2535 ATOMIC_INIT(&Context
->FreeContextProps
, NULL
);
2536 ATOMIC_INIT(&Context
->FreeListenerProps
, NULL
);
2537 ATOMIC_INIT(&Context
->FreeVoiceProps
, NULL
);
2538 ATOMIC_INIT(&Context
->FreeEffectslotProps
, NULL
);
2540 Context
->ExtensionList
= alExtList
;
2543 listener
->Params
.Matrix
= IdentityMatrixf
;
2544 aluVectorSet(&listener
->Params
.Velocity
, 0.0f
, 0.0f
, 0.0f
, 0.0f
);
2545 listener
->Params
.Gain
= listener
->Gain
;
2546 listener
->Params
.MetersPerUnit
= Context
->MetersPerUnit
;
2547 listener
->Params
.DopplerFactor
= Context
->DopplerFactor
;
2548 listener
->Params
.SpeedOfSound
= Context
->SpeedOfSound
* Context
->DopplerVelocity
;
2549 listener
->Params
.ReverbSpeedOfSound
= listener
->Params
.SpeedOfSound
*
2550 listener
->Params
.MetersPerUnit
;
2551 listener
->Params
.SourceDistanceModel
= Context
->SourceDistanceModel
;
2552 listener
->Params
.DistanceModel
= Context
->DistanceModel
;
2558 * Cleans up the context, and destroys any remaining objects the app failed to
2559 * delete. Called once there's no more references on the context.
2561 static void FreeContext(ALCcontext
*context
)
2563 ALlistener
*listener
= context
->Listener
;
2564 struct ALeffectslotArray
*auxslots
;
2565 struct ALeffectslotProps
*eprops
;
2566 struct ALlistenerProps
*lprops
;
2567 struct ALcontextProps
*cprops
;
2568 struct ALvoiceProps
*vprops
;
2572 TRACE("%p\n", context
);
2574 if((cprops
=ATOMIC_LOAD(&context
->Update
, almemory_order_acquire
)) != NULL
)
2576 TRACE("Freed unapplied context update %p\n", cprops
);
2581 cprops
= ATOMIC_LOAD(&context
->FreeContextProps
, almemory_order_acquire
);
2584 struct ALcontextProps
*next
= ATOMIC_LOAD(&cprops
->next
, almemory_order_acquire
);
2589 TRACE("Freed "SZFMT
" context property object%s\n", count
, (count
==1)?"":"s");
2591 if(context
->DefaultSlot
)
2593 DeinitEffectSlot(context
->DefaultSlot
);
2594 context
->DefaultSlot
= NULL
;
2597 auxslots
= ATOMIC_EXCHANGE_PTR(&context
->ActiveAuxSlots
, NULL
, almemory_order_relaxed
);
2600 if(context
->SourceMap
.size
> 0)
2602 WARN("(%p) Deleting %d Source%s\n", context
, context
->SourceMap
.size
,
2603 (context
->SourceMap
.size
==1)?"":"s");
2604 ReleaseALSources(context
);
2606 ResetUIntMap(&context
->SourceMap
);
2609 eprops
= ATOMIC_LOAD(&context
->FreeEffectslotProps
, almemory_order_relaxed
);
2612 struct ALeffectslotProps
*next
= ATOMIC_LOAD(&eprops
->next
, almemory_order_relaxed
);
2613 if(eprops
->State
) ALeffectState_DecRef(eprops
->State
);
2618 TRACE("Freed "SZFMT
" AuxiliaryEffectSlot property object%s\n", count
, (count
==1)?"":"s");
2619 if(context
->EffectSlotMap
.size
> 0)
2621 WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context
, context
->EffectSlotMap
.size
,
2622 (context
->EffectSlotMap
.size
==1)?"":"s");
2623 ReleaseALAuxiliaryEffectSlots(context
);
2625 ResetUIntMap(&context
->EffectSlotMap
);
2628 vprops
= ATOMIC_LOAD(&context
->FreeVoiceProps
, almemory_order_relaxed
);
2631 struct ALvoiceProps
*next
= ATOMIC_LOAD(&vprops
->next
, almemory_order_relaxed
);
2636 TRACE("Freed "SZFMT
" voice property object%s\n", count
, (count
==1)?"":"s");
2638 for(i
= 0;i
< context
->VoiceCount
;i
++)
2639 DeinitVoice(context
->Voices
[i
]);
2640 al_free(context
->Voices
);
2641 context
->Voices
= NULL
;
2642 context
->VoiceCount
= 0;
2643 context
->MaxVoices
= 0;
2645 if((lprops
=ATOMIC_LOAD(&listener
->Update
, almemory_order_acquire
)) != NULL
)
2647 TRACE("Freed unapplied listener update %p\n", lprops
);
2651 lprops
= ATOMIC_LOAD(&context
->FreeListenerProps
, almemory_order_acquire
);
2654 struct ALlistenerProps
*next
= ATOMIC_LOAD(&lprops
->next
, almemory_order_acquire
);
2659 TRACE("Freed "SZFMT
" listener property object%s\n", count
, (count
==1)?"":"s");
2661 ALCdevice_DecRef(context
->Device
);
2662 context
->Device
= NULL
;
2664 //Invalidate context
2665 memset(context
, 0, sizeof(ALCcontext
));
2671 * Removes the context reference from the given device and removes it from
2672 * being current on the running thread or globally. Returns true if other
2673 * contexts still exist on the device.
2675 static bool ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2677 ALCcontext
*origctx
, *newhead
;
2680 if(altss_get(LocalContext
) == context
)
2682 WARN("%p released while current on thread\n", context
);
2683 altss_set(LocalContext
, NULL
);
2684 ALCcontext_DecRef(context
);
2688 if(ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&GlobalContext
, &origctx
, NULL
))
2689 ALCcontext_DecRef(context
);
2691 V0(device
->Backend
,lock
)();
2693 newhead
= context
->next
;
2694 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&device
->ContextList
, &origctx
, newhead
))
2696 ALCcontext
*volatile*list
= &origctx
->next
;
2699 if(*list
== context
)
2701 *list
= (*list
)->next
;
2704 list
= &(*list
)->next
;
2709 V0(device
->Backend
,unlock
)();
2711 ALCcontext_DecRef(context
);
2715 static void ALCcontext_IncRef(ALCcontext
*context
)
2717 uint ref
= IncrementRef(&context
->ref
);
2718 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2721 void ALCcontext_DecRef(ALCcontext
*context
)
2723 uint ref
= DecrementRef(&context
->ref
);
2724 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2725 if(ref
== 0) FreeContext(context
);
2728 static void ReleaseThreadCtx(void *ptr
)
2730 ALCcontext
*context
= ptr
;
2731 uint ref
= DecrementRef(&context
->ref
);
2732 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2733 ERR("Context %p current for thread being destroyed, possible leak!\n", context
);
2738 * Checks that the given context is valid, and increments its reference count.
2740 static ALCboolean
VerifyContext(ALCcontext
**context
)
2745 dev
= ATOMIC_LOAD_SEQ(&DeviceList
);
2748 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
, almemory_order_acquire
);
2753 ALCcontext_IncRef(ctx
);
2770 * Returns the currently active context for this thread, and adds a reference
2771 * without locking it.
2773 ALCcontext
*GetContextRef(void)
2775 ALCcontext
*context
;
2777 context
= altss_get(LocalContext
);
2779 ALCcontext_IncRef(context
);
2783 context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
2785 ALCcontext_IncRef(context
);
2793 void AllocateVoices(ALCcontext
*context
, ALsizei num_voices
, ALsizei old_sends
)
2795 ALCdevice
*device
= context
->Device
;
2796 ALsizei num_sends
= device
->NumAuxSends
;
2797 struct ALvoiceProps
*props
;
2798 size_t sizeof_props
;
2799 size_t sizeof_voice
;
2805 if(num_voices
== context
->MaxVoices
&& num_sends
== old_sends
)
2808 /* Allocate the voice pointers, voices, and the voices' stored source
2809 * property set (including the dynamically-sized Send[] array) in one
2812 sizeof_voice
= RoundUp(FAM_SIZE(ALvoice
, Send
, num_sends
), 16);
2813 sizeof_props
= RoundUp(FAM_SIZE(struct ALvoiceProps
, Send
, num_sends
), 16);
2814 size
= sizeof(ALvoice
*) + sizeof_voice
+ sizeof_props
;
2816 voices
= al_calloc(16, RoundUp(size
*num_voices
, 16));
2817 /* The voice and property objects are stored interleaved since they're
2820 voice
= (ALvoice
*)((char*)voices
+ RoundUp(num_voices
*sizeof(ALvoice
*), 16));
2821 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2825 const ALsizei v_count
= mini(context
->VoiceCount
, num_voices
);
2826 const ALsizei s_count
= mini(old_sends
, num_sends
);
2828 for(;v
< v_count
;v
++)
2830 ALvoice
*old_voice
= context
->Voices
[v
];
2833 /* Copy the old voice data and source property set to the new
2836 *voice
= *old_voice
;
2837 for(i
= 0;i
< s_count
;i
++)
2838 voice
->Send
[i
] = old_voice
->Send
[i
];
2839 *props
= *(old_voice
->Props
);
2840 for(i
= 0;i
< s_count
;i
++)
2841 props
->Send
[i
] = old_voice
->Props
->Send
[i
];
2843 /* Set this voice's property set pointer and voice reference. */
2844 voice
->Props
= props
;
2847 /* Increment pointers to the next storage space. */
2848 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2849 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2851 /* Deinit any left over voices that weren't copied over to the new
2852 * array. NOTE: If this does anything, v equals num_voices and
2853 * num_voices is less than VoiceCount, so the following loop won't do
2856 for(;v
< context
->VoiceCount
;v
++)
2857 DeinitVoice(context
->Voices
[v
]);
2859 /* Finish setting the voices' property set pointers and references. */
2860 for(;v
< num_voices
;v
++)
2862 ATOMIC_INIT(&voice
->Update
, NULL
);
2864 voice
->Props
= props
;
2867 voice
= (ALvoice
*)((char*)props
+ sizeof_props
);
2868 props
= (struct ALvoiceProps
*)((char*)voice
+ sizeof_voice
);
2871 al_free(context
->Voices
);
2872 context
->Voices
= voices
;
2873 context
->MaxVoices
= num_voices
;
2874 context
->VoiceCount
= mini(context
->VoiceCount
, num_voices
);
2878 /************************************************
2879 * Standard ALC functions
2880 ************************************************/
2884 * Return last ALC generated error code for the given device
2886 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2890 if(VerifyDevice(&device
))
2892 errorCode
= ATOMIC_EXCHANGE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
2893 ALCdevice_DecRef(device
);
2896 errorCode
= ATOMIC_EXCHANGE_SEQ(&LastNullDeviceError
, ALC_NO_ERROR
);
2902 /* alcSuspendContext
2904 * Suspends updates for the given context
2906 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2911 if(!VerifyContext(&context
))
2912 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2915 ALCcontext_DeferUpdates(context
);
2916 ALCcontext_DecRef(context
);
2920 /* alcProcessContext
2922 * Resumes processing updates for the given context
2924 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2929 if(!VerifyContext(&context
))
2930 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2933 ALCcontext_ProcessUpdates(context
);
2934 ALCcontext_DecRef(context
);
2941 * Returns information about the device, and error strings
2943 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2945 const ALCchar
*value
= NULL
;
2953 case ALC_INVALID_ENUM
:
2954 value
= alcErrInvalidEnum
;
2957 case ALC_INVALID_VALUE
:
2958 value
= alcErrInvalidValue
;
2961 case ALC_INVALID_DEVICE
:
2962 value
= alcErrInvalidDevice
;
2965 case ALC_INVALID_CONTEXT
:
2966 value
= alcErrInvalidContext
;
2969 case ALC_OUT_OF_MEMORY
:
2970 value
= alcErrOutOfMemory
;
2973 case ALC_DEVICE_SPECIFIER
:
2974 value
= alcDefaultName
;
2977 case ALC_ALL_DEVICES_SPECIFIER
:
2978 if(VerifyDevice(&Device
))
2980 value
= alstr_get_cstr(Device
->DeviceName
);
2981 ALCdevice_DecRef(Device
);
2985 ProbeAllDevicesList();
2986 value
= alstr_get_cstr(alcAllDevicesList
);
2990 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2991 if(VerifyDevice(&Device
))
2993 value
= alstr_get_cstr(Device
->DeviceName
);
2994 ALCdevice_DecRef(Device
);
2998 ProbeCaptureDeviceList();
2999 value
= alstr_get_cstr(alcCaptureDeviceList
);
3003 /* Default devices are always first in the list */
3004 case ALC_DEFAULT_DEVICE_SPECIFIER
:
3005 value
= alcDefaultName
;
3008 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
3009 if(alstr_empty(alcAllDevicesList
))
3010 ProbeAllDevicesList();
3012 VerifyDevice(&Device
);
3014 free(alcDefaultAllDevicesSpecifier
);
3015 alcDefaultAllDevicesSpecifier
= strdup(alstr_get_cstr(alcAllDevicesList
));
3016 if(!alcDefaultAllDevicesSpecifier
)
3017 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3019 value
= alcDefaultAllDevicesSpecifier
;
3020 if(Device
) ALCdevice_DecRef(Device
);
3023 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
3024 if(alstr_empty(alcCaptureDeviceList
))
3025 ProbeCaptureDeviceList();
3027 VerifyDevice(&Device
);
3029 free(alcCaptureDefaultDeviceSpecifier
);
3030 alcCaptureDefaultDeviceSpecifier
= strdup(alstr_get_cstr(alcCaptureDeviceList
));
3031 if(!alcCaptureDefaultDeviceSpecifier
)
3032 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
3034 value
= alcCaptureDefaultDeviceSpecifier
;
3035 if(Device
) ALCdevice_DecRef(Device
);
3038 case ALC_EXTENSIONS
:
3039 if(!VerifyDevice(&Device
))
3040 value
= alcNoDeviceExtList
;
3043 value
= alcExtensionList
;
3044 ALCdevice_DecRef(Device
);
3048 case ALC_HRTF_SPECIFIER_SOFT
:
3049 if(!VerifyDevice(&Device
))
3050 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3053 almtx_lock(&Device
->BackendLock
);
3054 value
= (Device
->HrtfHandle
? alstr_get_cstr(Device
->HrtfName
) : "");
3055 almtx_unlock(&Device
->BackendLock
);
3056 ALCdevice_DecRef(Device
);
3061 VerifyDevice(&Device
);
3062 alcSetError(Device
, ALC_INVALID_ENUM
);
3063 if(Device
) ALCdevice_DecRef(Device
);
3071 static inline ALCsizei
NumAttrsForDevice(ALCdevice
*device
)
3073 if(device
->Type
== Capture
) return 9;
3074 if(device
->Type
!= Loopback
) return 29;
3075 if(device
->FmtChans
== DevFmtAmbi3D
)
3080 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3084 if(size
<= 0 || values
== NULL
)
3086 alcSetError(device
, ALC_INVALID_VALUE
);
3094 case ALC_MAJOR_VERSION
:
3095 values
[0] = alcMajorVersion
;
3097 case ALC_MINOR_VERSION
:
3098 values
[0] = alcMinorVersion
;
3101 case ALC_ATTRIBUTES_SIZE
:
3102 case ALC_ALL_ATTRIBUTES
:
3106 case ALC_MONO_SOURCES
:
3107 case ALC_STEREO_SOURCES
:
3108 case ALC_CAPTURE_SAMPLES
:
3109 case ALC_FORMAT_CHANNELS_SOFT
:
3110 case ALC_FORMAT_TYPE_SOFT
:
3111 case ALC_AMBISONIC_LAYOUT_SOFT
:
3112 case ALC_AMBISONIC_SCALING_SOFT
:
3113 case ALC_AMBISONIC_ORDER_SOFT
:
3114 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3115 alcSetError(NULL
, ALC_INVALID_DEVICE
);
3119 alcSetError(NULL
, ALC_INVALID_ENUM
);
3125 if(device
->Type
== Capture
)
3129 case ALC_ATTRIBUTES_SIZE
:
3130 values
[0] = NumAttrsForDevice(device
);
3133 case ALC_ALL_ATTRIBUTES
:
3134 if(size
< NumAttrsForDevice(device
))
3136 alcSetError(device
, ALC_INVALID_VALUE
);
3141 almtx_lock(&device
->BackendLock
);
3142 values
[i
++] = ALC_MAJOR_VERSION
;
3143 values
[i
++] = alcMajorVersion
;
3144 values
[i
++] = ALC_MINOR_VERSION
;
3145 values
[i
++] = alcMinorVersion
;
3146 values
[i
++] = ALC_CAPTURE_SAMPLES
;
3147 values
[i
++] = V0(device
->Backend
,availableSamples
)();
3148 values
[i
++] = ALC_CONNECTED
;
3149 values
[i
++] = device
->Connected
;
3150 almtx_unlock(&device
->BackendLock
);
3155 case ALC_MAJOR_VERSION
:
3156 values
[0] = alcMajorVersion
;
3158 case ALC_MINOR_VERSION
:
3159 values
[0] = alcMinorVersion
;
3162 case ALC_CAPTURE_SAMPLES
:
3163 almtx_lock(&device
->BackendLock
);
3164 values
[0] = V0(device
->Backend
,availableSamples
)();
3165 almtx_unlock(&device
->BackendLock
);
3169 values
[0] = device
->Connected
;
3173 alcSetError(device
, ALC_INVALID_ENUM
);
3182 case ALC_ATTRIBUTES_SIZE
:
3183 values
[0] = NumAttrsForDevice(device
);
3186 case ALC_ALL_ATTRIBUTES
:
3187 if(size
< NumAttrsForDevice(device
))
3189 alcSetError(device
, ALC_INVALID_VALUE
);
3194 almtx_lock(&device
->BackendLock
);
3195 values
[i
++] = ALC_MAJOR_VERSION
;
3196 values
[i
++] = alcMajorVersion
;
3197 values
[i
++] = ALC_MINOR_VERSION
;
3198 values
[i
++] = alcMinorVersion
;
3199 values
[i
++] = ALC_EFX_MAJOR_VERSION
;
3200 values
[i
++] = alcEFXMajorVersion
;
3201 values
[i
++] = ALC_EFX_MINOR_VERSION
;
3202 values
[i
++] = alcEFXMinorVersion
;
3204 values
[i
++] = ALC_FREQUENCY
;
3205 values
[i
++] = device
->Frequency
;
3206 if(device
->Type
!= Loopback
)
3208 values
[i
++] = ALC_REFRESH
;
3209 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3211 values
[i
++] = ALC_SYNC
;
3212 values
[i
++] = ALC_FALSE
;
3216 if(device
->FmtChans
== DevFmtAmbi3D
)
3218 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3219 values
[i
++] = device
->AmbiLayout
;
3221 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3222 values
[i
++] = device
->AmbiScale
;
3224 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3225 values
[i
++] = device
->AmbiOrder
;
3228 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3229 values
[i
++] = device
->FmtChans
;
3231 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3232 values
[i
++] = device
->FmtType
;
3235 values
[i
++] = ALC_MONO_SOURCES
;
3236 values
[i
++] = device
->NumMonoSources
;
3238 values
[i
++] = ALC_STEREO_SOURCES
;
3239 values
[i
++] = device
->NumStereoSources
;
3241 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3242 values
[i
++] = device
->NumAuxSends
;
3244 values
[i
++] = ALC_HRTF_SOFT
;
3245 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3247 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3248 values
[i
++] = device
->HrtfStatus
;
3250 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3251 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3253 values
[i
++] = ALC_MAX_AMBISONIC_ORDER_SOFT
;
3254 values
[i
++] = MAX_AMBI_ORDER
;
3255 almtx_unlock(&device
->BackendLock
);
3260 case ALC_MAJOR_VERSION
:
3261 values
[0] = alcMajorVersion
;
3264 case ALC_MINOR_VERSION
:
3265 values
[0] = alcMinorVersion
;
3268 case ALC_EFX_MAJOR_VERSION
:
3269 values
[0] = alcEFXMajorVersion
;
3272 case ALC_EFX_MINOR_VERSION
:
3273 values
[0] = alcEFXMinorVersion
;
3277 values
[0] = device
->Frequency
;
3281 if(device
->Type
== Loopback
)
3283 alcSetError(device
, ALC_INVALID_DEVICE
);
3286 almtx_lock(&device
->BackendLock
);
3287 values
[0] = device
->Frequency
/ device
->UpdateSize
;
3288 almtx_unlock(&device
->BackendLock
);
3292 if(device
->Type
== Loopback
)
3294 alcSetError(device
, ALC_INVALID_DEVICE
);
3297 values
[0] = ALC_FALSE
;
3300 case ALC_FORMAT_CHANNELS_SOFT
:
3301 if(device
->Type
!= Loopback
)
3303 alcSetError(device
, ALC_INVALID_DEVICE
);
3306 values
[0] = device
->FmtChans
;
3309 case ALC_FORMAT_TYPE_SOFT
:
3310 if(device
->Type
!= Loopback
)
3312 alcSetError(device
, ALC_INVALID_DEVICE
);
3315 values
[0] = device
->FmtType
;
3318 case ALC_AMBISONIC_LAYOUT_SOFT
:
3319 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3321 alcSetError(device
, ALC_INVALID_DEVICE
);
3324 values
[0] = device
->AmbiLayout
;
3327 case ALC_AMBISONIC_SCALING_SOFT
:
3328 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3330 alcSetError(device
, ALC_INVALID_DEVICE
);
3333 values
[0] = device
->AmbiScale
;
3336 case ALC_AMBISONIC_ORDER_SOFT
:
3337 if(device
->Type
!= Loopback
|| device
->FmtChans
!= DevFmtAmbi3D
)
3339 alcSetError(device
, ALC_INVALID_DEVICE
);
3342 values
[0] = device
->AmbiOrder
;
3345 case ALC_MONO_SOURCES
:
3346 values
[0] = device
->NumMonoSources
;
3349 case ALC_STEREO_SOURCES
:
3350 values
[0] = device
->NumStereoSources
;
3353 case ALC_MAX_AUXILIARY_SENDS
:
3354 values
[0] = device
->NumAuxSends
;
3358 values
[0] = device
->Connected
;
3362 values
[0] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3365 case ALC_HRTF_STATUS_SOFT
:
3366 values
[0] = device
->HrtfStatus
;
3369 case ALC_NUM_HRTF_SPECIFIERS_SOFT
:
3370 almtx_lock(&device
->BackendLock
);
3371 FreeHrtfList(&device
->HrtfList
);
3372 device
->HrtfList
= EnumerateHrtf(device
->DeviceName
);
3373 values
[0] = (ALCint
)VECTOR_SIZE(device
->HrtfList
);
3374 almtx_unlock(&device
->BackendLock
);
3377 case ALC_OUTPUT_LIMITER_SOFT
:
3378 values
[0] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3381 case ALC_MAX_AMBISONIC_ORDER_SOFT
:
3382 values
[0] = MAX_AMBI_ORDER
;
3386 alcSetError(device
, ALC_INVALID_ENUM
);
3394 * Returns information about the device and the version of OpenAL
3396 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
3398 VerifyDevice(&device
);
3399 if(size
<= 0 || values
== NULL
)
3400 alcSetError(device
, ALC_INVALID_VALUE
);
3402 GetIntegerv(device
, param
, size
, values
);
3403 if(device
) ALCdevice_DecRef(device
);
3406 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
3411 VerifyDevice(&device
);
3412 if(size
<= 0 || values
== NULL
)
3413 alcSetError(device
, ALC_INVALID_VALUE
);
3414 else if(!device
|| device
->Type
== Capture
)
3416 ivals
= malloc(size
* sizeof(ALCint
));
3417 size
= GetIntegerv(device
, pname
, size
, ivals
);
3418 for(i
= 0;i
< size
;i
++)
3419 values
[i
] = ivals
[i
];
3422 else /* render device */
3431 case ALC_ATTRIBUTES_SIZE
:
3432 *values
= NumAttrsForDevice(device
)+4;
3435 case ALC_ALL_ATTRIBUTES
:
3436 if(size
< NumAttrsForDevice(device
)+4)
3437 alcSetError(device
, ALC_INVALID_VALUE
);
3441 almtx_lock(&device
->BackendLock
);
3442 values
[i
++] = ALC_FREQUENCY
;
3443 values
[i
++] = device
->Frequency
;
3445 if(device
->Type
!= Loopback
)
3447 values
[i
++] = ALC_REFRESH
;
3448 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
3450 values
[i
++] = ALC_SYNC
;
3451 values
[i
++] = ALC_FALSE
;
3455 if(device
->FmtChans
== DevFmtAmbi3D
)
3457 values
[i
++] = ALC_AMBISONIC_LAYOUT_SOFT
;
3458 values
[i
++] = device
->AmbiLayout
;
3460 values
[i
++] = ALC_AMBISONIC_SCALING_SOFT
;
3461 values
[i
++] = device
->AmbiScale
;
3463 values
[i
++] = ALC_AMBISONIC_ORDER_SOFT
;
3464 values
[i
++] = device
->AmbiOrder
;
3467 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
3468 values
[i
++] = device
->FmtChans
;
3470 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
3471 values
[i
++] = device
->FmtType
;
3474 values
[i
++] = ALC_MONO_SOURCES
;
3475 values
[i
++] = device
->NumMonoSources
;
3477 values
[i
++] = ALC_STEREO_SOURCES
;
3478 values
[i
++] = device
->NumStereoSources
;
3480 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
3481 values
[i
++] = device
->NumAuxSends
;
3483 values
[i
++] = ALC_HRTF_SOFT
;
3484 values
[i
++] = (device
->HrtfHandle
? ALC_TRUE
: ALC_FALSE
);
3486 values
[i
++] = ALC_HRTF_STATUS_SOFT
;
3487 values
[i
++] = device
->HrtfStatus
;
3489 values
[i
++] = ALC_OUTPUT_LIMITER_SOFT
;
3490 values
[i
++] = device
->Limiter
? ALC_TRUE
: ALC_FALSE
;
3492 clock
= V0(device
->Backend
,getClockLatency
)();
3493 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
3494 values
[i
++] = clock
.ClockTime
;
3496 values
[i
++] = ALC_DEVICE_LATENCY_SOFT
;
3497 values
[i
++] = clock
.Latency
;
3498 almtx_unlock(&device
->BackendLock
);
3504 case ALC_DEVICE_CLOCK_SOFT
:
3505 almtx_lock(&device
->BackendLock
);
3507 while(((refcount
=ReadRef(&device
->MixCount
))&1) != 0)
3509 basecount
= device
->ClockBase
;
3510 samplecount
= device
->SamplesDone
;
3511 } while(refcount
!= ReadRef(&device
->MixCount
));
3512 *values
= basecount
+ (samplecount
*DEVICE_CLOCK_RES
/device
->Frequency
);
3513 almtx_unlock(&device
->BackendLock
);
3516 case ALC_DEVICE_LATENCY_SOFT
:
3517 almtx_lock(&device
->BackendLock
);
3518 clock
= V0(device
->Backend
,getClockLatency
)();
3519 almtx_unlock(&device
->BackendLock
);
3520 *values
= clock
.Latency
;
3523 case ALC_DEVICE_CLOCK_LATENCY_SOFT
:
3525 alcSetError(device
, ALC_INVALID_VALUE
);
3528 almtx_lock(&device
->BackendLock
);
3529 clock
= V0(device
->Backend
,getClockLatency
)();
3530 almtx_unlock(&device
->BackendLock
);
3531 values
[0] = clock
.ClockTime
;
3532 values
[1] = clock
.Latency
;
3537 ivals
= malloc(size
* sizeof(ALCint
));
3538 size
= GetIntegerv(device
, pname
, size
, ivals
);
3539 for(i
= 0;i
< size
;i
++)
3540 values
[i
] = ivals
[i
];
3546 ALCdevice_DecRef(device
);
3550 /* alcIsExtensionPresent
3552 * Determines if there is support for a particular extension
3554 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
3556 ALCboolean bResult
= ALC_FALSE
;
3558 VerifyDevice(&device
);
3561 alcSetError(device
, ALC_INVALID_VALUE
);
3564 size_t len
= strlen(extName
);
3565 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
3568 if(strncasecmp(ptr
, extName
, len
) == 0 &&
3569 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
3574 if((ptr
=strchr(ptr
, ' ')) != NULL
)
3578 } while(isspace(*ptr
));
3583 ALCdevice_DecRef(device
);
3588 /* alcGetProcAddress
3590 * Retrieves the function address for a particular extension function
3592 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
3594 ALCvoid
*ptr
= NULL
;
3598 VerifyDevice(&device
);
3599 alcSetError(device
, ALC_INVALID_VALUE
);
3600 if(device
) ALCdevice_DecRef(device
);
3605 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
3607 if(strcmp(alcFunctions
[i
].funcName
, funcName
) == 0)
3609 ptr
= alcFunctions
[i
].address
;
3621 * Get the value for a particular ALC enumeration name
3623 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
3629 VerifyDevice(&device
);
3630 alcSetError(device
, ALC_INVALID_VALUE
);
3631 if(device
) ALCdevice_DecRef(device
);
3636 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
3638 if(strcmp(alcEnumerations
[i
].enumName
, enumName
) == 0)
3640 val
= alcEnumerations
[i
].value
;
3652 * Create and attach a context to the given device.
3654 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
3656 ALCcontext
*ALContext
;
3660 /* Explicitly hold the list lock while taking the BackendLock in case the
3661 * device is asynchronously destropyed, to ensure this new context is
3662 * properly cleaned up after being made.
3665 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
3668 alcSetError(device
, ALC_INVALID_DEVICE
);
3669 if(device
) ALCdevice_DecRef(device
);
3672 almtx_lock(&device
->BackendLock
);
3675 ATOMIC_STORE_SEQ(&device
->LastError
, ALC_NO_ERROR
);
3677 if(device
->Type
== Playback
&& DefaultEffect
.type
!= AL_EFFECT_NULL
)
3678 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
)+sizeof(ALeffectslot
));
3680 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3683 almtx_unlock(&device
->BackendLock
);
3685 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3686 ALCdevice_DecRef(device
);
3690 InitRef(&ALContext
->ref
, 1);
3691 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3692 ALContext
->DefaultSlot
= NULL
;
3694 ALContext
->Voices
= NULL
;
3695 ALContext
->VoiceCount
= 0;
3696 ALContext
->MaxVoices
= 0;
3697 ATOMIC_INIT(&ALContext
->ActiveAuxSlots
, NULL
);
3698 ALContext
->Device
= device
;
3700 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3702 almtx_unlock(&device
->BackendLock
);
3707 alcSetError(device
, err
);
3708 if(err
== ALC_INVALID_DEVICE
)
3710 V0(device
->Backend
,lock
)();
3711 aluHandleDisconnect(device
);
3712 V0(device
->Backend
,unlock
)();
3714 ALCdevice_DecRef(device
);
3717 AllocateVoices(ALContext
, 256, device
->NumAuxSends
);
3719 if(DefaultEffect
.type
!= AL_EFFECT_NULL
&& device
->Type
== Playback
)
3721 ALContext
->DefaultSlot
= (ALeffectslot
*)(ALContext
->_listener_mem
+ sizeof(ALlistener
));
3722 if(InitEffectSlot(ALContext
->DefaultSlot
) == AL_NO_ERROR
)
3723 aluInitEffectPanning(ALContext
->DefaultSlot
);
3726 ALContext
->DefaultSlot
= NULL
;
3727 ERR("Failed to initialize the default effect slot\n");
3731 ALCdevice_IncRef(ALContext
->Device
);
3732 InitContext(ALContext
);
3734 if(ConfigValueFloat(alstr_get_cstr(device
->DeviceName
), NULL
, "volume-adjust", &valf
))
3737 ERR("volume-adjust must be finite: %f\n", valf
);
3740 ALfloat db
= clampf(valf
, -24.0f
, 24.0f
);
3742 WARN("volume-adjust clamped: %f, range: +/-%f\n", valf
, 24.0f
);
3743 ALContext
->GainBoost
= powf(10.0f
, db
/20.0f
);
3744 TRACE("volume-adjust gain: %f\n", ALContext
->GainBoost
);
3747 UpdateListenerProps(ALContext
);
3750 ALCcontext
*head
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
3752 ALContext
->next
= head
;
3753 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&device
->ContextList
, &head
,
3756 almtx_unlock(&device
->BackendLock
);
3758 if(ALContext
->DefaultSlot
)
3760 if(InitializeEffect(ALContext
, ALContext
->DefaultSlot
, &DefaultEffect
) == AL_NO_ERROR
)
3761 UpdateEffectSlotProps(ALContext
->DefaultSlot
, ALContext
);
3763 ERR("Failed to initialize the default effect\n");
3766 ALCdevice_DecRef(device
);
3768 TRACE("Created context %p\n", ALContext
);
3772 /* alcDestroyContext
3774 * Remove a context from its device
3776 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3781 if(!VerifyContext(&context
))
3784 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3788 Device
= context
->Device
;
3791 almtx_lock(&Device
->BackendLock
);
3792 if(!ReleaseContext(context
, Device
))
3794 V0(Device
->Backend
,stop
)();
3795 Device
->Flags
&= ~DEVICE_RUNNING
;
3797 almtx_unlock(&Device
->BackendLock
);
3801 ALCcontext_DecRef(context
);
3805 /* alcGetCurrentContext
3807 * Returns the currently active context on the calling thread
3809 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3811 ALCcontext
*Context
= altss_get(LocalContext
);
3812 if(!Context
) Context
= ATOMIC_LOAD_SEQ(&GlobalContext
);
3816 /* alcGetThreadContext
3818 * Returns the currently active thread-local context
3820 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3822 return altss_get(LocalContext
);
3826 /* alcMakeContextCurrent
3828 * Makes the given context the active process-wide context, and removes the
3829 * thread-local context for the calling thread.
3831 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3833 /* context must be valid or NULL */
3834 if(context
&& !VerifyContext(&context
))
3836 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3839 /* context's reference count is already incremented */
3840 context
= ATOMIC_EXCHANGE_PTR_SEQ(&GlobalContext
, context
);
3841 if(context
) ALCcontext_DecRef(context
);
3843 if((context
=altss_get(LocalContext
)) != NULL
)
3845 altss_set(LocalContext
, NULL
);
3846 ALCcontext_DecRef(context
);
3852 /* alcSetThreadContext
3854 * Makes the given context the active context for the current thread
3856 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3860 /* context must be valid or NULL */
3861 if(context
&& !VerifyContext(&context
))
3863 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3866 /* context's reference count is already incremented */
3867 old
= altss_get(LocalContext
);
3868 altss_set(LocalContext
, context
);
3869 if(old
) ALCcontext_DecRef(old
);
3875 /* alcGetContextsDevice
3877 * Returns the device that a particular context is attached to
3879 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3883 if(!VerifyContext(&Context
))
3885 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3888 Device
= Context
->Device
;
3889 ALCcontext_DecRef(Context
);
3897 * Opens the named device.
3899 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3901 ALCbackendFactory
*factory
;
3909 if(!PlaybackBackend
.name
)
3911 alcSetError(NULL
, ALC_INVALID_VALUE
);
3915 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0
3917 /* Some old Windows apps hardcode these expecting OpenAL to use a
3918 * specific audio API, even when they're not enumerated. Creative's
3919 * router effectively ignores them too.
3921 || strcasecmp(deviceName
, "DirectSound3D") == 0 || strcasecmp(deviceName
, "DirectSound") == 0
3922 || strcasecmp(deviceName
, "MMSYSTEM") == 0
3927 device
= al_calloc(16, sizeof(ALCdevice
));
3930 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3935 InitRef(&device
->ref
, 1);
3936 device
->Connected
= ALC_TRUE
;
3937 device
->Type
= Playback
;
3938 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3941 device
->Bs2b
= NULL
;
3942 device
->Uhj_Encoder
= NULL
;
3943 device
->Hrtf
= NULL
;
3944 device
->HrtfHandle
= NULL
;
3945 VECTOR_INIT(device
->HrtfList
);
3946 AL_STRING_INIT(device
->HrtfName
);
3947 device
->Render_Mode
= NormalRender
;
3948 AL_STRING_INIT(device
->DeviceName
);
3949 device
->Dry
.Buffer
= NULL
;
3950 device
->Dry
.NumChannels
= 0;
3951 device
->FOAOut
.Buffer
= NULL
;
3952 device
->FOAOut
.NumChannels
= 0;
3953 device
->RealOut
.Buffer
= NULL
;
3954 device
->RealOut
.NumChannels
= 0;
3955 device
->Limiter
= NULL
;
3956 device
->AvgSpeakerDist
= 0.0f
;
3958 ATOMIC_INIT(&device
->ContextList
, NULL
);
3960 device
->ClockBase
= 0;
3961 device
->SamplesDone
= 0;
3963 device
->SourcesMax
= 256;
3964 device
->AuxiliaryEffectSlotMax
= 64;
3965 device
->NumAuxSends
= DEFAULT_SENDS
;
3967 InitUIntMap(&device
->BufferMap
, INT_MAX
);
3968 InitUIntMap(&device
->EffectMap
, INT_MAX
);
3969 InitUIntMap(&device
->FilterMap
, INT_MAX
);
3971 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
3973 device
->ChannelDelay
[i
].Gain
= 1.0f
;
3974 device
->ChannelDelay
[i
].Length
= 0;
3975 device
->ChannelDelay
[i
].Buffer
= NULL
;
3979 device
->FmtChans
= DevFmtChannelsDefault
;
3980 device
->FmtType
= DevFmtTypeDefault
;
3981 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3982 device
->IsHeadphones
= AL_FALSE
;
3983 device
->AmbiLayout
= AmbiLayout_Default
;
3984 device
->AmbiScale
= AmbiNorm_Default
;
3985 device
->NumUpdates
= 3;
3986 device
->UpdateSize
= 1024;
3988 factory
= PlaybackBackend
.getFactory();
3989 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3990 if(!device
->Backend
)
3993 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3998 if(ConfigValueStr(deviceName
, NULL
, "channels", &fmt
))
4000 static const struct {
4001 const char name
[16];
4002 enum DevFmtChannels chans
;
4005 { "mono", DevFmtMono
, 0 },
4006 { "stereo", DevFmtStereo
, 0 },
4007 { "quad", DevFmtQuad
, 0 },
4008 { "surround51", DevFmtX51
, 0 },
4009 { "surround61", DevFmtX61
, 0 },
4010 { "surround71", DevFmtX71
, 0 },
4011 { "surround51rear", DevFmtX51Rear
, 0 },
4012 { "ambi1", DevFmtAmbi3D
, 1 },
4013 { "ambi2", DevFmtAmbi3D
, 2 },
4014 { "ambi3", DevFmtAmbi3D
, 3 },
4018 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
4020 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
4022 device
->FmtChans
= chanlist
[i
].chans
;
4023 device
->AmbiOrder
= chanlist
[i
].order
;
4024 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
4028 if(i
== COUNTOF(chanlist
))
4029 ERR("Unsupported channels: %s\n", fmt
);
4031 if(ConfigValueStr(deviceName
, NULL
, "sample-type", &fmt
))
4033 static const struct {
4034 const char name
[16];
4035 enum DevFmtType type
;
4037 { "int8", DevFmtByte
},
4038 { "uint8", DevFmtUByte
},
4039 { "int16", DevFmtShort
},
4040 { "uint16", DevFmtUShort
},
4041 { "int32", DevFmtInt
},
4042 { "uint32", DevFmtUInt
},
4043 { "float32", DevFmtFloat
},
4047 for(i
= 0;i
< COUNTOF(typelist
);i
++)
4049 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
4051 device
->FmtType
= typelist
[i
].type
;
4052 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
4056 if(i
== COUNTOF(typelist
))
4057 ERR("Unsupported sample-type: %s\n", fmt
);
4060 if(ConfigValueUInt(deviceName
, NULL
, "frequency", &device
->Frequency
))
4062 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4063 if(device
->Frequency
< MIN_OUTPUT_RATE
)
4064 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
4065 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
4068 ConfigValueUInt(deviceName
, NULL
, "periods", &device
->NumUpdates
);
4069 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
4071 ConfigValueUInt(deviceName
, NULL
, "period_size", &device
->UpdateSize
);
4072 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
4073 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
4074 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
4076 ConfigValueUInt(deviceName
, NULL
, "sources", &device
->SourcesMax
);
4077 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4079 ConfigValueUInt(deviceName
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4080 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4082 if(ConfigValueInt(deviceName
, NULL
, "sends", &device
->NumAuxSends
))
4083 device
->NumAuxSends
= clampi(
4084 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4087 device
->NumStereoSources
= 1;
4088 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4090 // Find a playback device to open
4091 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4093 DELETE_OBJ(device
->Backend
);
4095 alcSetError(NULL
, err
);
4098 almtx_init(&device
->BackendLock
, almtx_plain
);
4100 if(ConfigValueStr(alstr_get_cstr(device
->DeviceName
), NULL
, "ambi-format", &fmt
))
4102 if(strcasecmp(fmt
, "fuma") == 0)
4104 device
->AmbiLayout
= AmbiLayout_FuMa
;
4105 device
->AmbiScale
= AmbiNorm_FuMa
;
4107 else if(strcasecmp(fmt
, "acn+sn3d") == 0)
4109 device
->AmbiLayout
= AmbiLayout_ACN
;
4110 device
->AmbiScale
= AmbiNorm_SN3D
;
4112 else if(strcasecmp(fmt
, "acn+n3d") == 0)
4114 device
->AmbiLayout
= AmbiLayout_ACN
;
4115 device
->AmbiScale
= AmbiNorm_N3D
;
4118 ERR("Unsupported ambi-format: %s\n", fmt
);
4121 device
->Limiter
= CreateDeviceLimiter(device
);
4124 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4126 device
->next
= head
;
4127 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4130 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4136 * Closes the given device.
4138 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
4140 ALCdevice
*iter
, *origdev
;
4144 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4148 } while((iter
=iter
->next
) != NULL
);
4149 if(!iter
|| iter
->Type
== Capture
)
4151 alcSetError(iter
, ALC_INVALID_DEVICE
);
4155 almtx_lock(&device
->BackendLock
);
4158 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4160 ALCdevice
*volatile*list
= &origdev
->next
;
4165 *list
= (*list
)->next
;
4168 list
= &(*list
)->next
;
4173 ctx
= ATOMIC_LOAD_SEQ(&device
->ContextList
);
4176 ALCcontext
*next
= ctx
->next
;
4177 WARN("Releasing context %p\n", ctx
);
4178 ReleaseContext(ctx
, device
);
4181 if((device
->Flags
&DEVICE_RUNNING
))
4182 V0(device
->Backend
,stop
)();
4183 device
->Flags
&= ~DEVICE_RUNNING
;
4184 almtx_unlock(&device
->BackendLock
);
4186 ALCdevice_DecRef(device
);
4192 /************************************************
4193 * ALC capture functions
4194 ************************************************/
4195 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
4197 ALCbackendFactory
*factory
;
4198 ALCdevice
*device
= NULL
;
4204 if(!CaptureBackend
.name
)
4206 alcSetError(NULL
, ALC_INVALID_VALUE
);
4212 alcSetError(NULL
, ALC_INVALID_VALUE
);
4216 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
4219 device
= al_calloc(16, sizeof(ALCdevice
));
4222 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4227 InitRef(&device
->ref
, 1);
4228 device
->Connected
= ALC_TRUE
;
4229 device
->Type
= Capture
;
4231 device
->Hrtf
= NULL
;
4232 device
->HrtfHandle
= NULL
;
4233 VECTOR_INIT(device
->HrtfList
);
4234 AL_STRING_INIT(device
->HrtfName
);
4236 AL_STRING_INIT(device
->DeviceName
);
4237 device
->Dry
.Buffer
= NULL
;
4238 device
->Dry
.NumChannels
= 0;
4239 device
->FOAOut
.Buffer
= NULL
;
4240 device
->FOAOut
.NumChannels
= 0;
4241 device
->RealOut
.Buffer
= NULL
;
4242 device
->RealOut
.NumChannels
= 0;
4244 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4245 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4246 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4248 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4250 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4251 device
->ChannelDelay
[i
].Length
= 0;
4252 device
->ChannelDelay
[i
].Buffer
= NULL
;
4255 factory
= CaptureBackend
.getFactory();
4256 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
4257 if(!device
->Backend
)
4260 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4264 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
4265 device
->Frequency
= frequency
;
4267 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
4268 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
4271 alcSetError(NULL
, ALC_INVALID_ENUM
);
4274 device
->IsHeadphones
= AL_FALSE
;
4275 device
->AmbiOrder
= 0;
4276 device
->AmbiLayout
= AmbiLayout_Default
;
4277 device
->AmbiScale
= AmbiNorm_Default
;
4279 device
->UpdateSize
= samples
;
4280 device
->NumUpdates
= 1;
4282 TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
4283 DevFmtChannelsString(device
->FmtChans
), DevFmtTypeString(device
->FmtType
),
4284 device
->Frequency
, device
->UpdateSize
, device
->NumUpdates
4286 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
4289 alcSetError(NULL
, err
);
4292 almtx_init(&device
->BackendLock
, almtx_plain
);
4295 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4297 device
->next
= head
;
4298 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4301 TRACE("Created device %p, \"%s\"\n", device
, alstr_get_cstr(device
->DeviceName
));
4305 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
4307 ALCdevice
*iter
, *origdev
;
4310 iter
= ATOMIC_LOAD_SEQ(&DeviceList
);
4314 } while((iter
=iter
->next
) != NULL
);
4315 if(!iter
|| iter
->Type
!= Capture
)
4317 alcSetError(iter
, ALC_INVALID_DEVICE
);
4323 if(!ATOMIC_COMPARE_EXCHANGE_PTR_STRONG_SEQ(&DeviceList
, &origdev
, device
->next
))
4325 ALCdevice
*volatile*list
= &origdev
->next
;
4330 *list
= (*list
)->next
;
4333 list
= &(*list
)->next
;
4338 ALCdevice_DecRef(device
);
4343 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
4345 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4346 alcSetError(device
, ALC_INVALID_DEVICE
);
4349 almtx_lock(&device
->BackendLock
);
4350 if(!device
->Connected
)
4351 alcSetError(device
, ALC_INVALID_DEVICE
);
4352 else if(!(device
->Flags
&DEVICE_RUNNING
))
4354 if(V0(device
->Backend
,start
)())
4355 device
->Flags
|= DEVICE_RUNNING
;
4358 aluHandleDisconnect(device
);
4359 alcSetError(device
, ALC_INVALID_DEVICE
);
4362 almtx_unlock(&device
->BackendLock
);
4365 if(device
) ALCdevice_DecRef(device
);
4368 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
4370 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4371 alcSetError(device
, ALC_INVALID_DEVICE
);
4374 almtx_lock(&device
->BackendLock
);
4375 if((device
->Flags
&DEVICE_RUNNING
))
4376 V0(device
->Backend
,stop
)();
4377 device
->Flags
&= ~DEVICE_RUNNING
;
4378 almtx_unlock(&device
->BackendLock
);
4381 if(device
) ALCdevice_DecRef(device
);
4384 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4386 if(!VerifyDevice(&device
) || device
->Type
!= Capture
)
4387 alcSetError(device
, ALC_INVALID_DEVICE
);
4390 ALCenum err
= ALC_INVALID_VALUE
;
4392 almtx_lock(&device
->BackendLock
);
4393 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
4394 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
4395 almtx_unlock(&device
->BackendLock
);
4397 if(err
!= ALC_NO_ERROR
)
4398 alcSetError(device
, err
);
4400 if(device
) ALCdevice_DecRef(device
);
4404 /************************************************
4405 * ALC loopback functions
4406 ************************************************/
4408 /* alcLoopbackOpenDeviceSOFT
4410 * Open a loopback device, for manual rendering.
4412 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
4414 ALCbackendFactory
*factory
;
4420 /* Make sure the device name, if specified, is us. */
4421 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
4423 alcSetError(NULL
, ALC_INVALID_VALUE
);
4427 device
= al_calloc(16, sizeof(ALCdevice
));
4430 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4435 InitRef(&device
->ref
, 1);
4436 device
->Connected
= ALC_TRUE
;
4437 device
->Type
= Loopback
;
4438 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
4441 device
->Hrtf
= NULL
;
4442 device
->HrtfHandle
= NULL
;
4443 VECTOR_INIT(device
->HrtfList
);
4444 AL_STRING_INIT(device
->HrtfName
);
4445 device
->Bs2b
= NULL
;
4446 device
->Uhj_Encoder
= NULL
;
4447 device
->Render_Mode
= NormalRender
;
4448 AL_STRING_INIT(device
->DeviceName
);
4449 device
->Dry
.Buffer
= NULL
;
4450 device
->Dry
.NumChannels
= 0;
4451 device
->FOAOut
.Buffer
= NULL
;
4452 device
->FOAOut
.NumChannels
= 0;
4453 device
->RealOut
.Buffer
= NULL
;
4454 device
->RealOut
.NumChannels
= 0;
4455 device
->Limiter
= NULL
;
4456 device
->AvgSpeakerDist
= 0.0f
;
4458 ATOMIC_INIT(&device
->ContextList
, NULL
);
4460 device
->ClockBase
= 0;
4461 device
->SamplesDone
= 0;
4463 device
->SourcesMax
= 256;
4464 device
->AuxiliaryEffectSlotMax
= 64;
4465 device
->NumAuxSends
= DEFAULT_SENDS
;
4467 InitUIntMap(&device
->BufferMap
, INT_MAX
);
4468 InitUIntMap(&device
->EffectMap
, INT_MAX
);
4469 InitUIntMap(&device
->FilterMap
, INT_MAX
);
4471 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
4473 device
->ChannelDelay
[i
].Gain
= 1.0f
;
4474 device
->ChannelDelay
[i
].Length
= 0;
4475 device
->ChannelDelay
[i
].Buffer
= NULL
;
4478 factory
= ALCloopbackFactory_getFactory();
4479 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
4480 if(!device
->Backend
)
4483 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
4486 almtx_init(&device
->BackendLock
, almtx_plain
);
4489 device
->NumUpdates
= 0;
4490 device
->UpdateSize
= 0;
4492 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
4493 device
->FmtChans
= DevFmtChannelsDefault
;
4494 device
->FmtType
= DevFmtTypeDefault
;
4495 device
->IsHeadphones
= AL_FALSE
;
4496 device
->AmbiLayout
= AmbiLayout_Default
;
4497 device
->AmbiScale
= AmbiNorm_Default
;
4499 ConfigValueUInt(NULL
, NULL
, "sources", &device
->SourcesMax
);
4500 if(device
->SourcesMax
== 0) device
->SourcesMax
= 256;
4502 ConfigValueUInt(NULL
, NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
4503 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 64;
4505 if(ConfigValueInt(NULL
, NULL
, "sends", &device
->NumAuxSends
))
4506 device
->NumAuxSends
= clampi(
4507 DEFAULT_SENDS
, 0, clampi(device
->NumAuxSends
, 0, MAX_SENDS
)
4510 device
->NumStereoSources
= 1;
4511 device
->NumMonoSources
= device
->SourcesMax
- device
->NumStereoSources
;
4513 // Open the "backend"
4514 V(device
->Backend
,open
)("Loopback");
4516 device
->Limiter
= CreateDeviceLimiter(device
);
4519 ALCdevice
*head
= ATOMIC_LOAD_SEQ(&DeviceList
);
4521 device
->next
= head
;
4522 } while(!ATOMIC_COMPARE_EXCHANGE_PTR_WEAK_SEQ(&DeviceList
, &head
, device
));
4525 TRACE("Created device %p\n", device
);
4529 /* alcIsRenderFormatSupportedSOFT
4531 * Determines if the loopback device supports the given format for rendering.
4533 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
4535 ALCboolean ret
= ALC_FALSE
;
4537 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4538 alcSetError(device
, ALC_INVALID_DEVICE
);
4540 alcSetError(device
, ALC_INVALID_VALUE
);
4543 if(IsValidALCType(type
) && IsValidALCChannels(channels
) && freq
>= MIN_OUTPUT_RATE
)
4546 if(device
) ALCdevice_DecRef(device
);
4551 /* alcRenderSamplesSOFT
4553 * Renders some samples into a buffer, using the format last set by the
4554 * attributes given to alcCreateContext.
4556 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
4558 if(!VerifyDevice(&device
) || device
->Type
!= Loopback
)
4559 alcSetError(device
, ALC_INVALID_DEVICE
);
4560 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
4561 alcSetError(device
, ALC_INVALID_VALUE
);
4564 V0(device
->Backend
,lock
)();
4565 aluMixData(device
, buffer
, samples
);
4566 V0(device
->Backend
,unlock
)();
4568 if(device
) ALCdevice_DecRef(device
);
4572 /************************************************
4573 * ALC DSP pause/resume functions
4574 ************************************************/
4576 /* alcDevicePauseSOFT
4578 * Pause the DSP to stop audio processing.
4580 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
4582 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4583 alcSetError(device
, ALC_INVALID_DEVICE
);
4586 almtx_lock(&device
->BackendLock
);
4587 if((device
->Flags
&DEVICE_RUNNING
))
4588 V0(device
->Backend
,stop
)();
4589 device
->Flags
&= ~DEVICE_RUNNING
;
4590 device
->Flags
|= DEVICE_PAUSED
;
4591 almtx_unlock(&device
->BackendLock
);
4593 if(device
) ALCdevice_DecRef(device
);
4596 /* alcDeviceResumeSOFT
4598 * Resume the DSP to restart audio processing.
4600 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
4602 if(!VerifyDevice(&device
) || device
->Type
!= Playback
)
4603 alcSetError(device
, ALC_INVALID_DEVICE
);
4606 almtx_lock(&device
->BackendLock
);
4607 if((device
->Flags
&DEVICE_PAUSED
))
4609 device
->Flags
&= ~DEVICE_PAUSED
;
4610 if(ATOMIC_LOAD_SEQ(&device
->ContextList
) != NULL
)
4612 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
4613 device
->Flags
|= DEVICE_RUNNING
;
4616 alcSetError(device
, ALC_INVALID_DEVICE
);
4617 V0(device
->Backend
,lock
)();
4618 aluHandleDisconnect(device
);
4619 V0(device
->Backend
,unlock
)();
4623 almtx_unlock(&device
->BackendLock
);
4625 if(device
) ALCdevice_DecRef(device
);
4629 /************************************************
4630 * ALC HRTF functions
4631 ************************************************/
4633 /* alcGetStringiSOFT
4635 * Gets a string parameter at the given index.
4637 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetStringiSOFT(ALCdevice
*device
, ALCenum paramName
, ALCsizei index
)
4639 const ALCchar
*str
= NULL
;
4641 if(!VerifyDevice(&device
) || device
->Type
== Capture
)
4642 alcSetError(device
, ALC_INVALID_DEVICE
);
4643 else switch(paramName
)
4645 case ALC_HRTF_SPECIFIER_SOFT
:
4646 if(index
>= 0 && (size_t)index
< VECTOR_SIZE(device
->HrtfList
))
4647 str
= alstr_get_cstr(VECTOR_ELEM(device
->HrtfList
, index
).name
);
4649 alcSetError(device
, ALC_INVALID_VALUE
);
4653 alcSetError(device
, ALC_INVALID_ENUM
);
4656 if(device
) ALCdevice_DecRef(device
);
4661 /* alcResetDeviceSOFT
4663 * Resets the given device output, using the specified attribute list.
4665 ALC_API ALCboolean ALC_APIENTRY
alcResetDeviceSOFT(ALCdevice
*device
, const ALCint
*attribs
)
4670 if(!VerifyDevice(&device
) || device
->Type
== Capture
|| !device
->Connected
)
4673 alcSetError(device
, ALC_INVALID_DEVICE
);
4674 if(device
) ALCdevice_DecRef(device
);
4677 almtx_lock(&device
->BackendLock
);
4680 err
= UpdateDeviceParams(device
, attribs
);
4681 almtx_unlock(&device
->BackendLock
);
4683 if(err
!= ALC_NO_ERROR
)
4685 alcSetError(device
, err
);
4686 if(err
== ALC_INVALID_DEVICE
)
4688 V0(device
->Backend
,lock
)();
4689 aluHandleDisconnect(device
);
4690 V0(device
->Backend
,unlock
)();
4692 ALCdevice_DecRef(device
);
4695 ALCdevice_DecRef(device
);