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
32 #include "alListener.h"
36 #include "alAuxEffectSlot.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
52 ************************************************/
55 ALCbackendFactory
* (*getFactory
)(void);
56 ALCboolean (*Init
)(BackendFuncs
*);
58 void (*Probe
)(enum DevProbe
);
62 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
63 static struct BackendInfo BackendList
[] = {
64 #ifdef HAVE_PULSEAUDIO
65 { "pulse", ALCpulseBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
68 { "alsa", ALCalsaBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
71 { "core", NULL
, alc_ca_init
, alc_ca_deinit
, alc_ca_probe
, EmptyFuncs
},
74 { "oss", ALCossBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
77 { "solaris", NULL
, alc_solaris_init
, alc_solaris_deinit
, alc_solaris_probe
, EmptyFuncs
},
80 { "sndio", NULL
, alc_sndio_init
, alc_sndio_deinit
, alc_sndio_probe
, EmptyFuncs
},
83 { "qsa", NULL
, alc_qsa_init
, alc_qsa_deinit
, alc_qsa_probe
, EmptyFuncs
},
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
89 { "dsound", ALCdsoundBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
92 { "winmm", ALCwinmmBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
95 { "port", NULL
, alc_pa_init
, alc_pa_deinit
, alc_pa_probe
, EmptyFuncs
},
98 { "opensl", NULL
, alc_opensl_init
, alc_opensl_deinit
, alc_opensl_probe
, EmptyFuncs
},
101 { "null", ALCnullBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
103 { "wave", ALCwaveBackendFactory_getFactory
, NULL
, NULL
, NULL
, EmptyFuncs
},
106 { NULL
, NULL
, NULL
, NULL
, NULL
, EmptyFuncs
}
110 static struct BackendInfo PlaybackBackend
;
111 static struct BackendInfo CaptureBackend
;
114 /************************************************
115 * Functions, enums, and errors
116 ************************************************/
117 typedef struct ALCfunction
{
118 const ALCchar
*funcName
;
122 typedef struct ALCenums
{
123 const ALCchar
*enumName
;
127 #define DECL(x) { #x, (ALCvoid*)(x) }
128 static const ALCfunction alcFunctions
[] = {
129 DECL(alcCreateContext
),
130 DECL(alcMakeContextCurrent
),
131 DECL(alcProcessContext
),
132 DECL(alcSuspendContext
),
133 DECL(alcDestroyContext
),
134 DECL(alcGetCurrentContext
),
135 DECL(alcGetContextsDevice
),
137 DECL(alcCloseDevice
),
139 DECL(alcIsExtensionPresent
),
140 DECL(alcGetProcAddress
),
141 DECL(alcGetEnumValue
),
143 DECL(alcGetIntegerv
),
144 DECL(alcCaptureOpenDevice
),
145 DECL(alcCaptureCloseDevice
),
146 DECL(alcCaptureStart
),
147 DECL(alcCaptureStop
),
148 DECL(alcCaptureSamples
),
150 DECL(alcSetThreadContext
),
151 DECL(alcGetThreadContext
),
153 DECL(alcLoopbackOpenDeviceSOFT
),
154 DECL(alcIsRenderFormatSupportedSOFT
),
155 DECL(alcRenderSamplesSOFT
),
157 DECL(alcDevicePauseSOFT
),
158 DECL(alcDeviceResumeSOFT
),
160 DECL(alcGetInteger64vSOFT
),
175 DECL(alIsExtensionPresent
),
176 DECL(alGetProcAddress
),
177 DECL(alGetEnumValue
),
184 DECL(alGetListenerf
),
185 DECL(alGetListener3f
),
186 DECL(alGetListenerfv
),
187 DECL(alGetListeneri
),
188 DECL(alGetListener3i
),
189 DECL(alGetListeneriv
),
191 DECL(alDeleteSources
),
207 DECL(alSourceRewindv
),
208 DECL(alSourcePausev
),
211 DECL(alSourceRewind
),
213 DECL(alSourceQueueBuffers
),
214 DECL(alSourceUnqueueBuffers
),
216 DECL(alDeleteBuffers
),
231 DECL(alDopplerFactor
),
232 DECL(alDopplerVelocity
),
233 DECL(alSpeedOfSound
),
234 DECL(alDistanceModel
),
237 DECL(alDeleteFilters
),
248 DECL(alDeleteEffects
),
258 DECL(alGenAuxiliaryEffectSlots
),
259 DECL(alDeleteAuxiliaryEffectSlots
),
260 DECL(alIsAuxiliaryEffectSlot
),
261 DECL(alAuxiliaryEffectSloti
),
262 DECL(alAuxiliaryEffectSlotiv
),
263 DECL(alAuxiliaryEffectSlotf
),
264 DECL(alAuxiliaryEffectSlotfv
),
265 DECL(alGetAuxiliaryEffectSloti
),
266 DECL(alGetAuxiliaryEffectSlotiv
),
267 DECL(alGetAuxiliaryEffectSlotf
),
268 DECL(alGetAuxiliaryEffectSlotfv
),
270 DECL(alBufferSubDataSOFT
),
272 DECL(alBufferSamplesSOFT
),
273 DECL(alBufferSubSamplesSOFT
),
274 DECL(alGetBufferSamplesSOFT
),
275 DECL(alIsBufferFormatSupportedSOFT
),
277 DECL(alDeferUpdatesSOFT
),
278 DECL(alProcessUpdatesSOFT
),
281 DECL(alSource3dSOFT
),
282 DECL(alSourcedvSOFT
),
283 DECL(alGetSourcedSOFT
),
284 DECL(alGetSource3dSOFT
),
285 DECL(alGetSourcedvSOFT
),
286 DECL(alSourcei64SOFT
),
287 DECL(alSource3i64SOFT
),
288 DECL(alSourcei64vSOFT
),
289 DECL(alGetSourcei64SOFT
),
290 DECL(alGetSource3i64SOFT
),
291 DECL(alGetSourcei64vSOFT
),
293 DECL(alGenSoundfontsSOFT
),
294 DECL(alDeleteSoundfontsSOFT
),
295 DECL(alIsSoundfontSOFT
),
296 DECL(alGetSoundfontivSOFT
),
297 DECL(alSoundfontPresetsSOFT
),
298 DECL(alGenPresetsSOFT
),
299 DECL(alDeletePresetsSOFT
),
300 DECL(alIsPresetSOFT
),
302 DECL(alPresetivSOFT
),
303 DECL(alGetPresetivSOFT
),
304 DECL(alPresetFontsoundsSOFT
),
305 DECL(alGenFontsoundsSOFT
),
306 DECL(alDeleteFontsoundsSOFT
),
307 DECL(alIsFontsoundSOFT
),
308 DECL(alFontsoundiSOFT
),
309 DECL(alFontsound2iSOFT
),
310 DECL(alFontsoundivSOFT
),
311 DECL(alGetFontsoundivSOFT
),
312 DECL(alFontsoundModulatoriSOFT
),
313 DECL(alGetFontsoundModulatorivSOFT
),
314 DECL(alMidiSoundfontSOFT
),
315 DECL(alMidiSoundfontvSOFT
),
316 DECL(alMidiEventSOFT
),
317 DECL(alMidiSysExSOFT
),
318 DECL(alMidiPlaySOFT
),
319 DECL(alMidiPauseSOFT
),
320 DECL(alMidiStopSOFT
),
321 DECL(alMidiResetSOFT
),
322 DECL(alMidiGainSOFT
),
323 DECL(alGetInteger64SOFT
),
324 DECL(alGetInteger64vSOFT
),
325 DECL(alLoadSoundfontSOFT
),
331 #define DECL(x) { #x, (x) }
332 static const ALCenums enumeration
[] = {
337 DECL(ALC_MAJOR_VERSION
),
338 DECL(ALC_MINOR_VERSION
),
339 DECL(ALC_ATTRIBUTES_SIZE
),
340 DECL(ALC_ALL_ATTRIBUTES
),
341 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
342 DECL(ALC_DEVICE_SPECIFIER
),
343 DECL(ALC_ALL_DEVICES_SPECIFIER
),
344 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
345 DECL(ALC_EXTENSIONS
),
349 DECL(ALC_MONO_SOURCES
),
350 DECL(ALC_STEREO_SOURCES
),
351 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
352 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
353 DECL(ALC_CAPTURE_SAMPLES
),
356 DECL(ALC_EFX_MAJOR_VERSION
),
357 DECL(ALC_EFX_MINOR_VERSION
),
358 DECL(ALC_MAX_AUXILIARY_SENDS
),
360 DECL(ALC_FORMAT_CHANNELS_SOFT
),
361 DECL(ALC_FORMAT_TYPE_SOFT
),
364 DECL(ALC_STEREO_SOFT
),
366 DECL(ALC_5POINT1_SOFT
),
367 DECL(ALC_6POINT1_SOFT
),
368 DECL(ALC_7POINT1_SOFT
),
371 DECL(ALC_UNSIGNED_BYTE_SOFT
),
372 DECL(ALC_SHORT_SOFT
),
373 DECL(ALC_UNSIGNED_SHORT_SOFT
),
375 DECL(ALC_UNSIGNED_INT_SOFT
),
376 DECL(ALC_FLOAT_SOFT
),
379 DECL(ALC_INVALID_DEVICE
),
380 DECL(ALC_INVALID_CONTEXT
),
381 DECL(ALC_INVALID_ENUM
),
382 DECL(ALC_INVALID_VALUE
),
383 DECL(ALC_OUT_OF_MEMORY
),
391 DECL(AL_SOURCE_RELATIVE
),
392 DECL(AL_CONE_INNER_ANGLE
),
393 DECL(AL_CONE_OUTER_ANGLE
),
403 DECL(AL_ORIENTATION
),
404 DECL(AL_REFERENCE_DISTANCE
),
405 DECL(AL_ROLLOFF_FACTOR
),
406 DECL(AL_CONE_OUTER_GAIN
),
407 DECL(AL_MAX_DISTANCE
),
409 DECL(AL_SAMPLE_OFFSET
),
410 DECL(AL_SAMPLE_RW_OFFSETS_SOFT
),
411 DECL(AL_BYTE_OFFSET
),
412 DECL(AL_BYTE_RW_OFFSETS_SOFT
),
413 DECL(AL_SOURCE_TYPE
),
416 DECL(AL_UNDETERMINED
),
417 DECL(AL_METERS_PER_UNIT
),
418 DECL(AL_DIRECT_CHANNELS_SOFT
),
420 DECL(AL_DIRECT_FILTER
),
421 DECL(AL_AUXILIARY_SEND_FILTER
),
422 DECL(AL_AIR_ABSORPTION_FACTOR
),
423 DECL(AL_ROOM_ROLLOFF_FACTOR
),
424 DECL(AL_CONE_OUTER_GAINHF
),
425 DECL(AL_DIRECT_FILTER_GAINHF_AUTO
),
426 DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
),
427 DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
),
429 DECL(AL_SOURCE_STATE
),
435 DECL(AL_BUFFERS_QUEUED
),
436 DECL(AL_BUFFERS_PROCESSED
),
438 DECL(AL_FORMAT_MONO8
),
439 DECL(AL_FORMAT_MONO16
),
440 DECL(AL_FORMAT_MONO_FLOAT32
),
441 DECL(AL_FORMAT_MONO_DOUBLE_EXT
),
442 DECL(AL_FORMAT_STEREO8
),
443 DECL(AL_FORMAT_STEREO16
),
444 DECL(AL_FORMAT_STEREO_FLOAT32
),
445 DECL(AL_FORMAT_STEREO_DOUBLE_EXT
),
446 DECL(AL_FORMAT_MONO_IMA4
),
447 DECL(AL_FORMAT_STEREO_IMA4
),
448 DECL(AL_FORMAT_MONO_MSADPCM_SOFT
),
449 DECL(AL_FORMAT_STEREO_MSADPCM_SOFT
),
450 DECL(AL_FORMAT_QUAD8_LOKI
),
451 DECL(AL_FORMAT_QUAD16_LOKI
),
452 DECL(AL_FORMAT_QUAD8
),
453 DECL(AL_FORMAT_QUAD16
),
454 DECL(AL_FORMAT_QUAD32
),
455 DECL(AL_FORMAT_51CHN8
),
456 DECL(AL_FORMAT_51CHN16
),
457 DECL(AL_FORMAT_51CHN32
),
458 DECL(AL_FORMAT_61CHN8
),
459 DECL(AL_FORMAT_61CHN16
),
460 DECL(AL_FORMAT_61CHN32
),
461 DECL(AL_FORMAT_71CHN8
),
462 DECL(AL_FORMAT_71CHN16
),
463 DECL(AL_FORMAT_71CHN32
),
464 DECL(AL_FORMAT_REAR8
),
465 DECL(AL_FORMAT_REAR16
),
466 DECL(AL_FORMAT_REAR32
),
467 DECL(AL_FORMAT_MONO_MULAW
),
468 DECL(AL_FORMAT_MONO_MULAW_EXT
),
469 DECL(AL_FORMAT_STEREO_MULAW
),
470 DECL(AL_FORMAT_STEREO_MULAW_EXT
),
471 DECL(AL_FORMAT_QUAD_MULAW
),
472 DECL(AL_FORMAT_51CHN_MULAW
),
473 DECL(AL_FORMAT_61CHN_MULAW
),
474 DECL(AL_FORMAT_71CHN_MULAW
),
475 DECL(AL_FORMAT_REAR_MULAW
),
476 DECL(AL_FORMAT_MONO_ALAW_EXT
),
477 DECL(AL_FORMAT_STEREO_ALAW_EXT
),
480 DECL(AL_MONO16_SOFT
),
481 DECL(AL_MONO32F_SOFT
),
482 DECL(AL_STEREO8_SOFT
),
483 DECL(AL_STEREO16_SOFT
),
484 DECL(AL_STEREO32F_SOFT
),
486 DECL(AL_QUAD16_SOFT
),
487 DECL(AL_QUAD32F_SOFT
),
489 DECL(AL_REAR16_SOFT
),
490 DECL(AL_REAR32F_SOFT
),
491 DECL(AL_5POINT1_8_SOFT
),
492 DECL(AL_5POINT1_16_SOFT
),
493 DECL(AL_5POINT1_32F_SOFT
),
494 DECL(AL_6POINT1_8_SOFT
),
495 DECL(AL_6POINT1_16_SOFT
),
496 DECL(AL_6POINT1_32F_SOFT
),
497 DECL(AL_7POINT1_8_SOFT
),
498 DECL(AL_7POINT1_16_SOFT
),
499 DECL(AL_7POINT1_32F_SOFT
),
500 DECL(AL_FORMAT_BFORMAT2D_8
),
501 DECL(AL_FORMAT_BFORMAT2D_16
),
502 DECL(AL_FORMAT_BFORMAT2D_FLOAT32
),
503 DECL(AL_FORMAT_BFORMAT2D_MULAW
),
504 DECL(AL_FORMAT_BFORMAT3D_8
),
505 DECL(AL_FORMAT_BFORMAT3D_16
),
506 DECL(AL_FORMAT_BFORMAT3D_FLOAT32
),
507 DECL(AL_FORMAT_BFORMAT3D_MULAW
),
510 DECL(AL_STEREO_SOFT
),
513 DECL(AL_5POINT1_SOFT
),
514 DECL(AL_6POINT1_SOFT
),
515 DECL(AL_7POINT1_SOFT
),
518 DECL(AL_UNSIGNED_BYTE_SOFT
),
520 DECL(AL_UNSIGNED_SHORT_SOFT
),
522 DECL(AL_UNSIGNED_INT_SOFT
),
524 DECL(AL_DOUBLE_SOFT
),
526 DECL(AL_UNSIGNED_BYTE3_SOFT
),
532 DECL(AL_INTERNAL_FORMAT_SOFT
),
533 DECL(AL_BYTE_LENGTH_SOFT
),
534 DECL(AL_SAMPLE_LENGTH_SOFT
),
535 DECL(AL_SEC_LENGTH_SOFT
),
536 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT
),
537 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT
),
544 DECL(AL_INVALID_NAME
),
545 DECL(AL_INVALID_ENUM
),
546 DECL(AL_INVALID_VALUE
),
547 DECL(AL_INVALID_OPERATION
),
548 DECL(AL_OUT_OF_MEMORY
),
555 DECL(AL_DOPPLER_FACTOR
),
556 DECL(AL_DOPPLER_VELOCITY
),
557 DECL(AL_DISTANCE_MODEL
),
558 DECL(AL_SPEED_OF_SOUND
),
559 DECL(AL_SOURCE_DISTANCE_MODEL
),
560 DECL(AL_DEFERRED_UPDATES_SOFT
),
562 DECL(AL_INVERSE_DISTANCE
),
563 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
564 DECL(AL_LINEAR_DISTANCE
),
565 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
566 DECL(AL_EXPONENT_DISTANCE
),
567 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
569 DECL(AL_FILTER_TYPE
),
570 DECL(AL_FILTER_NULL
),
571 DECL(AL_FILTER_LOWPASS
),
572 DECL(AL_FILTER_HIGHPASS
),
573 DECL(AL_FILTER_BANDPASS
),
575 DECL(AL_LOWPASS_GAIN
),
576 DECL(AL_LOWPASS_GAINHF
),
578 DECL(AL_HIGHPASS_GAIN
),
579 DECL(AL_HIGHPASS_GAINLF
),
581 DECL(AL_BANDPASS_GAIN
),
582 DECL(AL_BANDPASS_GAINHF
),
583 DECL(AL_BANDPASS_GAINLF
),
585 DECL(AL_EFFECT_TYPE
),
586 DECL(AL_EFFECT_NULL
),
587 DECL(AL_EFFECT_REVERB
),
588 DECL(AL_EFFECT_EAXREVERB
),
589 DECL(AL_EFFECT_CHORUS
),
590 DECL(AL_EFFECT_DISTORTION
),
591 DECL(AL_EFFECT_ECHO
),
592 DECL(AL_EFFECT_FLANGER
),
594 DECL(AL_EFFECT_FREQUENCY_SHIFTER
),
595 DECL(AL_EFFECT_VOCAL_MORPHER
),
596 DECL(AL_EFFECT_PITCH_SHIFTER
),
598 DECL(AL_EFFECT_RING_MODULATOR
),
600 DECL(AL_EFFECT_AUTOWAH
),
602 DECL(AL_EFFECT_COMPRESSOR
),
603 DECL(AL_EFFECT_EQUALIZER
),
604 DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT
),
605 DECL(AL_EFFECT_DEDICATED_DIALOGUE
),
607 DECL(AL_EAXREVERB_DENSITY
),
608 DECL(AL_EAXREVERB_DIFFUSION
),
609 DECL(AL_EAXREVERB_GAIN
),
610 DECL(AL_EAXREVERB_GAINHF
),
611 DECL(AL_EAXREVERB_GAINLF
),
612 DECL(AL_EAXREVERB_DECAY_TIME
),
613 DECL(AL_EAXREVERB_DECAY_HFRATIO
),
614 DECL(AL_EAXREVERB_DECAY_LFRATIO
),
615 DECL(AL_EAXREVERB_REFLECTIONS_GAIN
),
616 DECL(AL_EAXREVERB_REFLECTIONS_DELAY
),
617 DECL(AL_EAXREVERB_REFLECTIONS_PAN
),
618 DECL(AL_EAXREVERB_LATE_REVERB_GAIN
),
619 DECL(AL_EAXREVERB_LATE_REVERB_DELAY
),
620 DECL(AL_EAXREVERB_LATE_REVERB_PAN
),
621 DECL(AL_EAXREVERB_ECHO_TIME
),
622 DECL(AL_EAXREVERB_ECHO_DEPTH
),
623 DECL(AL_EAXREVERB_MODULATION_TIME
),
624 DECL(AL_EAXREVERB_MODULATION_DEPTH
),
625 DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF
),
626 DECL(AL_EAXREVERB_HFREFERENCE
),
627 DECL(AL_EAXREVERB_LFREFERENCE
),
628 DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR
),
629 DECL(AL_EAXREVERB_DECAY_HFLIMIT
),
631 DECL(AL_REVERB_DENSITY
),
632 DECL(AL_REVERB_DIFFUSION
),
633 DECL(AL_REVERB_GAIN
),
634 DECL(AL_REVERB_GAINHF
),
635 DECL(AL_REVERB_DECAY_TIME
),
636 DECL(AL_REVERB_DECAY_HFRATIO
),
637 DECL(AL_REVERB_REFLECTIONS_GAIN
),
638 DECL(AL_REVERB_REFLECTIONS_DELAY
),
639 DECL(AL_REVERB_LATE_REVERB_GAIN
),
640 DECL(AL_REVERB_LATE_REVERB_DELAY
),
641 DECL(AL_REVERB_AIR_ABSORPTION_GAINHF
),
642 DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR
),
643 DECL(AL_REVERB_DECAY_HFLIMIT
),
645 DECL(AL_CHORUS_WAVEFORM
),
646 DECL(AL_CHORUS_PHASE
),
647 DECL(AL_CHORUS_RATE
),
648 DECL(AL_CHORUS_DEPTH
),
649 DECL(AL_CHORUS_FEEDBACK
),
650 DECL(AL_CHORUS_DELAY
),
652 DECL(AL_DISTORTION_EDGE
),
653 DECL(AL_DISTORTION_GAIN
),
654 DECL(AL_DISTORTION_LOWPASS_CUTOFF
),
655 DECL(AL_DISTORTION_EQCENTER
),
656 DECL(AL_DISTORTION_EQBANDWIDTH
),
659 DECL(AL_ECHO_LRDELAY
),
660 DECL(AL_ECHO_DAMPING
),
661 DECL(AL_ECHO_FEEDBACK
),
662 DECL(AL_ECHO_SPREAD
),
664 DECL(AL_FLANGER_WAVEFORM
),
665 DECL(AL_FLANGER_PHASE
),
666 DECL(AL_FLANGER_RATE
),
667 DECL(AL_FLANGER_DEPTH
),
668 DECL(AL_FLANGER_FEEDBACK
),
669 DECL(AL_FLANGER_DELAY
),
671 DECL(AL_RING_MODULATOR_FREQUENCY
),
672 DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF
),
673 DECL(AL_RING_MODULATOR_WAVEFORM
),
676 DECL(AL_AUTOWAH_ATTACK_TIME
),
677 DECL(AL_AUTOWAH_PEAK_GAIN
),
678 DECL(AL_AUTOWAH_RELEASE_TIME
),
679 DECL(AL_AUTOWAH_RESONANCE
),
682 DECL(AL_COMPRESSOR_ONOFF
),
684 DECL(AL_EQUALIZER_LOW_GAIN
),
685 DECL(AL_EQUALIZER_LOW_CUTOFF
),
686 DECL(AL_EQUALIZER_MID1_GAIN
),
687 DECL(AL_EQUALIZER_MID1_CENTER
),
688 DECL(AL_EQUALIZER_MID1_WIDTH
),
689 DECL(AL_EQUALIZER_MID2_GAIN
),
690 DECL(AL_EQUALIZER_MID2_CENTER
),
691 DECL(AL_EQUALIZER_MID2_WIDTH
),
692 DECL(AL_EQUALIZER_HIGH_GAIN
),
693 DECL(AL_EQUALIZER_HIGH_CUTOFF
),
695 DECL(AL_DEDICATED_GAIN
),
701 static const ALCchar alcNoError
[] = "No Error";
702 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
703 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
704 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
705 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
706 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
709 /************************************************
711 ************************************************/
713 /* Enumerated device names */
714 static const ALCchar alcDefaultName
[] = "OpenAL Soft\0";
716 static al_string alcAllDevicesList
;
717 static al_string alcCaptureDeviceList
;
719 /* Default is always the first in the list */
720 static ALCchar
*alcDefaultAllDevicesSpecifier
;
721 static ALCchar
*alcCaptureDefaultDeviceSpecifier
;
723 /* Default context extensions */
724 static const ALchar alExtList
[] =
725 "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE "
726 "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS "
727 "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET "
728 "AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_block_alignment "
729 "AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates "
730 "AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM "
731 "AL_SOFT_source_latency AL_SOFT_source_length";
733 static ATOMIC(ALCenum
) LastNullDeviceError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
735 /* Thread-local current context */
736 static altss_t LocalContext
;
737 /* Process-wide current context */
738 static ATOMIC(ALCcontext
*) GlobalContext
= ATOMIC_INIT_STATIC(NULL
);
740 /* Mixing thread piority level */
745 enum LogLevel LogLevel
= LogWarning
;
747 enum LogLevel LogLevel
= LogError
;
750 /* Flag to trap ALC device errors */
751 static ALCboolean TrapALCError
= ALC_FALSE
;
753 /* One-time configuration init control */
754 static alonce_flag alc_config_once
= AL_ONCE_FLAG_INIT
;
756 /* Default effect that applies to sources that don't have an effect on send 0 */
757 static ALeffect DefaultEffect
;
759 /* Flag to specify if alcSuspendContext/alcProcessContext should defer/process
762 static ALCboolean SuspendDefers
= ALC_TRUE
;
765 /************************************************
767 ************************************************/
768 static const ALCchar alcNoDeviceExtList
[] =
769 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
770 "ALC_EXT_thread_local_context ALC_SOFT_loopback";
771 static const ALCchar alcExtensionList
[] =
772 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
773 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX "
774 "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF "
775 "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device";
776 static const ALCint alcMajorVersion
= 1;
777 static const ALCint alcMinorVersion
= 1;
779 static const ALCint alcEFXMajorVersion
= 1;
780 static const ALCint alcEFXMinorVersion
= 0;
783 /************************************************
785 ************************************************/
786 static ATOMIC(ALCdevice
*) DeviceList
= ATOMIC_INIT_STATIC(NULL
);
788 static almtx_t ListLock
;
789 static inline void LockLists(void)
791 int lockret
= almtx_lock(&ListLock
);
792 assert(lockret
== althrd_success
);
794 static inline void UnlockLists(void)
796 int unlockret
= almtx_unlock(&ListLock
);
797 assert(unlockret
== althrd_success
);
800 /************************************************
801 * Library initialization
802 ************************************************/
804 static void alc_init(void);
805 static void alc_deinit(void);
806 static void alc_deinit_safe(void);
808 #ifndef AL_LIBTYPE_STATIC
809 BOOL APIENTRY
DllMain(HINSTANCE hModule
, DWORD reason
, LPVOID lpReserved
)
813 case DLL_PROCESS_ATTACH
:
814 /* Pin the DLL so we won't get unloaded until the process terminates */
815 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN
| GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
816 (WCHAR
*)hModule
, &hModule
);
820 case DLL_THREAD_DETACH
:
823 case DLL_PROCESS_DETACH
:
832 #elif defined(_MSC_VER)
833 #pragma section(".CRT$XCU",read)
834 static void alc_constructor(void);
835 static void alc_destructor(void);
836 __declspec(allocate(".CRT$XCU")) void (__cdecl
* alc_constructor_
)(void) = alc_constructor
;
838 static void alc_constructor(void)
840 atexit(alc_destructor
);
844 static void alc_destructor(void)
848 #elif defined(HAVE_GCC_DESTRUCTOR)
849 static void alc_init(void) __attribute__((constructor
));
850 static void alc_deinit(void) __attribute__((destructor
));
852 #error "No static initialization available on this platform!"
855 #elif defined(HAVE_GCC_DESTRUCTOR)
857 static void alc_init(void) __attribute__((constructor
));
858 static void alc_deinit(void) __attribute__((destructor
));
861 #error "No global initialization available on this platform!"
864 static void ReleaseThreadCtx(void *ptr
);
865 static void alc_init(void)
872 AL_STRING_INIT(alcAllDevicesList
);
873 AL_STRING_INIT(alcCaptureDeviceList
);
875 str
= getenv("__ALSOFT_HALF_ANGLE_CONES");
876 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
879 str
= getenv("__ALSOFT_REVERSE_Z");
880 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
883 ret
= altss_create(&LocalContext
, ReleaseThreadCtx
);
884 assert(ret
== althrd_success
);
886 ret
= almtx_init(&ListLock
, almtx_recursive
);
887 assert(ret
== althrd_success
);
892 static void alc_initconfig(void)
894 const char *devs
, *str
;
899 str
= getenv("ALSOFT_LOGLEVEL");
902 long lvl
= strtol(str
, NULL
, 0);
903 if(lvl
>= NoLog
&& lvl
<= LogRef
)
907 str
= getenv("ALSOFT_LOGFILE");
910 FILE *logfile
= al_fopen(str
, "wt");
911 if(logfile
) LogFile
= logfile
;
912 else ERR("Failed to open log file '%s'\n", str
);
917 int len
= snprintf(buf
, sizeof(buf
), "%s", BackendList
[0].name
);
918 for(i
= 1;BackendList
[i
].name
;i
++)
919 len
+= snprintf(buf
+len
, sizeof(buf
)-len
, ", %s", BackendList
[i
].name
);
920 TRACE("Supported backends: %s\n", buf
);
924 str
= getenv("__ALSOFT_SUSPEND_CONTEXT");
927 if(strcasecmp(str
, "ignore") == 0)
929 SuspendDefers
= ALC_FALSE
;
930 TRACE("Selected context suspend behavior, \"ignore\"\n");
933 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str
);
937 #if defined(HAVE_SSE4_1)
938 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
| CPU_CAP_SSE4_1
;
939 #elif defined(HAVE_SSE2)
940 capfilter
|= CPU_CAP_SSE
| CPU_CAP_SSE2
;
941 #elif defined(HAVE_SSE)
942 capfilter
|= CPU_CAP_SSE
;
945 capfilter
|= CPU_CAP_NEON
;
947 if(ConfigValueStr(NULL
, "disable-cpu-exts", &str
))
949 if(strcasecmp(str
, "all") == 0)
954 const char *next
= str
;
958 while(isspace(str
[0]))
960 next
= strchr(str
, ',');
962 if(!str
[0] || str
[0] == ',')
965 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
966 while(len
> 0 && isspace(str
[len
-1]))
968 if(len
== 3 && strncasecmp(str
, "sse", len
) == 0)
969 capfilter
&= ~CPU_CAP_SSE
;
970 else if(len
== 4 && strncasecmp(str
, "sse2", len
) == 0)
971 capfilter
&= ~CPU_CAP_SSE2
;
972 else if(len
== 6 && strncasecmp(str
, "sse4.1", len
) == 0)
973 capfilter
&= ~CPU_CAP_SSE4_1
;
974 else if(len
== 4 && strncasecmp(str
, "neon", len
) == 0)
975 capfilter
&= ~CPU_CAP_NEON
;
977 WARN("Invalid CPU extension \"%s\"\n", str
);
981 FillCPUCaps(capfilter
);
988 ConfigValueInt(NULL
, "rt-prio", &RTPrioLevel
);
990 if(ConfigValueStr(NULL
, "resampler", &str
))
992 if(strcasecmp(str
, "point") == 0 || strcasecmp(str
, "none") == 0)
993 DefaultResampler
= PointResampler
;
994 else if(strcasecmp(str
, "linear") == 0)
995 DefaultResampler
= LinearResampler
;
996 else if(strcasecmp(str
, "cubic") == 0)
997 DefaultResampler
= CubicResampler
;
1002 n
= strtol(str
, &end
, 0);
1003 if(*end
== '\0' && (n
== PointResampler
|| n
== LinearResampler
|| n
== CubicResampler
))
1004 DefaultResampler
= n
;
1006 WARN("Invalid resampler: %s\n", str
);
1010 str
= getenv("ALSOFT_TRAP_ERROR");
1011 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1013 TrapALError
= AL_TRUE
;
1014 TrapALCError
= AL_TRUE
;
1018 str
= getenv("ALSOFT_TRAP_AL_ERROR");
1019 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1020 TrapALError
= AL_TRUE
;
1021 TrapALError
= GetConfigValueBool(NULL
, "trap-al-error", TrapALError
);
1023 str
= getenv("ALSOFT_TRAP_ALC_ERROR");
1024 if(str
&& (strcasecmp(str
, "true") == 0 || strtol(str
, NULL
, 0) == 1))
1025 TrapALCError
= ALC_TRUE
;
1026 TrapALCError
= GetConfigValueBool(NULL
, "trap-alc-error", TrapALCError
);
1029 if(ConfigValueFloat("reverb", "boost", &valf
))
1030 ReverbBoost
*= powf(10.0f
, valf
/ 20.0f
);
1032 EmulateEAXReverb
= GetConfigValueBool("reverb", "emulate-eax", AL_FALSE
);
1034 if(((devs
=getenv("ALSOFT_DRIVERS")) && devs
[0]) ||
1035 ConfigValueStr(NULL
, "drivers", &devs
))
1039 const char *next
= devs
;
1040 int endlist
, delitem
;
1045 while(isspace(devs
[0]))
1047 next
= strchr(devs
, ',');
1049 delitem
= (devs
[0] == '-');
1050 if(devs
[0] == '-') devs
++;
1052 if(!devs
[0] || devs
[0] == ',')
1059 len
= (next
? ((size_t)(next
-devs
)) : strlen(devs
));
1060 while(len
> 0 && isspace(devs
[len
-1]))
1062 for(n
= i
;BackendList
[n
].name
;n
++)
1064 if(len
== strlen(BackendList
[n
].name
) &&
1065 strncmp(BackendList
[n
].name
, devs
, len
) == 0)
1070 BackendList
[n
] = BackendList
[n
+1];
1072 } while(BackendList
[n
].name
);
1076 struct BackendInfo Bkp
= BackendList
[n
];
1079 BackendList
[n
] = BackendList
[n
-1];
1082 BackendList
[n
] = Bkp
;
1093 BackendList
[i
].name
= NULL
;
1094 BackendList
[i
].getFactory
= NULL
;
1095 BackendList
[i
].Init
= NULL
;
1096 BackendList
[i
].Deinit
= NULL
;
1097 BackendList
[i
].Probe
= NULL
;
1101 for(i
= 0;(BackendList
[i
].Init
|| BackendList
[i
].getFactory
) && (!PlaybackBackend
.name
|| !CaptureBackend
.name
);i
++)
1103 if(BackendList
[i
].getFactory
)
1105 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1106 if(!V0(factory
,init
)())
1108 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1112 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1113 if(!PlaybackBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Playback
))
1115 PlaybackBackend
= BackendList
[i
];
1116 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1118 if(!CaptureBackend
.name
&& V(factory
,querySupport
)(ALCbackend_Capture
))
1120 CaptureBackend
= BackendList
[i
];
1121 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1127 if(!BackendList
[i
].Init(&BackendList
[i
].Funcs
))
1129 WARN("Failed to initialize backend \"%s\"\n", BackendList
[i
].name
);
1133 TRACE("Initialized backend \"%s\"\n", BackendList
[i
].name
);
1134 if(BackendList
[i
].Funcs
.OpenPlayback
&& !PlaybackBackend
.name
)
1136 PlaybackBackend
= BackendList
[i
];
1137 TRACE("Added \"%s\" for playback\n", PlaybackBackend
.name
);
1139 if(BackendList
[i
].Funcs
.OpenCapture
&& !CaptureBackend
.name
)
1141 CaptureBackend
= BackendList
[i
];
1142 TRACE("Added \"%s\" for capture\n", CaptureBackend
.name
);
1146 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1150 if(ConfigValueStr(NULL
, "excludefx", &str
))
1153 const char *next
= str
;
1157 next
= strchr(str
, ',');
1159 if(!str
[0] || next
== str
)
1162 len
= (next
? ((size_t)(next
-str
)) : strlen(str
));
1163 for(n
= 0;EffectList
[n
].name
;n
++)
1165 if(len
== strlen(EffectList
[n
].name
) &&
1166 strncmp(EffectList
[n
].name
, str
, len
) == 0)
1167 DisabledEffects
[EffectList
[n
].type
] = AL_TRUE
;
1172 InitEffectFactoryMap();
1174 InitEffect(&DefaultEffect
);
1175 str
= getenv("ALSOFT_DEFAULT_REVERB");
1176 if((str
&& str
[0]) || ConfigValueStr(NULL
, "default-reverb", &str
))
1177 LoadReverbPreset(str
, &DefaultEffect
);
1179 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1182 /************************************************
1183 * Library deinitialization
1184 ************************************************/
1185 static void alc_cleanup(void)
1189 AL_STRING_DEINIT(alcAllDevicesList
);
1190 AL_STRING_DEINIT(alcCaptureDeviceList
);
1192 free(alcDefaultAllDevicesSpecifier
);
1193 alcDefaultAllDevicesSpecifier
= NULL
;
1194 free(alcCaptureDefaultDeviceSpecifier
);
1195 alcCaptureDefaultDeviceSpecifier
= NULL
;
1197 if((dev
=ATOMIC_EXCHANGE(ALCdevice
*, &DeviceList
, NULL
)) != NULL
)
1202 } while((dev
=dev
->next
) != NULL
);
1203 ERR("%u device%s not closed\n", num
, (num
>1)?"s":"");
1206 DeinitEffectFactoryMap();
1209 static void alc_deinit_safe(void)
1217 almtx_destroy(&ListLock
);
1218 altss_delete(LocalContext
);
1220 if(LogFile
!= stderr
)
1225 static void alc_deinit(void)
1231 memset(&PlaybackBackend
, 0, sizeof(PlaybackBackend
));
1232 memset(&CaptureBackend
, 0, sizeof(CaptureBackend
));
1234 for(i
= 0;BackendList
[i
].Deinit
|| BackendList
[i
].getFactory
;i
++)
1236 if(!BackendList
[i
].getFactory
)
1237 BackendList
[i
].Deinit();
1240 ALCbackendFactory
*factory
= BackendList
[i
].getFactory();
1241 V0(factory
,deinit
)();
1245 ALCbackendFactory
*factory
= ALCloopbackFactory_getFactory();
1246 V0(factory
,deinit
)();
1253 /************************************************
1254 * Device enumeration
1255 ************************************************/
1256 static void ProbeDevices(al_string
*list
, enum DevProbe type
)
1261 al_string_clear(list
);
1263 if(type
== ALL_DEVICE_PROBE
&& (PlaybackBackend
.Probe
|| PlaybackBackend
.getFactory
))
1265 if(!PlaybackBackend
.getFactory
)
1266 PlaybackBackend
.Probe(type
);
1269 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
1270 V(factory
,probe
)(type
);
1273 else if(type
== CAPTURE_DEVICE_PROBE
&& (CaptureBackend
.Probe
|| CaptureBackend
.getFactory
))
1275 if(!CaptureBackend
.getFactory
)
1276 CaptureBackend
.Probe(type
);
1279 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
1280 V(factory
,probe
)(type
);
1285 static void ProbeAllDevicesList(void)
1286 { ProbeDevices(&alcAllDevicesList
, ALL_DEVICE_PROBE
); }
1287 static void ProbeCaptureDeviceList(void)
1288 { ProbeDevices(&alcCaptureDeviceList
, CAPTURE_DEVICE_PROBE
); }
1290 static void AppendDevice(const ALCchar
*name
, al_string
*devnames
)
1292 size_t len
= strlen(name
);
1294 al_string_append_range(devnames
, name
, name
+len
+1);
1296 void AppendAllDevicesList(const ALCchar
*name
)
1297 { AppendDevice(name
, &alcAllDevicesList
); }
1298 void AppendCaptureDeviceList(const ALCchar
*name
)
1299 { AppendDevice(name
, &alcCaptureDeviceList
); }
1302 /************************************************
1303 * Device format information
1304 ************************************************/
1305 const ALCchar
*DevFmtTypeString(enum DevFmtType type
)
1309 case DevFmtByte
: return "Signed Byte";
1310 case DevFmtUByte
: return "Unsigned Byte";
1311 case DevFmtShort
: return "Signed Short";
1312 case DevFmtUShort
: return "Unsigned Short";
1313 case DevFmtInt
: return "Signed Int";
1314 case DevFmtUInt
: return "Unsigned Int";
1315 case DevFmtFloat
: return "Float";
1317 return "(unknown type)";
1319 const ALCchar
*DevFmtChannelsString(enum DevFmtChannels chans
)
1323 case DevFmtMono
: return "Mono";
1324 case DevFmtStereo
: return "Stereo";
1325 case DevFmtQuad
: return "Quadraphonic";
1326 case DevFmtX51
: return "5.1 Surround";
1327 case DevFmtX51Rear
: return "5.1 Surround (Rear)";
1328 case DevFmtX61
: return "6.1 Surround";
1329 case DevFmtX71
: return "7.1 Surround";
1331 return "(unknown channels)";
1334 extern inline ALuint
FrameSizeFromDevFmt(enum DevFmtChannels chans
, enum DevFmtType type
);
1335 ALuint
BytesFromDevFmt(enum DevFmtType type
)
1339 case DevFmtByte
: return sizeof(ALbyte
);
1340 case DevFmtUByte
: return sizeof(ALubyte
);
1341 case DevFmtShort
: return sizeof(ALshort
);
1342 case DevFmtUShort
: return sizeof(ALushort
);
1343 case DevFmtInt
: return sizeof(ALint
);
1344 case DevFmtUInt
: return sizeof(ALuint
);
1345 case DevFmtFloat
: return sizeof(ALfloat
);
1349 ALuint
ChannelsFromDevFmt(enum DevFmtChannels chans
)
1353 case DevFmtMono
: return 1;
1354 case DevFmtStereo
: return 2;
1355 case DevFmtQuad
: return 4;
1356 case DevFmtX51
: return 6;
1357 case DevFmtX51Rear
: return 6;
1358 case DevFmtX61
: return 7;
1359 case DevFmtX71
: return 8;
1364 DECL_CONST
static ALboolean
DecomposeDevFormat(ALenum format
,
1365 enum DevFmtChannels
*chans
, enum DevFmtType
*type
)
1367 static const struct {
1369 enum DevFmtChannels channels
;
1370 enum DevFmtType type
;
1372 { AL_FORMAT_MONO8
, DevFmtMono
, DevFmtUByte
},
1373 { AL_FORMAT_MONO16
, DevFmtMono
, DevFmtShort
},
1374 { AL_FORMAT_MONO_FLOAT32
, DevFmtMono
, DevFmtFloat
},
1376 { AL_FORMAT_STEREO8
, DevFmtStereo
, DevFmtUByte
},
1377 { AL_FORMAT_STEREO16
, DevFmtStereo
, DevFmtShort
},
1378 { AL_FORMAT_STEREO_FLOAT32
, DevFmtStereo
, DevFmtFloat
},
1380 { AL_FORMAT_QUAD8
, DevFmtQuad
, DevFmtUByte
},
1381 { AL_FORMAT_QUAD16
, DevFmtQuad
, DevFmtShort
},
1382 { AL_FORMAT_QUAD32
, DevFmtQuad
, DevFmtFloat
},
1384 { AL_FORMAT_51CHN8
, DevFmtX51
, DevFmtUByte
},
1385 { AL_FORMAT_51CHN16
, DevFmtX51
, DevFmtShort
},
1386 { AL_FORMAT_51CHN32
, DevFmtX51
, DevFmtFloat
},
1388 { AL_FORMAT_61CHN8
, DevFmtX61
, DevFmtUByte
},
1389 { AL_FORMAT_61CHN16
, DevFmtX61
, DevFmtShort
},
1390 { AL_FORMAT_61CHN32
, DevFmtX61
, DevFmtFloat
},
1392 { AL_FORMAT_71CHN8
, DevFmtX71
, DevFmtUByte
},
1393 { AL_FORMAT_71CHN16
, DevFmtX71
, DevFmtShort
},
1394 { AL_FORMAT_71CHN32
, DevFmtX71
, DevFmtFloat
},
1398 for(i
= 0;i
< COUNTOF(list
);i
++)
1400 if(list
[i
].format
== format
)
1402 *chans
= list
[i
].channels
;
1403 *type
= list
[i
].type
;
1411 DECL_CONST
static ALCboolean
IsValidALCType(ALCenum type
)
1416 case ALC_UNSIGNED_BYTE_SOFT
:
1417 case ALC_SHORT_SOFT
:
1418 case ALC_UNSIGNED_SHORT_SOFT
:
1420 case ALC_UNSIGNED_INT_SOFT
:
1421 case ALC_FLOAT_SOFT
:
1427 DECL_CONST
static ALCboolean
IsValidALCChannels(ALCenum channels
)
1432 case ALC_STEREO_SOFT
:
1434 case ALC_5POINT1_SOFT
:
1435 case ALC_6POINT1_SOFT
:
1436 case ALC_7POINT1_SOFT
:
1443 /************************************************
1444 * Miscellaneous ALC helpers
1445 ************************************************/
1446 extern inline void LockContext(ALCcontext
*context
);
1447 extern inline void UnlockContext(ALCcontext
*context
);
1449 ALint64
ALCdevice_GetLatency(ALCdevice
*device
)
1451 return V0(device
->Backend
,getLatency
)();
1454 void ALCdevice_Lock(ALCdevice
*device
)
1456 V0(device
->Backend
,lock
)();
1459 void ALCdevice_Unlock(ALCdevice
*device
)
1461 V0(device
->Backend
,unlock
)();
1465 /* SetDefaultWFXChannelOrder
1467 * Sets the default channel order used by WaveFormatEx.
1469 void SetDefaultWFXChannelOrder(ALCdevice
*device
)
1473 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1474 device
->ChannelName
[i
] = InvalidChannel
;
1476 switch(device
->FmtChans
)
1479 device
->ChannelName
[0] = FrontCenter
;
1482 device
->ChannelName
[0] = FrontLeft
;
1483 device
->ChannelName
[1] = FrontRight
;
1486 device
->ChannelName
[0] = FrontLeft
;
1487 device
->ChannelName
[1] = FrontRight
;
1488 device
->ChannelName
[2] = BackLeft
;
1489 device
->ChannelName
[3] = BackRight
;
1492 device
->ChannelName
[0] = FrontLeft
;
1493 device
->ChannelName
[1] = FrontRight
;
1494 device
->ChannelName
[2] = FrontCenter
;
1495 device
->ChannelName
[3] = LFE
;
1496 device
->ChannelName
[4] = SideLeft
;
1497 device
->ChannelName
[5] = SideRight
;
1500 device
->ChannelName
[0] = FrontLeft
;
1501 device
->ChannelName
[1] = FrontRight
;
1502 device
->ChannelName
[2] = FrontCenter
;
1503 device
->ChannelName
[3] = LFE
;
1504 device
->ChannelName
[4] = BackLeft
;
1505 device
->ChannelName
[5] = BackRight
;
1508 device
->ChannelName
[0] = FrontLeft
;
1509 device
->ChannelName
[1] = FrontRight
;
1510 device
->ChannelName
[2] = FrontCenter
;
1511 device
->ChannelName
[3] = LFE
;
1512 device
->ChannelName
[4] = BackCenter
;
1513 device
->ChannelName
[5] = SideLeft
;
1514 device
->ChannelName
[6] = SideRight
;
1517 device
->ChannelName
[0] = FrontLeft
;
1518 device
->ChannelName
[1] = FrontRight
;
1519 device
->ChannelName
[2] = FrontCenter
;
1520 device
->ChannelName
[3] = LFE
;
1521 device
->ChannelName
[4] = BackLeft
;
1522 device
->ChannelName
[5] = BackRight
;
1523 device
->ChannelName
[6] = SideLeft
;
1524 device
->ChannelName
[7] = SideRight
;
1529 /* SetDefaultChannelOrder
1531 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1533 void SetDefaultChannelOrder(ALCdevice
*device
)
1537 for(i
= 0;i
< MAX_OUTPUT_CHANNELS
;i
++)
1538 device
->ChannelName
[i
] = InvalidChannel
;
1540 switch(device
->FmtChans
)
1543 device
->ChannelName
[0] = FrontLeft
;
1544 device
->ChannelName
[1] = FrontRight
;
1545 device
->ChannelName
[2] = BackLeft
;
1546 device
->ChannelName
[3] = BackRight
;
1547 device
->ChannelName
[4] = FrontCenter
;
1548 device
->ChannelName
[5] = LFE
;
1551 device
->ChannelName
[0] = FrontLeft
;
1552 device
->ChannelName
[1] = FrontRight
;
1553 device
->ChannelName
[2] = BackLeft
;
1554 device
->ChannelName
[3] = BackRight
;
1555 device
->ChannelName
[4] = FrontCenter
;
1556 device
->ChannelName
[5] = LFE
;
1557 device
->ChannelName
[6] = SideLeft
;
1558 device
->ChannelName
[7] = SideRight
;
1561 /* Same as WFX order */
1567 SetDefaultWFXChannelOrder(device
);
1572 extern inline ALint
GetChannelIdxByName(const ALCdevice
*device
, enum Channel chan
);
1575 /* ALCcontext_DeferUpdates
1577 * Defers/suspends updates for the given context's listener and sources. This
1578 * does *NOT* stop mixing, but rather prevents certain property changes from
1581 void ALCcontext_DeferUpdates(ALCcontext
*context
)
1583 ALCdevice
*device
= context
->Device
;
1586 SetMixerFPUMode(&oldMode
);
1588 V0(device
->Backend
,lock
)();
1589 if(!ExchangeInt(&context
->DeferUpdates
, AL_TRUE
))
1591 ALboolean UpdateSources
;
1592 ALvoice
*voice
, *voice_end
;
1593 ALeffectslot
**slot
, **slot_end
;
1594 /* Make sure all pending updates are performed */
1595 UpdateSources
= ATOMIC_EXCHANGE(ALenum
, &context
->UpdateSources
, AL_FALSE
);
1597 voice
= context
->Voices
;
1598 voice_end
= voice
+ context
->VoiceCount
;
1599 while(voice
!= voice_end
)
1601 ALsource
*source
= voice
->Source
;
1602 if(!source
) goto next
;
1604 if(source
->state
!= AL_PLAYING
&& source
->state
!= AL_PAUSED
)
1606 voice
->Source
= NULL
;
1610 if(ATOMIC_EXCHANGE(ALenum
, &source
->NeedsUpdate
, AL_FALSE
) || UpdateSources
)
1611 voice
->Update(voice
, source
, context
);
1616 slot
= VECTOR_ITER_BEGIN(context
->ActiveAuxSlots
);
1617 slot_end
= VECTOR_ITER_END(context
->ActiveAuxSlots
);
1618 while(slot
!= slot_end
)
1620 if(ATOMIC_EXCHANGE(ALenum
, &(*slot
)->NeedsUpdate
, AL_FALSE
))
1621 V((*slot
)->EffectState
,update
)(context
->Device
, *slot
);
1625 V0(device
->Backend
,unlock
)();
1627 RestoreFPUMode(&oldMode
);
1630 /* ALCcontext_ProcessUpdates
1632 * Resumes update processing after being deferred.
1634 void ALCcontext_ProcessUpdates(ALCcontext
*context
)
1636 ALCdevice
*device
= context
->Device
;
1638 V0(device
->Backend
,lock
)();
1639 if(ExchangeInt(&context
->DeferUpdates
, AL_FALSE
))
1643 LockUIntMapRead(&context
->SourceMap
);
1644 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
1646 ALsource
*Source
= context
->SourceMap
.array
[pos
].value
;
1649 if((Source
->state
== AL_PLAYING
|| Source
->state
== AL_PAUSED
) &&
1650 Source
->Offset
>= 0.0)
1652 ReadLock(&Source
->queue_lock
);
1653 ApplyOffset(Source
);
1654 ReadUnlock(&Source
->queue_lock
);
1657 new_state
= ExchangeInt(&Source
->new_state
, AL_NONE
);
1659 SetSourceState(Source
, context
, new_state
);
1661 UnlockUIntMapRead(&context
->SourceMap
);
1663 V0(device
->Backend
,unlock
)();
1669 * Stores the latest ALC device error
1671 static void alcSetError(ALCdevice
*device
, ALCenum errorCode
)
1676 /* DebugBreak() will cause an exception if there is no debugger */
1677 if(IsDebuggerPresent())
1679 #elif defined(SIGTRAP)
1685 ATOMIC_STORE(&device
->LastError
, errorCode
);
1687 ATOMIC_STORE(&LastNullDeviceError
, errorCode
);
1693 * Updates the device's base clock time with however many samples have been
1694 * done. This is used so frequency changes on the device don't cause the time
1695 * to jump forward or back.
1697 static inline void UpdateClockBase(ALCdevice
*device
)
1699 device
->ClockBase
+= device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
;
1700 device
->SamplesDone
= 0;
1703 /* UpdateDeviceParams
1705 * Updates device parameters according to the attribute list (caller is
1706 * responsible for holding the list lock).
1708 static ALCenum
UpdateDeviceParams(ALCdevice
*device
, const ALCint
*attrList
)
1710 ALCcontext
*context
;
1711 enum DevFmtChannels oldChans
;
1712 enum DevFmtType oldType
;
1716 // Check for attributes
1717 if(device
->Type
== Loopback
)
1723 GotAll
= GotFreq
|GotChans
|GotType
1725 ALCuint freq
, numMono
, numStereo
, numSends
, flags
;
1726 enum DevFmtChannels schans
;
1727 enum DevFmtType stype
;
1728 ALCuint attrIdx
= 0;
1733 WARN("Missing attributes for loopback device\n");
1734 return ALC_INVALID_VALUE
;
1737 numMono
= device
->NumMonoSources
;
1738 numStereo
= device
->NumStereoSources
;
1739 numSends
= device
->NumAuxSends
;
1740 schans
= device
->FmtChans
;
1741 stype
= device
->FmtType
;
1742 freq
= device
->Frequency
;
1743 flags
= device
->Flags
;
1745 while(attrList
[attrIdx
])
1747 if(attrList
[attrIdx
] == ALC_FORMAT_CHANNELS_SOFT
)
1749 ALCint val
= attrList
[attrIdx
+ 1];
1750 if(!IsValidALCChannels(val
) || !ChannelsFromDevFmt(val
))
1751 return ALC_INVALID_VALUE
;
1756 if(attrList
[attrIdx
] == ALC_FORMAT_TYPE_SOFT
)
1758 ALCint val
= attrList
[attrIdx
+ 1];
1759 if(!IsValidALCType(val
) || !BytesFromDevFmt(val
))
1760 return ALC_INVALID_VALUE
;
1765 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1767 freq
= attrList
[attrIdx
+ 1];
1768 if(freq
< MIN_OUTPUT_RATE
)
1769 return ALC_INVALID_VALUE
;
1773 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1775 numStereo
= attrList
[attrIdx
+ 1];
1776 if(numStereo
> device
->MaxNoOfSources
)
1777 numStereo
= device
->MaxNoOfSources
;
1779 numMono
= device
->MaxNoOfSources
- numStereo
;
1782 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1783 numSends
= attrList
[attrIdx
+ 1];
1785 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1787 if(attrList
[attrIdx
+ 1] != ALC_FALSE
)
1788 flags
|= DEVICE_HRTF_REQUEST
;
1790 flags
&= ~DEVICE_HRTF_REQUEST
;
1796 if(gotFmt
!= GotAll
)
1798 WARN("Missing format for loopback device\n");
1799 return ALC_INVALID_VALUE
;
1802 ConfigValueUInt(NULL
, "sends", &numSends
);
1803 numSends
= minu(MAX_SENDS
, numSends
);
1805 if((device
->Flags
&DEVICE_RUNNING
))
1806 V0(device
->Backend
,stop
)();
1807 device
->Flags
= (flags
& ~DEVICE_RUNNING
);
1809 UpdateClockBase(device
);
1811 device
->Frequency
= freq
;
1812 device
->FmtChans
= schans
;
1813 device
->FmtType
= stype
;
1814 device
->NumMonoSources
= numMono
;
1815 device
->NumStereoSources
= numStereo
;
1816 device
->NumAuxSends
= numSends
;
1818 else if(attrList
&& attrList
[0])
1820 ALCuint freq
, numMono
, numStereo
, numSends
;
1821 ALCuint attrIdx
= 0;
1823 /* If a context is already running on the device, stop playback so the
1824 * device attributes can be updated. */
1825 if((device
->Flags
&DEVICE_RUNNING
))
1826 V0(device
->Backend
,stop
)();
1827 device
->Flags
&= ~DEVICE_RUNNING
;
1829 freq
= device
->Frequency
;
1830 numMono
= device
->NumMonoSources
;
1831 numStereo
= device
->NumStereoSources
;
1832 numSends
= device
->NumAuxSends
;
1834 while(attrList
[attrIdx
])
1836 if(attrList
[attrIdx
] == ALC_FREQUENCY
)
1838 freq
= attrList
[attrIdx
+ 1];
1839 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
1842 if(attrList
[attrIdx
] == ALC_STEREO_SOURCES
)
1844 numStereo
= attrList
[attrIdx
+ 1];
1845 if(numStereo
> device
->MaxNoOfSources
)
1846 numStereo
= device
->MaxNoOfSources
;
1848 numMono
= device
->MaxNoOfSources
- numStereo
;
1851 if(attrList
[attrIdx
] == ALC_MAX_AUXILIARY_SENDS
)
1852 numSends
= attrList
[attrIdx
+ 1];
1854 if(attrList
[attrIdx
] == ALC_HRTF_SOFT
)
1856 if(attrList
[attrIdx
+ 1] != ALC_FALSE
)
1857 device
->Flags
|= DEVICE_HRTF_REQUEST
;
1859 device
->Flags
&= ~DEVICE_HRTF_REQUEST
;
1865 ConfigValueUInt(NULL
, "frequency", &freq
);
1866 freq
= maxu(freq
, MIN_OUTPUT_RATE
);
1868 ConfigValueUInt(NULL
, "sends", &numSends
);
1869 numSends
= minu(MAX_SENDS
, numSends
);
1871 UpdateClockBase(device
);
1873 device
->UpdateSize
= (ALuint64
)device
->UpdateSize
* freq
/
1875 /* SSE and Neon do best with the update size being a multiple of 4 */
1876 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
1877 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
1879 device
->Frequency
= freq
;
1880 device
->NumMonoSources
= numMono
;
1881 device
->NumStereoSources
= numStereo
;
1882 device
->NumAuxSends
= numSends
;
1885 if((device
->Flags
&DEVICE_RUNNING
))
1886 return ALC_NO_ERROR
;
1888 UpdateClockBase(device
);
1890 if(device
->Type
!= Loopback
)
1892 bool usehrtf
= !!(device
->Flags
&DEVICE_HRTF_REQUEST
);
1893 if(GetConfigValueBool(NULL
, "hrtf", usehrtf
))
1894 device
->Flags
|= DEVICE_HRTF_REQUEST
;
1896 device
->Flags
&= ~DEVICE_HRTF_REQUEST
;
1898 if((device
->Flags
&DEVICE_HRTF_REQUEST
))
1900 enum DevFmtChannels chans
= device
->FmtChans
;
1901 ALCuint freq
= device
->Frequency
;
1902 if(FindHrtfFormat(&chans
, &freq
))
1904 if(device
->Type
!= Loopback
)
1906 device
->Frequency
= freq
;
1907 device
->FmtChans
= chans
;
1908 device
->Flags
|= DEVICE_CHANNELS_REQUEST
|
1909 DEVICE_FREQUENCY_REQUEST
;
1911 else if(device
->Frequency
!= freq
|| device
->FmtChans
!= chans
)
1913 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1914 DevFmtChannelsString(device
->FmtChans
), device
->Frequency
);
1915 device
->Flags
&= ~DEVICE_HRTF_REQUEST
;
1920 oldFreq
= device
->Frequency
;
1921 oldChans
= device
->FmtChans
;
1922 oldType
= device
->FmtType
;
1924 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1925 (device
->Flags
&DEVICE_CHANNELS_REQUEST
)?"*":"",
1926 DevFmtChannelsString(device
->FmtChans
),
1927 (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
)?"*":"",
1928 DevFmtTypeString(device
->FmtType
),
1929 (device
->Flags
&DEVICE_FREQUENCY_REQUEST
)?"*":"",
1931 device
->UpdateSize
, device
->NumUpdates
);
1933 if(V0(device
->Backend
,reset
)() == ALC_FALSE
)
1934 return ALC_INVALID_DEVICE
;
1936 if(device
->FmtChans
!= oldChans
&& (device
->Flags
&DEVICE_CHANNELS_REQUEST
))
1938 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans
),
1939 DevFmtChannelsString(device
->FmtChans
));
1940 device
->Flags
&= ~DEVICE_CHANNELS_REQUEST
;
1942 if(device
->FmtType
!= oldType
&& (device
->Flags
&DEVICE_SAMPLE_TYPE_REQUEST
))
1944 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType
),
1945 DevFmtTypeString(device
->FmtType
));
1946 device
->Flags
&= ~DEVICE_SAMPLE_TYPE_REQUEST
;
1948 if(device
->Frequency
!= oldFreq
&& (device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
1950 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq
, device
->Frequency
);
1951 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
1954 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1955 DevFmtChannelsString(device
->FmtChans
),
1956 DevFmtTypeString(device
->FmtType
), device
->Frequency
,
1957 device
->UpdateSize
, device
->NumUpdates
);
1959 aluInitPanning(device
);
1961 V(device
->Synth
,update
)(device
);
1963 device
->Hrtf
= NULL
;
1964 if((device
->Flags
&DEVICE_HRTF_REQUEST
))
1966 device
->Hrtf
= GetHrtf(device
->FmtChans
, device
->Frequency
);
1968 device
->Flags
&= ~DEVICE_HRTF_REQUEST
;
1970 TRACE("HRTF %s\n", device
->Hrtf
?"enabled":"disabled");
1972 if(!device
->Hrtf
&& device
->Bs2bLevel
> 0 && device
->Bs2bLevel
<= 6 &&
1973 device
->FmtChans
== DevFmtStereo
)
1977 device
->Bs2b
= calloc(1, sizeof(*device
->Bs2b
));
1978 bs2b_clear(device
->Bs2b
);
1980 bs2b_set_srate(device
->Bs2b
, device
->Frequency
);
1981 bs2b_set_level(device
->Bs2b
, device
->Bs2bLevel
);
1982 TRACE("BS2B level %d\n", device
->Bs2bLevel
);
1987 device
->Bs2b
= NULL
;
1988 TRACE("BS2B disabled\n");
1991 if(!device
->Hrtf
&& (device
->UpdateSize
&3))
1993 if((CPUCapFlags
&CPU_CAP_SSE
))
1994 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
1995 if((CPUCapFlags
&CPU_CAP_NEON
))
1996 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device
->UpdateSize
);
1999 SetMixerFPUMode(&oldMode
);
2000 V0(device
->Backend
,lock
)();
2001 context
= ATOMIC_LOAD(&device
->ContextList
);
2006 ATOMIC_STORE(&context
->UpdateSources
, AL_FALSE
);
2007 LockUIntMapRead(&context
->EffectSlotMap
);
2008 for(pos
= 0;pos
< context
->EffectSlotMap
.size
;pos
++)
2010 ALeffectslot
*slot
= context
->EffectSlotMap
.array
[pos
].value
;
2012 if(V(slot
->EffectState
,deviceUpdate
)(device
) == AL_FALSE
)
2014 UnlockUIntMapRead(&context
->EffectSlotMap
);
2015 V0(device
->Backend
,unlock
)();
2016 RestoreFPUMode(&oldMode
);
2017 return ALC_INVALID_DEVICE
;
2019 ATOMIC_STORE(&slot
->NeedsUpdate
, AL_FALSE
);
2020 V(slot
->EffectState
,update
)(device
, slot
);
2022 UnlockUIntMapRead(&context
->EffectSlotMap
);
2024 LockUIntMapRead(&context
->SourceMap
);
2025 for(pos
= 0;pos
< context
->SourceMap
.size
;pos
++)
2027 ALsource
*source
= context
->SourceMap
.array
[pos
].value
;
2028 ALuint s
= device
->NumAuxSends
;
2029 while(s
< MAX_SENDS
)
2031 if(source
->Send
[s
].Slot
)
2032 DecrementRef(&source
->Send
[s
].Slot
->ref
);
2033 source
->Send
[s
].Slot
= NULL
;
2034 source
->Send
[s
].Gain
= 1.0f
;
2035 source
->Send
[s
].GainHF
= 1.0f
;
2038 ATOMIC_STORE(&source
->NeedsUpdate
, AL_TRUE
);
2040 UnlockUIntMapRead(&context
->SourceMap
);
2042 for(pos
= 0;pos
< context
->VoiceCount
;pos
++)
2044 ALvoice
*voice
= &context
->Voices
[pos
];
2045 ALsource
*source
= voice
->Source
;
2046 ALuint s
= device
->NumAuxSends
;
2048 while(s
< MAX_SENDS
)
2050 voice
->Send
[s
].Moving
= AL_FALSE
;
2051 voice
->Send
[s
].Counter
= 0;
2057 ATOMIC_STORE(&source
->NeedsUpdate
, AL_FALSE
);
2058 voice
->Update(voice
, source
, context
);
2062 context
= context
->next
;
2064 if(device
->DefaultSlot
)
2066 ALeffectslot
*slot
= device
->DefaultSlot
;
2068 if(V(slot
->EffectState
,deviceUpdate
)(device
) == AL_FALSE
)
2070 V0(device
->Backend
,unlock
)();
2071 RestoreFPUMode(&oldMode
);
2072 return ALC_INVALID_DEVICE
;
2074 ATOMIC_STORE(&slot
->NeedsUpdate
, AL_FALSE
);
2075 V(slot
->EffectState
,update
)(device
, slot
);
2077 V0(device
->Backend
,unlock
)();
2078 RestoreFPUMode(&oldMode
);
2080 if(!(device
->Flags
&DEVICE_PAUSED
))
2082 if(V0(device
->Backend
,start
)() == ALC_FALSE
)
2083 return ALC_INVALID_DEVICE
;
2084 device
->Flags
|= DEVICE_RUNNING
;
2087 return ALC_NO_ERROR
;
2092 * Frees the device structure, and destroys any objects the app failed to
2093 * delete. Called once there's no more references on the device.
2095 static ALCvoid
FreeDevice(ALCdevice
*device
)
2097 TRACE("%p\n", device
);
2099 V0(device
->Backend
,close
)();
2100 DELETE_OBJ(device
->Backend
);
2101 device
->Backend
= NULL
;
2103 DELETE_OBJ(device
->Synth
);
2104 device
->Synth
= NULL
;
2106 if(device
->DefaultSlot
)
2108 ALeffectState
*state
= device
->DefaultSlot
->EffectState
;
2109 device
->DefaultSlot
= NULL
;
2113 if(device
->DefaultSfont
)
2114 ALsoundfont_deleteSoundfont(device
->DefaultSfont
, device
);
2115 device
->DefaultSfont
= NULL
;
2117 if(device
->BufferMap
.size
> 0)
2119 WARN("(%p) Deleting %d Buffer(s)\n", device
, device
->BufferMap
.size
);
2120 ReleaseALBuffers(device
);
2122 ResetUIntMap(&device
->BufferMap
);
2124 if(device
->EffectMap
.size
> 0)
2126 WARN("(%p) Deleting %d Effect(s)\n", device
, device
->EffectMap
.size
);
2127 ReleaseALEffects(device
);
2129 ResetUIntMap(&device
->EffectMap
);
2131 if(device
->FilterMap
.size
> 0)
2133 WARN("(%p) Deleting %d Filter(s)\n", device
, device
->FilterMap
.size
);
2134 ReleaseALFilters(device
);
2136 ResetUIntMap(&device
->FilterMap
);
2138 if(device
->SfontMap
.size
> 0)
2140 WARN("(%p) Deleting %d Soundfont(s)\n", device
, device
->SfontMap
.size
);
2141 ReleaseALSoundfonts(device
);
2143 ResetUIntMap(&device
->SfontMap
);
2145 if(device
->PresetMap
.size
> 0)
2147 WARN("(%p) Deleting %d Preset(s)\n", device
, device
->PresetMap
.size
);
2148 ReleaseALPresets(device
);
2150 ResetUIntMap(&device
->PresetMap
);
2152 if(device
->FontsoundMap
.size
> 0)
2154 WARN("(%p) Deleting %d Fontsound(s)\n", device
, device
->FontsoundMap
.size
);
2155 ReleaseALFontsounds(device
);
2157 ResetUIntMap(&device
->FontsoundMap
);
2160 device
->Bs2b
= NULL
;
2162 AL_STRING_DEINIT(device
->DeviceName
);
2168 void ALCdevice_IncRef(ALCdevice
*device
)
2171 ref
= IncrementRef(&device
->ref
);
2172 TRACEREF("%p increasing refcount to %u\n", device
, ref
);
2175 void ALCdevice_DecRef(ALCdevice
*device
)
2178 ref
= DecrementRef(&device
->ref
);
2179 TRACEREF("%p decreasing refcount to %u\n", device
, ref
);
2180 if(ref
== 0) FreeDevice(device
);
2185 * Checks if the device handle is valid, and increments its ref count if so.
2187 static ALCdevice
*VerifyDevice(ALCdevice
*device
)
2189 ALCdevice
*tmpDevice
;
2195 tmpDevice
= ATOMIC_LOAD(&DeviceList
);
2196 while(tmpDevice
&& tmpDevice
!= device
)
2197 tmpDevice
= tmpDevice
->next
;
2200 ALCdevice_IncRef(tmpDevice
);
2208 * Initializes context fields
2210 static ALvoid
InitContext(ALCcontext
*Context
)
2214 //Initialise listener
2215 Context
->Listener
->Gain
= 1.0f
;
2216 Context
->Listener
->MetersPerUnit
= 1.0f
;
2217 Context
->Listener
->Position
[0] = 0.0f
;
2218 Context
->Listener
->Position
[1] = 0.0f
;
2219 Context
->Listener
->Position
[2] = 0.0f
;
2220 Context
->Listener
->Velocity
[0] = 0.0f
;
2221 Context
->Listener
->Velocity
[1] = 0.0f
;
2222 Context
->Listener
->Velocity
[2] = 0.0f
;
2223 Context
->Listener
->Forward
[0] = 0.0f
;
2224 Context
->Listener
->Forward
[1] = 0.0f
;
2225 Context
->Listener
->Forward
[2] = -1.0f
;
2226 Context
->Listener
->Up
[0] = 0.0f
;
2227 Context
->Listener
->Up
[1] = 1.0f
;
2228 Context
->Listener
->Up
[2] = 0.0f
;
2229 for(i
= 0;i
< 4;i
++)
2231 for(j
= 0;j
< 4;j
++)
2232 Context
->Listener
->Params
.Matrix
[i
][j
] = ((i
==j
) ? 1.0f
: 0.0f
);
2234 for(i
= 0;i
< 3;i
++)
2235 Context
->Listener
->Params
.Velocity
[i
] = 0.0f
;
2238 ATOMIC_INIT(&Context
->LastError
, AL_NO_ERROR
);
2239 ATOMIC_INIT(&Context
->UpdateSources
, AL_FALSE
);
2240 InitUIntMap(&Context
->SourceMap
, Context
->Device
->MaxNoOfSources
);
2241 InitUIntMap(&Context
->EffectSlotMap
, Context
->Device
->AuxiliaryEffectSlotMax
);
2244 Context
->DistanceModel
= DefaultDistanceModel
;
2245 Context
->SourceDistanceModel
= AL_FALSE
;
2246 Context
->DopplerFactor
= 1.0f
;
2247 Context
->DopplerVelocity
= 1.0f
;
2248 Context
->SpeedOfSound
= SPEEDOFSOUNDMETRESPERSEC
;
2249 Context
->DeferUpdates
= AL_FALSE
;
2251 Context
->ExtensionList
= alExtList
;
2257 * Cleans up the context, and destroys any remaining objects the app failed to
2258 * delete. Called once there's no more references on the context.
2260 static void FreeContext(ALCcontext
*context
)
2262 TRACE("%p\n", context
);
2264 if(context
->SourceMap
.size
> 0)
2266 WARN("(%p) Deleting %d Source(s)\n", context
, context
->SourceMap
.size
);
2267 ReleaseALSources(context
);
2269 ResetUIntMap(&context
->SourceMap
);
2271 if(context
->EffectSlotMap
.size
> 0)
2273 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context
, context
->EffectSlotMap
.size
);
2274 ReleaseALAuxiliaryEffectSlots(context
);
2276 ResetUIntMap(&context
->EffectSlotMap
);
2278 al_free(context
->Voices
);
2279 context
->Voices
= NULL
;
2280 context
->VoiceCount
= 0;
2281 context
->MaxVoices
= 0;
2283 VECTOR_DEINIT(context
->ActiveAuxSlots
);
2285 ALCdevice_DecRef(context
->Device
);
2286 context
->Device
= NULL
;
2288 //Invalidate context
2289 memset(context
, 0, sizeof(ALCcontext
));
2295 * Removes the context reference from the given device and removes it from
2296 * being current on the running thread or globally.
2298 static void ReleaseContext(ALCcontext
*context
, ALCdevice
*device
)
2300 ALCcontext
*nextctx
;
2301 ALCcontext
*origctx
;
2303 if(altss_get(LocalContext
) == context
)
2305 WARN("%p released while current on thread\n", context
);
2306 altss_set(LocalContext
, NULL
);
2307 ALCcontext_DecRef(context
);
2311 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext
*, &GlobalContext
, &origctx
, NULL
))
2312 ALCcontext_DecRef(context
);
2314 ALCdevice_Lock(device
);
2316 nextctx
= context
->next
;
2317 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext
*, &device
->ContextList
, &origctx
, nextctx
))
2323 } while(!COMPARE_EXCHANGE(&list
->next
, &origctx
, nextctx
));
2325 ALCdevice_Unlock(device
);
2327 ALCcontext_DecRef(context
);
2330 void ALCcontext_IncRef(ALCcontext
*context
)
2333 ref
= IncrementRef(&context
->ref
);
2334 TRACEREF("%p increasing refcount to %u\n", context
, ref
);
2337 void ALCcontext_DecRef(ALCcontext
*context
)
2340 ref
= DecrementRef(&context
->ref
);
2341 TRACEREF("%p decreasing refcount to %u\n", context
, ref
);
2342 if(ref
== 0) FreeContext(context
);
2345 static void ReleaseThreadCtx(void *ptr
)
2347 WARN("%p current for thread being destroyed\n", ptr
);
2348 ALCcontext_DecRef(ptr
);
2353 * Checks that the given context is valid, and increments its reference count.
2355 static ALCcontext
*VerifyContext(ALCcontext
*context
)
2360 dev
= ATOMIC_LOAD(&DeviceList
);
2363 ALCcontext
*ctx
= ATOMIC_LOAD(&dev
->ContextList
);
2368 ALCcontext_IncRef(ctx
);
2384 * Returns the currently active context for this thread, and adds a reference
2385 * without locking it.
2387 ALCcontext
*GetContextRef(void)
2389 ALCcontext
*context
;
2391 context
= altss_get(LocalContext
);
2393 ALCcontext_IncRef(context
);
2397 context
= ATOMIC_LOAD(&GlobalContext
);
2399 ALCcontext_IncRef(context
);
2407 /************************************************
2408 * Standard ALC functions
2409 ************************************************/
2413 * Return last ALC generated error code for the given device
2415 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
2419 if(VerifyDevice(device
))
2421 errorCode
= ATOMIC_EXCHANGE(ALCenum
, &device
->LastError
, ALC_NO_ERROR
);
2422 ALCdevice_DecRef(device
);
2425 errorCode
= ATOMIC_EXCHANGE(ALCenum
, &LastNullDeviceError
, ALC_NO_ERROR
);
2431 /* alcSuspendContext
2433 * Suspends updates for the given context
2435 ALC_API ALCvoid ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
2440 context
= VerifyContext(context
);
2442 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2445 ALCcontext_DeferUpdates(context
);
2446 ALCcontext_DecRef(context
);
2450 /* alcProcessContext
2452 * Resumes processing updates for the given context
2454 ALC_API ALCvoid ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
2459 context
= VerifyContext(context
);
2461 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
2464 ALCcontext_ProcessUpdates(context
);
2465 ALCcontext_DecRef(context
);
2472 * Returns information about the device, and error strings
2474 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*Device
, ALCenum param
)
2476 const ALCchar
*value
= NULL
;
2484 case ALC_INVALID_ENUM
:
2485 value
= alcErrInvalidEnum
;
2488 case ALC_INVALID_VALUE
:
2489 value
= alcErrInvalidValue
;
2492 case ALC_INVALID_DEVICE
:
2493 value
= alcErrInvalidDevice
;
2496 case ALC_INVALID_CONTEXT
:
2497 value
= alcErrInvalidContext
;
2500 case ALC_OUT_OF_MEMORY
:
2501 value
= alcErrOutOfMemory
;
2504 case ALC_DEVICE_SPECIFIER
:
2505 value
= alcDefaultName
;
2508 case ALC_ALL_DEVICES_SPECIFIER
:
2509 if(VerifyDevice(Device
))
2511 value
= al_string_get_cstr(Device
->DeviceName
);
2512 ALCdevice_DecRef(Device
);
2516 ProbeAllDevicesList();
2517 value
= al_string_get_cstr(alcAllDevicesList
);
2521 case ALC_CAPTURE_DEVICE_SPECIFIER
:
2522 if(VerifyDevice(Device
))
2524 value
= al_string_get_cstr(Device
->DeviceName
);
2525 ALCdevice_DecRef(Device
);
2529 ProbeCaptureDeviceList();
2530 value
= al_string_get_cstr(alcCaptureDeviceList
);
2534 /* Default devices are always first in the list */
2535 case ALC_DEFAULT_DEVICE_SPECIFIER
:
2536 value
= alcDefaultName
;
2539 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
2540 if(al_string_empty(alcAllDevicesList
))
2541 ProbeAllDevicesList();
2543 Device
= VerifyDevice(Device
);
2545 free(alcDefaultAllDevicesSpecifier
);
2546 alcDefaultAllDevicesSpecifier
= strdup(al_string_get_cstr(alcAllDevicesList
));
2547 if(!alcDefaultAllDevicesSpecifier
)
2548 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2550 value
= alcDefaultAllDevicesSpecifier
;
2551 if(Device
) ALCdevice_DecRef(Device
);
2554 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
2555 if(al_string_empty(alcCaptureDeviceList
))
2556 ProbeCaptureDeviceList();
2558 Device
= VerifyDevice(Device
);
2560 free(alcCaptureDefaultDeviceSpecifier
);
2561 alcCaptureDefaultDeviceSpecifier
= strdup(al_string_get_cstr(alcCaptureDeviceList
));
2562 if(!alcCaptureDefaultDeviceSpecifier
)
2563 alcSetError(Device
, ALC_OUT_OF_MEMORY
);
2565 value
= alcCaptureDefaultDeviceSpecifier
;
2566 if(Device
) ALCdevice_DecRef(Device
);
2569 case ALC_EXTENSIONS
:
2570 if(!VerifyDevice(Device
))
2571 value
= alcNoDeviceExtList
;
2574 value
= alcExtensionList
;
2575 ALCdevice_DecRef(Device
);
2580 Device
= VerifyDevice(Device
);
2581 alcSetError(Device
, ALC_INVALID_ENUM
);
2582 if(Device
) ALCdevice_DecRef(Device
);
2590 static ALCsizei
GetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2594 if(size
<= 0 || values
== NULL
)
2596 alcSetError(device
, ALC_INVALID_VALUE
);
2604 case ALC_MAJOR_VERSION
:
2605 values
[0] = alcMajorVersion
;
2607 case ALC_MINOR_VERSION
:
2608 values
[0] = alcMinorVersion
;
2611 case ALC_ATTRIBUTES_SIZE
:
2612 case ALC_ALL_ATTRIBUTES
:
2616 case ALC_MONO_SOURCES
:
2617 case ALC_STEREO_SOURCES
:
2618 case ALC_CAPTURE_SAMPLES
:
2619 case ALC_FORMAT_CHANNELS_SOFT
:
2620 case ALC_FORMAT_TYPE_SOFT
:
2621 alcSetError(NULL
, ALC_INVALID_DEVICE
);
2625 alcSetError(NULL
, ALC_INVALID_ENUM
);
2631 if(device
->Type
== Capture
)
2635 case ALC_CAPTURE_SAMPLES
:
2636 ALCdevice_Lock(device
);
2637 values
[0] = V0(device
->Backend
,availableSamples
)();
2638 ALCdevice_Unlock(device
);
2642 values
[0] = device
->Connected
;
2646 alcSetError(device
, ALC_INVALID_ENUM
);
2655 case ALC_MAJOR_VERSION
:
2656 values
[0] = alcMajorVersion
;
2659 case ALC_MINOR_VERSION
:
2660 values
[0] = alcMinorVersion
;
2663 case ALC_EFX_MAJOR_VERSION
:
2664 values
[0] = alcEFXMajorVersion
;
2667 case ALC_EFX_MINOR_VERSION
:
2668 values
[0] = alcEFXMinorVersion
;
2671 case ALC_ATTRIBUTES_SIZE
:
2675 case ALC_ALL_ATTRIBUTES
:
2678 alcSetError(device
, ALC_INVALID_VALUE
);
2683 values
[i
++] = ALC_FREQUENCY
;
2684 values
[i
++] = device
->Frequency
;
2686 if(device
->Type
!= Loopback
)
2688 values
[i
++] = ALC_REFRESH
;
2689 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2691 values
[i
++] = ALC_SYNC
;
2692 values
[i
++] = ALC_FALSE
;
2696 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2697 values
[i
++] = device
->FmtChans
;
2699 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2700 values
[i
++] = device
->FmtType
;
2703 values
[i
++] = ALC_MONO_SOURCES
;
2704 values
[i
++] = device
->NumMonoSources
;
2706 values
[i
++] = ALC_STEREO_SOURCES
;
2707 values
[i
++] = device
->NumStereoSources
;
2709 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2710 values
[i
++] = device
->NumAuxSends
;
2712 values
[i
++] = ALC_HRTF_SOFT
;
2713 values
[i
++] = (device
->Hrtf
? ALC_TRUE
: ALC_FALSE
);
2719 values
[0] = device
->Frequency
;
2723 if(device
->Type
== Loopback
)
2725 alcSetError(device
, ALC_INVALID_DEVICE
);
2728 values
[0] = device
->Frequency
/ device
->UpdateSize
;
2732 if(device
->Type
== Loopback
)
2734 alcSetError(device
, ALC_INVALID_DEVICE
);
2737 values
[0] = ALC_FALSE
;
2740 case ALC_FORMAT_CHANNELS_SOFT
:
2741 if(device
->Type
!= Loopback
)
2743 alcSetError(device
, ALC_INVALID_DEVICE
);
2746 values
[0] = device
->FmtChans
;
2749 case ALC_FORMAT_TYPE_SOFT
:
2750 if(device
->Type
!= Loopback
)
2752 alcSetError(device
, ALC_INVALID_DEVICE
);
2755 values
[0] = device
->FmtType
;
2758 case ALC_MONO_SOURCES
:
2759 values
[0] = device
->NumMonoSources
;
2762 case ALC_STEREO_SOURCES
:
2763 values
[0] = device
->NumStereoSources
;
2766 case ALC_MAX_AUXILIARY_SENDS
:
2767 values
[0] = device
->NumAuxSends
;
2771 values
[0] = device
->Connected
;
2775 values
[0] = (device
->Hrtf
? ALC_TRUE
: ALC_FALSE
);
2779 alcSetError(device
, ALC_INVALID_ENUM
);
2787 * Returns information about the device and the version of OpenAL
2789 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
2791 device
= VerifyDevice(device
);
2792 if(size
<= 0 || values
== NULL
)
2793 alcSetError(device
, ALC_INVALID_VALUE
);
2795 GetIntegerv(device
, param
, size
, values
);
2796 if(device
) ALCdevice_DecRef(device
);
2799 ALC_API
void ALC_APIENTRY
alcGetInteger64vSOFT(ALCdevice
*device
, ALCenum pname
, ALCsizei size
, ALCint64SOFT
*values
)
2804 device
= VerifyDevice(device
);
2805 if(size
<= 0 || values
== NULL
)
2806 alcSetError(device
, ALC_INVALID_VALUE
);
2807 else if(!device
|| device
->Type
== Capture
)
2809 ivals
= malloc(size
* sizeof(ALCint
));
2810 size
= GetIntegerv(device
, pname
, size
, ivals
);
2811 for(i
= 0;i
< size
;i
++)
2812 values
[i
] = ivals
[i
];
2815 else /* render device */
2819 case ALC_ATTRIBUTES_SIZE
:
2823 case ALC_ALL_ATTRIBUTES
:
2825 alcSetError(device
, ALC_INVALID_VALUE
);
2830 V0(device
->Backend
,lock
)();
2831 values
[i
++] = ALC_FREQUENCY
;
2832 values
[i
++] = device
->Frequency
;
2834 if(device
->Type
!= Loopback
)
2836 values
[i
++] = ALC_REFRESH
;
2837 values
[i
++] = device
->Frequency
/ device
->UpdateSize
;
2839 values
[i
++] = ALC_SYNC
;
2840 values
[i
++] = ALC_FALSE
;
2844 values
[i
++] = ALC_FORMAT_CHANNELS_SOFT
;
2845 values
[i
++] = device
->FmtChans
;
2847 values
[i
++] = ALC_FORMAT_TYPE_SOFT
;
2848 values
[i
++] = device
->FmtType
;
2851 values
[i
++] = ALC_MONO_SOURCES
;
2852 values
[i
++] = device
->NumMonoSources
;
2854 values
[i
++] = ALC_STEREO_SOURCES
;
2855 values
[i
++] = device
->NumStereoSources
;
2857 values
[i
++] = ALC_MAX_AUXILIARY_SENDS
;
2858 values
[i
++] = device
->NumAuxSends
;
2860 values
[i
++] = ALC_HRTF_SOFT
;
2861 values
[i
++] = (device
->Hrtf
? ALC_TRUE
: ALC_FALSE
);
2863 values
[i
++] = ALC_DEVICE_CLOCK_SOFT
;
2864 values
[i
++] = device
->ClockBase
+
2865 (device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
);
2868 V0(device
->Backend
,unlock
)();
2872 case ALC_DEVICE_CLOCK_SOFT
:
2873 V0(device
->Backend
,lock
)();
2874 *values
= device
->ClockBase
+
2875 (device
->SamplesDone
* DEVICE_CLOCK_RES
/ device
->Frequency
);
2876 V0(device
->Backend
,unlock
)();
2880 ivals
= malloc(size
* sizeof(ALCint
));
2881 size
= GetIntegerv(device
, pname
, size
, ivals
);
2882 for(i
= 0;i
< size
;i
++)
2883 values
[i
] = ivals
[i
];
2889 ALCdevice_DecRef(device
);
2893 /* alcIsExtensionPresent
2895 * Determines if there is support for a particular extension
2897 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extName
)
2899 ALCboolean bResult
= ALC_FALSE
;
2901 device
= VerifyDevice(device
);
2904 alcSetError(device
, ALC_INVALID_VALUE
);
2907 size_t len
= strlen(extName
);
2908 const char *ptr
= (device
? alcExtensionList
: alcNoDeviceExtList
);
2911 if(strncasecmp(ptr
, extName
, len
) == 0 &&
2912 (ptr
[len
] == '\0' || isspace(ptr
[len
])))
2917 if((ptr
=strchr(ptr
, ' ')) != NULL
)
2921 } while(isspace(*ptr
));
2926 ALCdevice_DecRef(device
);
2931 /* alcGetProcAddress
2933 * Retrieves the function address for a particular extension function
2935 ALC_API ALCvoid
* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcName
)
2937 ALCvoid
*ptr
= NULL
;
2941 device
= VerifyDevice(device
);
2942 alcSetError(device
, ALC_INVALID_VALUE
);
2943 if(device
) ALCdevice_DecRef(device
);
2948 while(alcFunctions
[i
].funcName
&& strcmp(alcFunctions
[i
].funcName
, funcName
) != 0)
2950 ptr
= alcFunctions
[i
].address
;
2959 * Get the value for a particular ALC enumeration name
2961 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumName
)
2967 device
= VerifyDevice(device
);
2968 alcSetError(device
, ALC_INVALID_VALUE
);
2969 if(device
) ALCdevice_DecRef(device
);
2974 while(enumeration
[i
].enumName
&& strcmp(enumeration
[i
].enumName
, enumName
) != 0)
2976 val
= enumeration
[i
].value
;
2985 * Create and attach a context to the given device.
2987 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrList
)
2989 ALCcontext
*ALContext
;
2993 if(!(device
=VerifyDevice(device
)) || device
->Type
== Capture
|| !device
->Connected
)
2996 alcSetError(device
, ALC_INVALID_DEVICE
);
2997 if(device
) ALCdevice_DecRef(device
);
3001 ATOMIC_STORE(&device
->LastError
, ALC_NO_ERROR
);
3003 if((err
=UpdateDeviceParams(device
, attrList
)) != ALC_NO_ERROR
)
3006 alcSetError(device
, err
);
3007 if(err
== ALC_INVALID_DEVICE
)
3009 ALCdevice_Lock(device
);
3010 aluHandleDisconnect(device
);
3011 ALCdevice_Unlock(device
);
3013 ALCdevice_DecRef(device
);
3017 ALContext
= al_calloc(16, sizeof(ALCcontext
)+sizeof(ALlistener
));
3020 InitRef(&ALContext
->ref
, 1);
3021 ALContext
->Listener
= (ALlistener
*)ALContext
->_listener_mem
;
3023 VECTOR_INIT(ALContext
->ActiveAuxSlots
);
3025 ALContext
->VoiceCount
= 0;
3026 ALContext
->MaxVoices
= 256;
3027 ALContext
->Voices
= al_calloc(16, ALContext
->MaxVoices
* sizeof(ALContext
->Voices
[0]));
3029 if(!ALContext
|| !ALContext
->Voices
)
3031 if(!ATOMIC_LOAD(&device
->ContextList
))
3033 V0(device
->Backend
,stop
)();
3034 device
->Flags
&= ~DEVICE_RUNNING
;
3040 al_free(ALContext
->Voices
);
3041 ALContext
->Voices
= NULL
;
3043 VECTOR_DEINIT(ALContext
->ActiveAuxSlots
);
3049 alcSetError(device
, ALC_OUT_OF_MEMORY
);
3050 ALCdevice_DecRef(device
);
3054 ALContext
->Device
= device
;
3055 ALCdevice_IncRef(device
);
3056 InitContext(ALContext
);
3059 ALCcontext
*head
= ATOMIC_LOAD(&device
->ContextList
);
3061 ALContext
->next
= head
;
3062 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext
*, &device
->ContextList
, &head
, ALContext
));
3066 ALCdevice_DecRef(device
);
3068 TRACE("Created context %p\n", ALContext
);
3072 /* alcDestroyContext
3074 * Remove a context from its device
3076 ALC_API ALCvoid ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
3081 /* alcGetContextsDevice sets an error for invalid contexts */
3082 Device
= alcGetContextsDevice(context
);
3085 ReleaseContext(context
, Device
);
3086 if(!ATOMIC_LOAD(&Device
->ContextList
))
3088 V0(Device
->Backend
,stop
)();
3089 Device
->Flags
&= ~DEVICE_RUNNING
;
3096 /* alcGetCurrentContext
3098 * Returns the currently active context on the calling thread
3100 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
3102 ALCcontext
*Context
= altss_get(LocalContext
);
3103 if(!Context
) Context
= ATOMIC_LOAD(&GlobalContext
);
3107 /* alcGetThreadContext
3109 * Returns the currently active thread-local context
3111 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
3113 return altss_get(LocalContext
);
3117 /* alcMakeContextCurrent
3119 * Makes the given context the active process-wide context, and removes the
3120 * thread-local context for the calling thread.
3122 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
3124 /* context must be valid or NULL */
3125 if(context
&& !(context
=VerifyContext(context
)))
3127 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3130 /* context's reference count is already incremented */
3131 context
= ATOMIC_EXCHANGE(ALCcontext
*, &GlobalContext
, context
);
3132 if(context
) ALCcontext_DecRef(context
);
3134 if((context
=altss_get(LocalContext
)) != NULL
)
3136 altss_set(LocalContext
, NULL
);
3137 ALCcontext_DecRef(context
);
3143 /* alcSetThreadContext
3145 * Makes the given context the active context for the current thread
3147 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
3151 /* context must be valid or NULL */
3152 if(context
&& !(context
=VerifyContext(context
)))
3154 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3157 /* context's reference count is already incremented */
3158 old
= altss_get(LocalContext
);
3159 altss_set(LocalContext
, context
);
3160 if(old
) ALCcontext_DecRef(old
);
3166 /* alcGetContextsDevice
3168 * Returns the device that a particular context is attached to
3170 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*Context
)
3174 if(!(Context
=VerifyContext(Context
)))
3176 alcSetError(NULL
, ALC_INVALID_CONTEXT
);
3179 Device
= Context
->Device
;
3180 ALCcontext_DecRef(Context
);
3188 * Opens the named device.
3190 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*deviceName
)
3198 if(!PlaybackBackend
.name
)
3200 alcSetError(NULL
, ALC_INVALID_VALUE
);
3204 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
3207 device
= al_calloc(16, sizeof(ALCdevice
)+sizeof(ALeffectslot
));
3210 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3215 InitRef(&device
->ref
, 1);
3216 device
->Connected
= ALC_TRUE
;
3217 device
->Type
= Playback
;
3218 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3221 device
->Bs2b
= NULL
;
3222 device
->Bs2bLevel
= 0;
3223 AL_STRING_INIT(device
->DeviceName
);
3225 ATOMIC_INIT(&device
->ContextList
, NULL
);
3227 device
->ClockBase
= 0;
3228 device
->SamplesDone
= 0;
3230 device
->MaxNoOfSources
= 256;
3231 device
->AuxiliaryEffectSlotMax
= 4;
3232 device
->NumAuxSends
= MAX_SENDS
;
3234 InitUIntMap(&device
->BufferMap
, ~0);
3235 InitUIntMap(&device
->EffectMap
, ~0);
3236 InitUIntMap(&device
->FilterMap
, ~0);
3237 InitUIntMap(&device
->SfontMap
, ~0);
3238 InitUIntMap(&device
->PresetMap
, ~0);
3239 InitUIntMap(&device
->FontsoundMap
, ~0);
3242 device
->FmtChans
= DevFmtChannelsDefault
;
3243 device
->FmtType
= DevFmtTypeDefault
;
3244 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3245 device
->NumUpdates
= 4;
3246 device
->UpdateSize
= 1024;
3248 if(!PlaybackBackend
.getFactory
)
3249 device
->Backend
= create_backend_wrapper(device
, &PlaybackBackend
.Funcs
,
3250 ALCbackend_Playback
);
3253 ALCbackendFactory
*factory
= PlaybackBackend
.getFactory();
3254 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Playback
);
3256 if(!device
->Backend
)
3259 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3264 if(ConfigValueStr(NULL
, "channels", &fmt
))
3266 static const struct {
3267 const char name
[16];
3268 enum DevFmtChannels chans
;
3270 { "mono", DevFmtMono
},
3271 { "stereo", DevFmtStereo
},
3272 { "quad", DevFmtQuad
},
3273 { "surround51", DevFmtX51
},
3274 { "surround61", DevFmtX61
},
3275 { "surround71", DevFmtX71
},
3276 { "surround51rear", DevFmtX51Rear
},
3280 for(i
= 0;i
< COUNTOF(chanlist
);i
++)
3282 if(strcasecmp(chanlist
[i
].name
, fmt
) == 0)
3284 device
->FmtChans
= chanlist
[i
].chans
;
3285 device
->Flags
|= DEVICE_CHANNELS_REQUEST
;
3289 if(i
== COUNTOF(chanlist
))
3290 ERR("Unsupported channels: %s\n", fmt
);
3292 if(ConfigValueStr(NULL
, "sample-type", &fmt
))
3294 static const struct {
3295 const char name
[16];
3296 enum DevFmtType type
;
3298 { "int8", DevFmtByte
},
3299 { "uint8", DevFmtUByte
},
3300 { "int16", DevFmtShort
},
3301 { "uint16", DevFmtUShort
},
3302 { "int32", DevFmtInt
},
3303 { "uint32", DevFmtUInt
},
3304 { "float32", DevFmtFloat
},
3308 for(i
= 0;i
< COUNTOF(typelist
);i
++)
3310 if(strcasecmp(typelist
[i
].name
, fmt
) == 0)
3312 device
->FmtType
= typelist
[i
].type
;
3313 device
->Flags
|= DEVICE_SAMPLE_TYPE_REQUEST
;
3317 if(i
== COUNTOF(typelist
))
3318 ERR("Unsupported sample-type: %s\n", fmt
);
3321 if(ConfigValueUInt(NULL
, "frequency", &device
->Frequency
))
3323 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3324 if(device
->Frequency
< MIN_OUTPUT_RATE
)
3325 ERR("%uhz request clamped to %uhz minimum\n", device
->Frequency
, MIN_OUTPUT_RATE
);
3326 device
->Frequency
= maxu(device
->Frequency
, MIN_OUTPUT_RATE
);
3329 ConfigValueUInt(NULL
, "periods", &device
->NumUpdates
);
3330 device
->NumUpdates
= clampu(device
->NumUpdates
, 2, 16);
3332 ConfigValueUInt(NULL
, "period_size", &device
->UpdateSize
);
3333 device
->UpdateSize
= clampu(device
->UpdateSize
, 64, 8192);
3334 if((CPUCapFlags
&(CPU_CAP_SSE
|CPU_CAP_NEON
)) != 0)
3335 device
->UpdateSize
= (device
->UpdateSize
+3)&~3;
3337 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3338 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3340 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3341 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3343 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3344 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3346 ConfigValueInt(NULL
, "cf_level", &device
->Bs2bLevel
);
3348 device
->NumStereoSources
= 1;
3349 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3351 device
->Synth
= SynthCreate(device
);
3354 DELETE_OBJ(device
->Backend
);
3356 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3360 // Find a playback device to open
3361 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3363 DELETE_OBJ(device
->Synth
);
3364 DELETE_OBJ(device
->Backend
);
3366 alcSetError(NULL
, err
);
3370 if(DefaultEffect
.type
!= AL_EFFECT_NULL
)
3372 device
->DefaultSlot
= (ALeffectslot
*)device
->_slot_mem
;
3373 if(InitEffectSlot(device
->DefaultSlot
) != AL_NO_ERROR
)
3375 device
->DefaultSlot
= NULL
;
3376 ERR("Failed to initialize the default effect slot\n");
3378 else if(InitializeEffect(device
, device
->DefaultSlot
, &DefaultEffect
) != AL_NO_ERROR
)
3380 ALeffectState
*state
= device
->DefaultSlot
->EffectState
;
3381 device
->DefaultSlot
= NULL
;
3383 ERR("Failed to initialize the default effect\n");
3388 ALCdevice
*head
= ATOMIC_LOAD(&DeviceList
);
3390 device
->next
= head
;
3391 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice
*, &DeviceList
, &head
, device
));
3394 TRACE("Created device %p, \"%s\"\n", device
, al_string_get_cstr(device
->DeviceName
));
3400 * Closes the given device.
3402 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
3404 ALCdevice
*list
, *origdev
, *nextdev
;
3408 list
= ATOMIC_LOAD(&DeviceList
);
3412 } while((list
=list
->next
) != NULL
);
3413 if(!list
|| list
->Type
== Capture
)
3415 alcSetError(list
, ALC_INVALID_DEVICE
);
3421 nextdev
= device
->next
;
3422 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice
*, &DeviceList
, &origdev
, nextdev
))
3427 } while(!COMPARE_EXCHANGE(&list
->next
, &origdev
, nextdev
));
3431 ctx
= ATOMIC_LOAD(&device
->ContextList
);
3434 ALCcontext
*next
= ctx
->next
;
3435 WARN("Releasing context %p\n", ctx
);
3436 ReleaseContext(ctx
, device
);
3439 if((device
->Flags
&DEVICE_RUNNING
))
3440 V0(device
->Backend
,stop
)();
3441 device
->Flags
&= ~DEVICE_RUNNING
;
3443 ALCdevice_DecRef(device
);
3449 /************************************************
3450 * ALC capture functions
3451 ************************************************/
3452 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*deviceName
, ALCuint frequency
, ALCenum format
, ALCsizei samples
)
3454 ALCdevice
*device
= NULL
;
3459 if(!CaptureBackend
.name
)
3461 alcSetError(NULL
, ALC_INVALID_VALUE
);
3467 alcSetError(NULL
, ALC_INVALID_VALUE
);
3471 if(deviceName
&& (!deviceName
[0] || strcasecmp(deviceName
, alcDefaultName
) == 0 || strcasecmp(deviceName
, "openal-soft") == 0))
3474 device
= al_calloc(16, sizeof(ALCdevice
));
3477 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3482 InitRef(&device
->ref
, 1);
3483 device
->Connected
= ALC_TRUE
;
3484 device
->Type
= Capture
;
3486 AL_STRING_INIT(device
->DeviceName
);
3488 InitUIntMap(&device
->BufferMap
, ~0);
3489 InitUIntMap(&device
->EffectMap
, ~0);
3490 InitUIntMap(&device
->FilterMap
, ~0);
3491 InitUIntMap(&device
->SfontMap
, ~0);
3492 InitUIntMap(&device
->PresetMap
, ~0);
3493 InitUIntMap(&device
->FontsoundMap
, ~0);
3495 if(!CaptureBackend
.getFactory
)
3496 device
->Backend
= create_backend_wrapper(device
, &CaptureBackend
.Funcs
,
3497 ALCbackend_Capture
);
3500 ALCbackendFactory
*factory
= CaptureBackend
.getFactory();
3501 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Capture
);
3503 if(!device
->Backend
)
3506 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3510 device
->Flags
|= DEVICE_FREQUENCY_REQUEST
;
3511 device
->Frequency
= frequency
;
3513 device
->Flags
|= DEVICE_CHANNELS_REQUEST
| DEVICE_SAMPLE_TYPE_REQUEST
;
3514 if(DecomposeDevFormat(format
, &device
->FmtChans
, &device
->FmtType
) == AL_FALSE
)
3517 alcSetError(NULL
, ALC_INVALID_ENUM
);
3521 device
->UpdateSize
= samples
;
3522 device
->NumUpdates
= 1;
3524 if((err
=V(device
->Backend
,open
)(deviceName
)) != ALC_NO_ERROR
)
3527 alcSetError(NULL
, err
);
3532 ALCdevice
*head
= ATOMIC_LOAD(&DeviceList
);
3534 device
->next
= head
;
3535 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice
*, &DeviceList
, &head
, device
));
3538 TRACE("Created device %p, \"%s\"\n", device
, al_string_get_cstr(device
->DeviceName
));
3542 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
3544 ALCdevice
*list
, *next
, *nextdev
;
3547 list
= ATOMIC_LOAD(&DeviceList
);
3551 } while((list
=list
->next
) != NULL
);
3552 if(!list
|| list
->Type
!= Capture
)
3554 alcSetError(list
, ALC_INVALID_DEVICE
);
3560 nextdev
= device
->next
;
3561 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice
*, &DeviceList
, &next
, nextdev
))
3566 } while(!COMPARE_EXCHANGE(&list
->next
, &next
, nextdev
));
3570 ALCdevice_DecRef(device
);
3575 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
3577 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3578 alcSetError(device
, ALC_INVALID_DEVICE
);
3581 ALCdevice_Lock(device
);
3582 if(device
->Connected
)
3584 if(!(device
->Flags
&DEVICE_RUNNING
))
3585 V0(device
->Backend
,start
)();
3586 device
->Flags
|= DEVICE_RUNNING
;
3588 ALCdevice_Unlock(device
);
3591 if(device
) ALCdevice_DecRef(device
);
3594 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
3596 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3597 alcSetError(device
, ALC_INVALID_DEVICE
);
3600 ALCdevice_Lock(device
);
3601 if((device
->Flags
&DEVICE_RUNNING
))
3602 V0(device
->Backend
,stop
)();
3603 device
->Flags
&= ~DEVICE_RUNNING
;
3604 ALCdevice_Unlock(device
);
3607 if(device
) ALCdevice_DecRef(device
);
3610 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3612 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Capture
)
3613 alcSetError(device
, ALC_INVALID_DEVICE
);
3616 ALCenum err
= ALC_INVALID_VALUE
;
3618 ALCdevice_Lock(device
);
3619 if(samples
>= 0 && V0(device
->Backend
,availableSamples
)() >= (ALCuint
)samples
)
3620 err
= V(device
->Backend
,captureSamples
)(buffer
, samples
);
3621 ALCdevice_Unlock(device
);
3623 if(err
!= ALC_NO_ERROR
)
3624 alcSetError(device
, err
);
3626 if(device
) ALCdevice_DecRef(device
);
3630 /************************************************
3631 * ALC loopback functions
3632 ************************************************/
3634 /* alcLoopbackOpenDeviceSOFT
3636 * Open a loopback device, for manual rendering.
3638 ALC_API ALCdevice
* ALC_APIENTRY
alcLoopbackOpenDeviceSOFT(const ALCchar
*deviceName
)
3640 ALCbackendFactory
*factory
;
3645 /* Make sure the device name, if specified, is us. */
3646 if(deviceName
&& strcmp(deviceName
, alcDefaultName
) != 0)
3648 alcSetError(NULL
, ALC_INVALID_VALUE
);
3652 device
= al_calloc(16, sizeof(ALCdevice
));
3655 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3660 InitRef(&device
->ref
, 1);
3661 device
->Connected
= ALC_TRUE
;
3662 device
->Type
= Loopback
;
3663 ATOMIC_INIT(&device
->LastError
, ALC_NO_ERROR
);
3666 device
->Bs2b
= NULL
;
3667 device
->Bs2bLevel
= 0;
3668 AL_STRING_INIT(device
->DeviceName
);
3670 ATOMIC_INIT(&device
->ContextList
, NULL
);
3672 device
->ClockBase
= 0;
3673 device
->SamplesDone
= 0;
3675 device
->MaxNoOfSources
= 256;
3676 device
->AuxiliaryEffectSlotMax
= 4;
3677 device
->NumAuxSends
= MAX_SENDS
;
3679 InitUIntMap(&device
->BufferMap
, ~0);
3680 InitUIntMap(&device
->EffectMap
, ~0);
3681 InitUIntMap(&device
->FilterMap
, ~0);
3682 InitUIntMap(&device
->SfontMap
, ~0);
3683 InitUIntMap(&device
->PresetMap
, ~0);
3684 InitUIntMap(&device
->FontsoundMap
, ~0);
3686 factory
= ALCloopbackFactory_getFactory();
3687 device
->Backend
= V(factory
,createBackend
)(device
, ALCbackend_Loopback
);
3688 if(!device
->Backend
)
3691 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3696 device
->NumUpdates
= 0;
3697 device
->UpdateSize
= 0;
3699 device
->Frequency
= DEFAULT_OUTPUT_RATE
;
3700 device
->FmtChans
= DevFmtChannelsDefault
;
3701 device
->FmtType
= DevFmtTypeDefault
;
3703 ConfigValueUInt(NULL
, "sources", &device
->MaxNoOfSources
);
3704 if(device
->MaxNoOfSources
== 0) device
->MaxNoOfSources
= 256;
3706 ConfigValueUInt(NULL
, "slots", &device
->AuxiliaryEffectSlotMax
);
3707 if(device
->AuxiliaryEffectSlotMax
== 0) device
->AuxiliaryEffectSlotMax
= 4;
3709 ConfigValueUInt(NULL
, "sends", &device
->NumAuxSends
);
3710 if(device
->NumAuxSends
> MAX_SENDS
) device
->NumAuxSends
= MAX_SENDS
;
3712 device
->NumStereoSources
= 1;
3713 device
->NumMonoSources
= device
->MaxNoOfSources
- device
->NumStereoSources
;
3715 device
->Synth
= SynthCreate(device
);
3718 DELETE_OBJ(device
->Backend
);
3720 alcSetError(NULL
, ALC_OUT_OF_MEMORY
);
3724 // Open the "backend"
3725 V(device
->Backend
,open
)("Loopback");
3728 ALCdevice
*head
= ATOMIC_LOAD(&DeviceList
);
3730 device
->next
= head
;
3731 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice
*, &DeviceList
, &head
, device
));
3734 TRACE("Created device %p\n", device
);
3738 /* alcIsRenderFormatSupportedSOFT
3740 * Determines if the loopback device supports the given format for rendering.
3742 ALC_API ALCboolean ALC_APIENTRY
alcIsRenderFormatSupportedSOFT(ALCdevice
*device
, ALCsizei freq
, ALCenum channels
, ALCenum type
)
3744 ALCboolean ret
= ALC_FALSE
;
3746 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3747 alcSetError(device
, ALC_INVALID_DEVICE
);
3749 alcSetError(device
, ALC_INVALID_VALUE
);
3752 if(IsValidALCType(type
) && BytesFromDevFmt(type
) > 0 &&
3753 IsValidALCChannels(channels
) && ChannelsFromDevFmt(channels
) > 0 &&
3754 freq
>= MIN_OUTPUT_RATE
)
3757 if(device
) ALCdevice_DecRef(device
);
3762 /* alcRenderSamplesSOFT
3764 * Renders some samples into a buffer, using the format last set by the
3765 * attributes given to alcCreateContext.
3767 FORCE_ALIGN ALC_API
void ALC_APIENTRY
alcRenderSamplesSOFT(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
3769 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Loopback
)
3770 alcSetError(device
, ALC_INVALID_DEVICE
);
3771 else if(samples
< 0 || (samples
> 0 && buffer
== NULL
))
3772 alcSetError(device
, ALC_INVALID_VALUE
);
3774 aluMixData(device
, buffer
, samples
);
3775 if(device
) ALCdevice_DecRef(device
);
3779 /************************************************
3780 * ALC DSP pause/resume functions
3781 ************************************************/
3783 /* alcDevicePauseSOFT
3785 * Pause the DSP to stop audio processing.
3787 ALC_API
void ALC_APIENTRY
alcDevicePauseSOFT(ALCdevice
*device
)
3789 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Playback
)
3790 alcSetError(device
, ALC_INVALID_DEVICE
);
3794 if((device
->Flags
&DEVICE_RUNNING
))
3795 V0(device
->Backend
,stop
)();
3796 device
->Flags
&= ~DEVICE_RUNNING
;
3797 device
->Flags
|= DEVICE_PAUSED
;
3800 if(device
) ALCdevice_DecRef(device
);
3803 /* alcDeviceResumeSOFT
3805 * Resume the DSP to restart audio processing.
3807 ALC_API
void ALC_APIENTRY
alcDeviceResumeSOFT(ALCdevice
*device
)
3809 if(!(device
=VerifyDevice(device
)) || device
->Type
!= Playback
)
3810 alcSetError(device
, ALC_INVALID_DEVICE
);
3814 if((device
->Flags
&DEVICE_PAUSED
))
3816 device
->Flags
&= ~DEVICE_PAUSED
;
3817 if(ATOMIC_LOAD(&device
->ContextList
) != NULL
)
3819 if(V0(device
->Backend
,start
)() != ALC_FALSE
)
3820 device
->Flags
|= DEVICE_RUNNING
;
3823 alcSetError(device
, ALC_INVALID_DEVICE
);
3824 ALCdevice_Lock(device
);
3825 aluHandleDisconnect(device
);
3826 ALCdevice_Unlock(device
);
3832 if(device
) ALCdevice_DecRef(device
);