Do up to 256 samples at a time with multi-step loops
[openal-soft.git] / Alc / ALc.c
blob2f1747449dad19e5d3efcd6bb545c65c5ec24886
1 /**
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include <signal.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "alListener.h"
33 #include "alThunk.h"
34 #include "alSource.h"
35 #include "alBuffer.h"
36 #include "alAuxEffectSlot.h"
37 #include "alError.h"
38 #include "alMidi.h"
39 #include "bs2b.h"
40 #include "alu.h"
42 #include "compat.h"
43 #include "threads.h"
44 #include "alstring.h"
46 #include "backends/base.h"
47 #include "midi/base.h"
50 /************************************************
51 * Backends
52 ************************************************/
53 struct BackendInfo {
54 const char *name;
55 ALCbackendFactory* (*getFactory)(void);
56 ALCboolean (*Init)(BackendFuncs*);
57 void (*Deinit)(void);
58 void (*Probe)(enum DevProbe);
59 BackendFuncs Funcs;
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 },
66 #endif
67 #ifdef HAVE_ALSA
68 { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
69 #endif
70 #ifdef HAVE_COREAUDIO
71 { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs },
72 #endif
73 #ifdef HAVE_OSS
74 { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
75 #endif
76 #ifdef HAVE_SOLARIS
77 { "solaris", NULL, alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
78 #endif
79 #ifdef HAVE_SNDIO
80 { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs },
81 #endif
82 #ifdef HAVE_QSA
83 { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs },
84 #endif
85 #ifdef HAVE_MMDEVAPI
86 { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
87 #endif
88 #ifdef HAVE_DSOUND
89 { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
90 #endif
91 #ifdef HAVE_WINMM
92 { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
93 #endif
94 #ifdef HAVE_PORTAUDIO
95 { "port", NULL, alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
96 #endif
97 #ifdef HAVE_OPENSL
98 { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs },
99 #endif
101 { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
102 #ifdef HAVE_WAVE
103 { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs },
104 #endif
106 { NULL, NULL, NULL, NULL, NULL, EmptyFuncs }
108 #undef 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;
119 ALCvoid *address;
120 } ALCfunction;
122 typedef struct ALCenums {
123 const ALCchar *enumName;
124 ALCenum value;
125 } ALCenums;
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),
136 DECL(alcOpenDevice),
137 DECL(alcCloseDevice),
138 DECL(alcGetError),
139 DECL(alcIsExtensionPresent),
140 DECL(alcGetProcAddress),
141 DECL(alcGetEnumValue),
142 DECL(alcGetString),
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),
162 DECL(alEnable),
163 DECL(alDisable),
164 DECL(alIsEnabled),
165 DECL(alGetString),
166 DECL(alGetBooleanv),
167 DECL(alGetIntegerv),
168 DECL(alGetFloatv),
169 DECL(alGetDoublev),
170 DECL(alGetBoolean),
171 DECL(alGetInteger),
172 DECL(alGetFloat),
173 DECL(alGetDouble),
174 DECL(alGetError),
175 DECL(alIsExtensionPresent),
176 DECL(alGetProcAddress),
177 DECL(alGetEnumValue),
178 DECL(alListenerf),
179 DECL(alListener3f),
180 DECL(alListenerfv),
181 DECL(alListeneri),
182 DECL(alListener3i),
183 DECL(alListeneriv),
184 DECL(alGetListenerf),
185 DECL(alGetListener3f),
186 DECL(alGetListenerfv),
187 DECL(alGetListeneri),
188 DECL(alGetListener3i),
189 DECL(alGetListeneriv),
190 DECL(alGenSources),
191 DECL(alDeleteSources),
192 DECL(alIsSource),
193 DECL(alSourcef),
194 DECL(alSource3f),
195 DECL(alSourcefv),
196 DECL(alSourcei),
197 DECL(alSource3i),
198 DECL(alSourceiv),
199 DECL(alGetSourcef),
200 DECL(alGetSource3f),
201 DECL(alGetSourcefv),
202 DECL(alGetSourcei),
203 DECL(alGetSource3i),
204 DECL(alGetSourceiv),
205 DECL(alSourcePlayv),
206 DECL(alSourceStopv),
207 DECL(alSourceRewindv),
208 DECL(alSourcePausev),
209 DECL(alSourcePlay),
210 DECL(alSourceStop),
211 DECL(alSourceRewind),
212 DECL(alSourcePause),
213 DECL(alSourceQueueBuffers),
214 DECL(alSourceUnqueueBuffers),
215 DECL(alGenBuffers),
216 DECL(alDeleteBuffers),
217 DECL(alIsBuffer),
218 DECL(alBufferData),
219 DECL(alBufferf),
220 DECL(alBuffer3f),
221 DECL(alBufferfv),
222 DECL(alBufferi),
223 DECL(alBuffer3i),
224 DECL(alBufferiv),
225 DECL(alGetBufferf),
226 DECL(alGetBuffer3f),
227 DECL(alGetBufferfv),
228 DECL(alGetBufferi),
229 DECL(alGetBuffer3i),
230 DECL(alGetBufferiv),
231 DECL(alDopplerFactor),
232 DECL(alDopplerVelocity),
233 DECL(alSpeedOfSound),
234 DECL(alDistanceModel),
236 DECL(alGenFilters),
237 DECL(alDeleteFilters),
238 DECL(alIsFilter),
239 DECL(alFilteri),
240 DECL(alFilteriv),
241 DECL(alFilterf),
242 DECL(alFilterfv),
243 DECL(alGetFilteri),
244 DECL(alGetFilteriv),
245 DECL(alGetFilterf),
246 DECL(alGetFilterfv),
247 DECL(alGenEffects),
248 DECL(alDeleteEffects),
249 DECL(alIsEffect),
250 DECL(alEffecti),
251 DECL(alEffectiv),
252 DECL(alEffectf),
253 DECL(alEffectfv),
254 DECL(alGetEffecti),
255 DECL(alGetEffectiv),
256 DECL(alGetEffectf),
257 DECL(alGetEffectfv),
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),
280 DECL(alSourcedSOFT),
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),
301 DECL(alPresetiSOFT),
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),
327 { NULL, NULL }
329 #undef DECL
331 #define DECL(x) { #x, (x) }
332 static const ALCenums enumeration[] = {
333 DECL(ALC_INVALID),
334 DECL(ALC_FALSE),
335 DECL(ALC_TRUE),
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),
346 DECL(ALC_FREQUENCY),
347 DECL(ALC_REFRESH),
348 DECL(ALC_SYNC),
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),
354 DECL(ALC_CONNECTED),
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),
363 DECL(ALC_MONO_SOFT),
364 DECL(ALC_STEREO_SOFT),
365 DECL(ALC_QUAD_SOFT),
366 DECL(ALC_5POINT1_SOFT),
367 DECL(ALC_6POINT1_SOFT),
368 DECL(ALC_7POINT1_SOFT),
370 DECL(ALC_BYTE_SOFT),
371 DECL(ALC_UNSIGNED_BYTE_SOFT),
372 DECL(ALC_SHORT_SOFT),
373 DECL(ALC_UNSIGNED_SHORT_SOFT),
374 DECL(ALC_INT_SOFT),
375 DECL(ALC_UNSIGNED_INT_SOFT),
376 DECL(ALC_FLOAT_SOFT),
378 DECL(ALC_NO_ERROR),
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),
386 DECL(AL_INVALID),
387 DECL(AL_NONE),
388 DECL(AL_FALSE),
389 DECL(AL_TRUE),
391 DECL(AL_SOURCE_RELATIVE),
392 DECL(AL_CONE_INNER_ANGLE),
393 DECL(AL_CONE_OUTER_ANGLE),
394 DECL(AL_PITCH),
395 DECL(AL_POSITION),
396 DECL(AL_DIRECTION),
397 DECL(AL_VELOCITY),
398 DECL(AL_LOOPING),
399 DECL(AL_BUFFER),
400 DECL(AL_GAIN),
401 DECL(AL_MIN_GAIN),
402 DECL(AL_MAX_GAIN),
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),
408 DECL(AL_SEC_OFFSET),
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),
414 DECL(AL_STATIC),
415 DECL(AL_STREAMING),
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),
430 DECL(AL_INITIAL),
431 DECL(AL_PLAYING),
432 DECL(AL_PAUSED),
433 DECL(AL_STOPPED),
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),
479 DECL(AL_MONO8_SOFT),
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),
485 DECL(AL_QUAD8_SOFT),
486 DECL(AL_QUAD16_SOFT),
487 DECL(AL_QUAD32F_SOFT),
488 DECL(AL_REAR8_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),
509 DECL(AL_MONO_SOFT),
510 DECL(AL_STEREO_SOFT),
511 DECL(AL_QUAD_SOFT),
512 DECL(AL_REAR_SOFT),
513 DECL(AL_5POINT1_SOFT),
514 DECL(AL_6POINT1_SOFT),
515 DECL(AL_7POINT1_SOFT),
517 DECL(AL_BYTE_SOFT),
518 DECL(AL_UNSIGNED_BYTE_SOFT),
519 DECL(AL_SHORT_SOFT),
520 DECL(AL_UNSIGNED_SHORT_SOFT),
521 DECL(AL_INT_SOFT),
522 DECL(AL_UNSIGNED_INT_SOFT),
523 DECL(AL_FLOAT_SOFT),
524 DECL(AL_DOUBLE_SOFT),
525 DECL(AL_BYTE3_SOFT),
526 DECL(AL_UNSIGNED_BYTE3_SOFT),
528 DECL(AL_FREQUENCY),
529 DECL(AL_BITS),
530 DECL(AL_CHANNELS),
531 DECL(AL_SIZE),
532 DECL(AL_INTERNAL_FORMAT_SOFT),
533 DECL(AL_BYTE_LENGTH_SOFT),
534 DECL(AL_SAMPLE_LENGTH_SOFT),
535 DECL(AL_SEC_LENGTH_SOFT),
536 DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT),
537 DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT),
539 DECL(AL_UNUSED),
540 DECL(AL_PENDING),
541 DECL(AL_PROCESSED),
543 DECL(AL_NO_ERROR),
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),
550 DECL(AL_VENDOR),
551 DECL(AL_VERSION),
552 DECL(AL_RENDERER),
553 DECL(AL_EXTENSIONS),
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),
593 #if 0
594 DECL(AL_EFFECT_FREQUENCY_SHIFTER),
595 DECL(AL_EFFECT_VOCAL_MORPHER),
596 DECL(AL_EFFECT_PITCH_SHIFTER),
597 #endif
598 DECL(AL_EFFECT_RING_MODULATOR),
599 #if 0
600 DECL(AL_EFFECT_AUTOWAH),
601 #endif
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),
658 DECL(AL_ECHO_DELAY),
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),
675 #if 0
676 DECL(AL_AUTOWAH_ATTACK_TIME),
677 DECL(AL_AUTOWAH_PEAK_GAIN),
678 DECL(AL_AUTOWAH_RELEASE_TIME),
679 DECL(AL_AUTOWAH_RESONANCE),
680 #endif
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),
697 { NULL, (ALCenum)0 }
699 #undef DECL
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 /************************************************
710 * Global variables
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 */
741 ALint RTPrioLevel;
743 FILE *LogFile;
744 #ifdef _DEBUG
745 enum LogLevel LogLevel = LogWarning;
746 #else
747 enum LogLevel LogLevel = LogError;
748 #endif
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
760 * updates.
762 static ALCboolean SuspendDefers = ALC_TRUE;
765 /************************************************
766 * ALC information
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 /************************************************
784 * Device lists
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 ************************************************/
803 #if defined(_WIN32)
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)
811 switch(reason)
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);
817 alc_init();
818 break;
820 case DLL_THREAD_DETACH:
821 break;
823 case DLL_PROCESS_DETACH:
824 if(!lpReserved)
825 alc_deinit();
826 else
827 alc_deinit_safe();
828 break;
830 return TRUE;
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);
841 alc_init();
844 static void alc_destructor(void)
846 alc_deinit();
848 #elif defined(HAVE_GCC_DESTRUCTOR)
849 static void alc_init(void) __attribute__((constructor));
850 static void alc_deinit(void) __attribute__((destructor));
851 #else
852 #error "No static initialization available on this platform!"
853 #endif
855 #elif defined(HAVE_GCC_DESTRUCTOR)
857 static void alc_init(void) __attribute__((constructor));
858 static void alc_deinit(void) __attribute__((destructor));
860 #else
861 #error "No global initialization available on this platform!"
862 #endif
864 static void ReleaseThreadCtx(void *ptr);
865 static void alc_init(void)
867 const char *str;
868 int ret;
870 LogFile = stderr;
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))
877 ConeScale *= 0.5f;
879 str = getenv("__ALSOFT_REVERSE_Z");
880 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
881 ZScale *= -1.0f;
883 ret = altss_create(&LocalContext, ReleaseThreadCtx);
884 assert(ret == althrd_success);
886 ret = almtx_init(&ListLock, almtx_recursive);
887 assert(ret == althrd_success);
889 ThunkInit();
892 static void alc_initconfig(void)
894 const char *devs, *str;
895 ALuint capfilter;
896 float valf;
897 int i, n;
899 str = getenv("ALSOFT_LOGLEVEL");
900 if(str)
902 long lvl = strtol(str, NULL, 0);
903 if(lvl >= NoLog && lvl <= LogRef)
904 LogLevel = lvl;
907 str = getenv("ALSOFT_LOGFILE");
908 if(str && str[0])
910 FILE *logfile = al_fopen(str, "wt");
911 if(logfile) LogFile = logfile;
912 else ERR("Failed to open log file '%s'\n", str);
916 char buf[1024] = "";
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);
922 ReadALConfig();
924 str = getenv("__ALSOFT_SUSPEND_CONTEXT");
925 if(str && *str)
927 if(strcasecmp(str, "ignore") == 0)
929 SuspendDefers = ALC_FALSE;
930 TRACE("Selected context suspend behavior, \"ignore\"\n");
932 else
933 ERR("Unhandled context suspend behavior setting: \"%s\"\n", str);
936 capfilter = 0;
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;
943 #endif
944 #ifdef HAVE_NEON
945 capfilter |= CPU_CAP_NEON;
946 #endif
947 if(ConfigValueStr(NULL, "disable-cpu-exts", &str))
949 if(strcasecmp(str, "all") == 0)
950 capfilter = 0;
951 else
953 size_t len;
954 const char *next = str;
956 do {
957 str = next;
958 while(isspace(str[0]))
959 str++;
960 next = strchr(str, ',');
962 if(!str[0] || str[0] == ',')
963 continue;
965 len = (next ? ((size_t)(next-str)) : strlen(str));
966 while(len > 0 && isspace(str[len-1]))
967 len--;
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;
976 else
977 WARN("Invalid CPU extension \"%s\"\n", str);
978 } while(next++);
981 FillCPUCaps(capfilter);
983 #ifdef _WIN32
984 RTPrioLevel = 1;
985 #else
986 RTPrioLevel = 0;
987 #endif
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;
998 else
1000 char *end;
1002 n = strtol(str, &end, 0);
1003 if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == CubicResampler))
1004 DefaultResampler = n;
1005 else
1006 WARN("Invalid resampler: %s\n", str);
1009 aluInitResamplers();
1011 str = getenv("ALSOFT_TRAP_ERROR");
1012 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1014 TrapALError = AL_TRUE;
1015 TrapALCError = AL_TRUE;
1017 else
1019 str = getenv("ALSOFT_TRAP_AL_ERROR");
1020 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1021 TrapALError = AL_TRUE;
1022 TrapALError = GetConfigValueBool(NULL, "trap-al-error", TrapALError);
1024 str = getenv("ALSOFT_TRAP_ALC_ERROR");
1025 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1))
1026 TrapALCError = ALC_TRUE;
1027 TrapALCError = GetConfigValueBool(NULL, "trap-alc-error", TrapALCError);
1030 if(ConfigValueFloat("reverb", "boost", &valf))
1031 ReverbBoost *= powf(10.0f, valf / 20.0f);
1033 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE);
1035 if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) ||
1036 ConfigValueStr(NULL, "drivers", &devs))
1038 int n;
1039 size_t len;
1040 const char *next = devs;
1041 int endlist, delitem;
1043 i = 0;
1044 do {
1045 devs = next;
1046 while(isspace(devs[0]))
1047 devs++;
1048 next = strchr(devs, ',');
1050 delitem = (devs[0] == '-');
1051 if(devs[0] == '-') devs++;
1053 if(!devs[0] || devs[0] == ',')
1055 endlist = 0;
1056 continue;
1058 endlist = 1;
1060 len = (next ? ((size_t)(next-devs)) : strlen(devs));
1061 while(len > 0 && isspace(devs[len-1]))
1062 len--;
1063 for(n = i;BackendList[n].name;n++)
1065 if(len == strlen(BackendList[n].name) &&
1066 strncmp(BackendList[n].name, devs, len) == 0)
1068 if(delitem)
1070 do {
1071 BackendList[n] = BackendList[n+1];
1072 ++n;
1073 } while(BackendList[n].name);
1075 else
1077 struct BackendInfo Bkp = BackendList[n];
1078 while(n > i)
1080 BackendList[n] = BackendList[n-1];
1081 --n;
1083 BackendList[n] = Bkp;
1085 i++;
1087 break;
1090 } while(next++);
1092 if(endlist)
1094 BackendList[i].name = NULL;
1095 BackendList[i].getFactory = NULL;
1096 BackendList[i].Init = NULL;
1097 BackendList[i].Deinit = NULL;
1098 BackendList[i].Probe = NULL;
1102 for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++)
1104 if(BackendList[i].getFactory)
1106 ALCbackendFactory *factory = BackendList[i].getFactory();
1107 if(!V0(factory,init)())
1109 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1110 continue;
1113 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1114 if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback))
1116 PlaybackBackend = BackendList[i];
1117 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1119 if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture))
1121 CaptureBackend = BackendList[i];
1122 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1125 continue;
1128 if(!BackendList[i].Init(&BackendList[i].Funcs))
1130 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name);
1131 continue;
1134 TRACE("Initialized backend \"%s\"\n", BackendList[i].name);
1135 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name)
1137 PlaybackBackend = BackendList[i];
1138 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name);
1140 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name)
1142 CaptureBackend = BackendList[i];
1143 TRACE("Added \"%s\" for capture\n", CaptureBackend.name);
1147 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1148 V0(factory,init)();
1151 if(ConfigValueStr(NULL, "excludefx", &str))
1153 size_t len;
1154 const char *next = str;
1156 do {
1157 str = next;
1158 next = strchr(str, ',');
1160 if(!str[0] || next == str)
1161 continue;
1163 len = (next ? ((size_t)(next-str)) : strlen(str));
1164 for(n = 0;EffectList[n].name;n++)
1166 if(len == strlen(EffectList[n].name) &&
1167 strncmp(EffectList[n].name, str, len) == 0)
1168 DisabledEffects[EffectList[n].type] = AL_TRUE;
1170 } while(next++);
1173 InitEffectFactoryMap();
1175 InitEffect(&DefaultEffect);
1176 str = getenv("ALSOFT_DEFAULT_REVERB");
1177 if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str))
1178 LoadReverbPreset(str, &DefaultEffect);
1180 #define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig)
1183 /************************************************
1184 * Library deinitialization
1185 ************************************************/
1186 static void alc_cleanup(void)
1188 ALCdevice *dev;
1190 AL_STRING_DEINIT(alcAllDevicesList);
1191 AL_STRING_DEINIT(alcCaptureDeviceList);
1193 free(alcDefaultAllDevicesSpecifier);
1194 alcDefaultAllDevicesSpecifier = NULL;
1195 free(alcCaptureDefaultDeviceSpecifier);
1196 alcCaptureDefaultDeviceSpecifier = NULL;
1198 if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL)
1200 ALCuint num = 0;
1201 do {
1202 num++;
1203 } while((dev=dev->next) != NULL);
1204 ERR("%u device%s not closed\n", num, (num>1)?"s":"");
1207 DeinitEffectFactoryMap();
1210 static void alc_deinit_safe(void)
1212 alc_cleanup();
1214 FreeHrtfs();
1215 FreeALConfig();
1217 ThunkExit();
1218 almtx_destroy(&ListLock);
1219 altss_delete(LocalContext);
1221 if(LogFile != stderr)
1222 fclose(LogFile);
1223 LogFile = NULL;
1226 static void alc_deinit(void)
1228 int i;
1230 alc_cleanup();
1232 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend));
1233 memset(&CaptureBackend, 0, sizeof(CaptureBackend));
1235 for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++)
1237 if(!BackendList[i].getFactory)
1238 BackendList[i].Deinit();
1239 else
1241 ALCbackendFactory *factory = BackendList[i].getFactory();
1242 V0(factory,deinit)();
1246 ALCbackendFactory *factory = ALCloopbackFactory_getFactory();
1247 V0(factory,deinit)();
1250 alc_deinit_safe();
1254 /************************************************
1255 * Device enumeration
1256 ************************************************/
1257 static void ProbeDevices(al_string *list, enum DevProbe type)
1259 DO_INITCONFIG();
1261 LockLists();
1262 al_string_clear(list);
1264 if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory))
1266 if(!PlaybackBackend.getFactory)
1267 PlaybackBackend.Probe(type);
1268 else
1270 ALCbackendFactory *factory = PlaybackBackend.getFactory();
1271 V(factory,probe)(type);
1274 else if(type == CAPTURE_DEVICE_PROBE && (CaptureBackend.Probe || CaptureBackend.getFactory))
1276 if(!CaptureBackend.getFactory)
1277 CaptureBackend.Probe(type);
1278 else
1280 ALCbackendFactory *factory = CaptureBackend.getFactory();
1281 V(factory,probe)(type);
1284 UnlockLists();
1286 static void ProbeAllDevicesList(void)
1287 { ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); }
1288 static void ProbeCaptureDeviceList(void)
1289 { ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); }
1291 static void AppendDevice(const ALCchar *name, al_string *devnames)
1293 size_t len = strlen(name);
1294 if(len > 0)
1295 al_string_append_range(devnames, name, name+len+1);
1297 void AppendAllDevicesList(const ALCchar *name)
1298 { AppendDevice(name, &alcAllDevicesList); }
1299 void AppendCaptureDeviceList(const ALCchar *name)
1300 { AppendDevice(name, &alcCaptureDeviceList); }
1303 /************************************************
1304 * Device format information
1305 ************************************************/
1306 const ALCchar *DevFmtTypeString(enum DevFmtType type)
1308 switch(type)
1310 case DevFmtByte: return "Signed Byte";
1311 case DevFmtUByte: return "Unsigned Byte";
1312 case DevFmtShort: return "Signed Short";
1313 case DevFmtUShort: return "Unsigned Short";
1314 case DevFmtInt: return "Signed Int";
1315 case DevFmtUInt: return "Unsigned Int";
1316 case DevFmtFloat: return "Float";
1318 return "(unknown type)";
1320 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans)
1322 switch(chans)
1324 case DevFmtMono: return "Mono";
1325 case DevFmtStereo: return "Stereo";
1326 case DevFmtQuad: return "Quadraphonic";
1327 case DevFmtX51: return "5.1 Surround";
1328 case DevFmtX51Rear: return "5.1 Surround (Rear)";
1329 case DevFmtX61: return "6.1 Surround";
1330 case DevFmtX71: return "7.1 Surround";
1331 case DevFmtBFormat3D: return "B-Format 3D";
1333 return "(unknown channels)";
1336 extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type);
1337 ALuint BytesFromDevFmt(enum DevFmtType type)
1339 switch(type)
1341 case DevFmtByte: return sizeof(ALbyte);
1342 case DevFmtUByte: return sizeof(ALubyte);
1343 case DevFmtShort: return sizeof(ALshort);
1344 case DevFmtUShort: return sizeof(ALushort);
1345 case DevFmtInt: return sizeof(ALint);
1346 case DevFmtUInt: return sizeof(ALuint);
1347 case DevFmtFloat: return sizeof(ALfloat);
1349 return 0;
1351 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans)
1353 switch(chans)
1355 case DevFmtMono: return 1;
1356 case DevFmtStereo: return 2;
1357 case DevFmtQuad: return 4;
1358 case DevFmtX51: return 6;
1359 case DevFmtX51Rear: return 6;
1360 case DevFmtX61: return 7;
1361 case DevFmtX71: return 8;
1362 case DevFmtBFormat3D: return 4;
1364 return 0;
1367 DECL_CONST static ALboolean DecomposeDevFormat(ALenum format,
1368 enum DevFmtChannels *chans, enum DevFmtType *type)
1370 static const struct {
1371 ALenum format;
1372 enum DevFmtChannels channels;
1373 enum DevFmtType type;
1374 } list[] = {
1375 { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte },
1376 { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort },
1377 { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
1379 { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte },
1380 { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort },
1381 { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
1383 { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte },
1384 { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort },
1385 { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat },
1387 { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte },
1388 { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort },
1389 { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat },
1391 { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte },
1392 { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort },
1393 { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat },
1395 { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte },
1396 { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort },
1397 { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat },
1399 ALuint i;
1401 for(i = 0;i < COUNTOF(list);i++)
1403 if(list[i].format == format)
1405 *chans = list[i].channels;
1406 *type = list[i].type;
1407 return AL_TRUE;
1411 return AL_FALSE;
1414 DECL_CONST static ALCboolean IsValidALCType(ALCenum type)
1416 switch(type)
1418 case ALC_BYTE_SOFT:
1419 case ALC_UNSIGNED_BYTE_SOFT:
1420 case ALC_SHORT_SOFT:
1421 case ALC_UNSIGNED_SHORT_SOFT:
1422 case ALC_INT_SOFT:
1423 case ALC_UNSIGNED_INT_SOFT:
1424 case ALC_FLOAT_SOFT:
1425 return ALC_TRUE;
1427 return ALC_FALSE;
1430 DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels)
1432 switch(channels)
1434 case ALC_MONO_SOFT:
1435 case ALC_STEREO_SOFT:
1436 case ALC_QUAD_SOFT:
1437 case ALC_5POINT1_SOFT:
1438 case ALC_6POINT1_SOFT:
1439 case ALC_7POINT1_SOFT:
1440 return ALC_TRUE;
1442 return ALC_FALSE;
1446 /************************************************
1447 * Miscellaneous ALC helpers
1448 ************************************************/
1449 extern inline void LockContext(ALCcontext *context);
1450 extern inline void UnlockContext(ALCcontext *context);
1452 ALint64 ALCdevice_GetLatency(ALCdevice *device)
1454 return V0(device->Backend,getLatency)();
1457 void ALCdevice_Lock(ALCdevice *device)
1459 V0(device->Backend,lock)();
1462 void ALCdevice_Unlock(ALCdevice *device)
1464 V0(device->Backend,unlock)();
1468 /* SetDefaultWFXChannelOrder
1470 * Sets the default channel order used by WaveFormatEx.
1472 void SetDefaultWFXChannelOrder(ALCdevice *device)
1474 ALuint i;
1476 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1477 device->ChannelName[i] = InvalidChannel;
1479 switch(device->FmtChans)
1481 case DevFmtMono:
1482 device->ChannelName[0] = FrontCenter;
1483 break;
1484 case DevFmtStereo:
1485 device->ChannelName[0] = FrontLeft;
1486 device->ChannelName[1] = FrontRight;
1487 break;
1488 case DevFmtQuad:
1489 device->ChannelName[0] = FrontLeft;
1490 device->ChannelName[1] = FrontRight;
1491 device->ChannelName[2] = BackLeft;
1492 device->ChannelName[3] = BackRight;
1493 break;
1494 case DevFmtX51:
1495 device->ChannelName[0] = FrontLeft;
1496 device->ChannelName[1] = FrontRight;
1497 device->ChannelName[2] = FrontCenter;
1498 device->ChannelName[3] = LFE;
1499 device->ChannelName[4] = SideLeft;
1500 device->ChannelName[5] = SideRight;
1501 break;
1502 case DevFmtX51Rear:
1503 device->ChannelName[0] = FrontLeft;
1504 device->ChannelName[1] = FrontRight;
1505 device->ChannelName[2] = FrontCenter;
1506 device->ChannelName[3] = LFE;
1507 device->ChannelName[4] = BackLeft;
1508 device->ChannelName[5] = BackRight;
1509 break;
1510 case DevFmtX61:
1511 device->ChannelName[0] = FrontLeft;
1512 device->ChannelName[1] = FrontRight;
1513 device->ChannelName[2] = FrontCenter;
1514 device->ChannelName[3] = LFE;
1515 device->ChannelName[4] = BackCenter;
1516 device->ChannelName[5] = SideLeft;
1517 device->ChannelName[6] = SideRight;
1518 break;
1519 case DevFmtX71:
1520 device->ChannelName[0] = FrontLeft;
1521 device->ChannelName[1] = FrontRight;
1522 device->ChannelName[2] = FrontCenter;
1523 device->ChannelName[3] = LFE;
1524 device->ChannelName[4] = BackLeft;
1525 device->ChannelName[5] = BackRight;
1526 device->ChannelName[6] = SideLeft;
1527 device->ChannelName[7] = SideRight;
1528 break;
1529 case DevFmtBFormat3D:
1530 device->ChannelName[0] = Aux0;
1531 device->ChannelName[1] = Aux1;
1532 device->ChannelName[2] = Aux2;
1533 device->ChannelName[3] = Aux3;
1534 break;
1538 /* SetDefaultChannelOrder
1540 * Sets the default channel order used by most non-WaveFormatEx-based APIs.
1542 void SetDefaultChannelOrder(ALCdevice *device)
1544 ALuint i;
1546 for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
1547 device->ChannelName[i] = InvalidChannel;
1549 switch(device->FmtChans)
1551 case DevFmtX51Rear:
1552 device->ChannelName[0] = FrontLeft;
1553 device->ChannelName[1] = FrontRight;
1554 device->ChannelName[2] = BackLeft;
1555 device->ChannelName[3] = BackRight;
1556 device->ChannelName[4] = FrontCenter;
1557 device->ChannelName[5] = LFE;
1558 return;
1559 case DevFmtX71:
1560 device->ChannelName[0] = FrontLeft;
1561 device->ChannelName[1] = FrontRight;
1562 device->ChannelName[2] = BackLeft;
1563 device->ChannelName[3] = BackRight;
1564 device->ChannelName[4] = FrontCenter;
1565 device->ChannelName[5] = LFE;
1566 device->ChannelName[6] = SideLeft;
1567 device->ChannelName[7] = SideRight;
1568 return;
1570 /* Same as WFX order */
1571 case DevFmtMono:
1572 case DevFmtStereo:
1573 case DevFmtQuad:
1574 case DevFmtX51:
1575 case DevFmtX61:
1576 case DevFmtBFormat3D:
1577 SetDefaultWFXChannelOrder(device);
1578 break;
1582 extern inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan);
1585 /* ALCcontext_DeferUpdates
1587 * Defers/suspends updates for the given context's listener and sources. This
1588 * does *NOT* stop mixing, but rather prevents certain property changes from
1589 * taking effect.
1591 void ALCcontext_DeferUpdates(ALCcontext *context)
1593 ALCdevice *device = context->Device;
1594 FPUCtl oldMode;
1596 SetMixerFPUMode(&oldMode);
1598 V0(device->Backend,lock)();
1599 if(!ExchangeInt(&context->DeferUpdates, AL_TRUE))
1601 ALboolean UpdateSources;
1602 ALvoice *voice, *voice_end;
1603 ALeffectslot **slot, **slot_end;
1604 /* Make sure all pending updates are performed */
1605 UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
1607 voice = context->Voices;
1608 voice_end = voice + context->VoiceCount;
1609 while(voice != voice_end)
1611 ALsource *source = voice->Source;
1612 if(!source) goto next;
1614 if(source->state != AL_PLAYING && source->state != AL_PAUSED)
1616 voice->Source = NULL;
1617 goto next;
1620 if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
1621 voice->Update(voice, source, context);
1622 next:
1623 voice++;
1626 slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
1627 slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
1628 while(slot != slot_end)
1630 if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
1631 V((*slot)->EffectState,update)(context->Device, *slot);
1632 slot++;
1635 V0(device->Backend,unlock)();
1637 RestoreFPUMode(&oldMode);
1640 /* ALCcontext_ProcessUpdates
1642 * Resumes update processing after being deferred.
1644 void ALCcontext_ProcessUpdates(ALCcontext *context)
1646 ALCdevice *device = context->Device;
1648 V0(device->Backend,lock)();
1649 if(ExchangeInt(&context->DeferUpdates, AL_FALSE))
1651 ALsizei pos;
1653 LockUIntMapRead(&context->SourceMap);
1654 for(pos = 0;pos < context->SourceMap.size;pos++)
1656 ALsource *Source = context->SourceMap.array[pos].value;
1657 ALenum new_state;
1659 if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
1660 Source->Offset >= 0.0)
1662 ReadLock(&Source->queue_lock);
1663 ApplyOffset(Source);
1664 ReadUnlock(&Source->queue_lock);
1667 new_state = ExchangeInt(&Source->new_state, AL_NONE);
1668 if(new_state)
1669 SetSourceState(Source, context, new_state);
1671 UnlockUIntMapRead(&context->SourceMap);
1673 V0(device->Backend,unlock)();
1677 /* alcSetError
1679 * Stores the latest ALC device error
1681 static void alcSetError(ALCdevice *device, ALCenum errorCode)
1683 if(TrapALCError)
1685 #ifdef _WIN32
1686 /* DebugBreak() will cause an exception if there is no debugger */
1687 if(IsDebuggerPresent())
1688 DebugBreak();
1689 #elif defined(SIGTRAP)
1690 raise(SIGTRAP);
1691 #endif
1694 if(device)
1695 ATOMIC_STORE(&device->LastError, errorCode);
1696 else
1697 ATOMIC_STORE(&LastNullDeviceError, errorCode);
1701 /* UpdateClockBase
1703 * Updates the device's base clock time with however many samples have been
1704 * done. This is used so frequency changes on the device don't cause the time
1705 * to jump forward or back.
1707 static inline void UpdateClockBase(ALCdevice *device)
1709 device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency;
1710 device->SamplesDone = 0;
1713 /* UpdateDeviceParams
1715 * Updates device parameters according to the attribute list (caller is
1716 * responsible for holding the list lock).
1718 static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
1720 ALCcontext *context;
1721 enum DevFmtChannels oldChans;
1722 enum DevFmtType oldType;
1723 ALCuint oldFreq;
1724 FPUCtl oldMode;
1725 size_t size;
1727 // Check for attributes
1728 if(device->Type == Loopback)
1730 enum {
1731 GotFreq = 1<<0,
1732 GotChans = 1<<1,
1733 GotType = 1<<2,
1734 GotAll = GotFreq|GotChans|GotType
1736 ALCuint freq, numMono, numStereo, numSends, flags;
1737 enum DevFmtChannels schans;
1738 enum DevFmtType stype;
1739 ALCuint attrIdx = 0;
1740 ALCint gotFmt = 0;
1742 if(!attrList)
1744 WARN("Missing attributes for loopback device\n");
1745 return ALC_INVALID_VALUE;
1748 numMono = device->NumMonoSources;
1749 numStereo = device->NumStereoSources;
1750 numSends = device->NumAuxSends;
1751 schans = device->FmtChans;
1752 stype = device->FmtType;
1753 freq = device->Frequency;
1754 flags = device->Flags;
1756 while(attrList[attrIdx])
1758 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT)
1760 ALCint val = attrList[attrIdx + 1];
1761 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val))
1762 return ALC_INVALID_VALUE;
1763 schans = val;
1764 gotFmt |= GotChans;
1767 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT)
1769 ALCint val = attrList[attrIdx + 1];
1770 if(!IsValidALCType(val) || !BytesFromDevFmt(val))
1771 return ALC_INVALID_VALUE;
1772 stype = val;
1773 gotFmt |= GotType;
1776 if(attrList[attrIdx] == ALC_FREQUENCY)
1778 freq = attrList[attrIdx + 1];
1779 if(freq < MIN_OUTPUT_RATE)
1780 return ALC_INVALID_VALUE;
1781 gotFmt |= GotFreq;
1784 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1786 numStereo = attrList[attrIdx + 1];
1787 if(numStereo > device->MaxNoOfSources)
1788 numStereo = device->MaxNoOfSources;
1790 numMono = device->MaxNoOfSources - numStereo;
1793 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1794 numSends = attrList[attrIdx + 1];
1796 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1798 if(attrList[attrIdx + 1] != ALC_FALSE)
1799 flags |= DEVICE_HRTF_REQUEST;
1800 else
1801 flags &= ~DEVICE_HRTF_REQUEST;
1804 attrIdx += 2;
1807 if(gotFmt != GotAll)
1809 WARN("Missing format for loopback device\n");
1810 return ALC_INVALID_VALUE;
1813 ConfigValueUInt(NULL, "sends", &numSends);
1814 numSends = minu(MAX_SENDS, numSends);
1816 if((device->Flags&DEVICE_RUNNING))
1817 V0(device->Backend,stop)();
1818 device->Flags = (flags & ~DEVICE_RUNNING);
1820 UpdateClockBase(device);
1822 device->Frequency = freq;
1823 device->FmtChans = schans;
1824 device->FmtType = stype;
1825 device->NumMonoSources = numMono;
1826 device->NumStereoSources = numStereo;
1827 device->NumAuxSends = numSends;
1829 else if(attrList && attrList[0])
1831 ALCuint freq, numMono, numStereo, numSends;
1832 ALCuint attrIdx = 0;
1834 /* If a context is already running on the device, stop playback so the
1835 * device attributes can be updated. */
1836 if((device->Flags&DEVICE_RUNNING))
1837 V0(device->Backend,stop)();
1838 device->Flags &= ~DEVICE_RUNNING;
1840 freq = device->Frequency;
1841 numMono = device->NumMonoSources;
1842 numStereo = device->NumStereoSources;
1843 numSends = device->NumAuxSends;
1845 while(attrList[attrIdx])
1847 if(attrList[attrIdx] == ALC_FREQUENCY)
1849 freq = attrList[attrIdx + 1];
1850 device->Flags |= DEVICE_FREQUENCY_REQUEST;
1853 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1855 numStereo = attrList[attrIdx + 1];
1856 if(numStereo > device->MaxNoOfSources)
1857 numStereo = device->MaxNoOfSources;
1859 numMono = device->MaxNoOfSources - numStereo;
1862 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1863 numSends = attrList[attrIdx + 1];
1865 if(attrList[attrIdx] == ALC_HRTF_SOFT)
1867 if(attrList[attrIdx + 1] != ALC_FALSE)
1868 device->Flags |= DEVICE_HRTF_REQUEST;
1869 else
1870 device->Flags &= ~DEVICE_HRTF_REQUEST;
1873 attrIdx += 2;
1876 ConfigValueUInt(NULL, "frequency", &freq);
1877 freq = maxu(freq, MIN_OUTPUT_RATE);
1879 ConfigValueUInt(NULL, "sends", &numSends);
1880 numSends = minu(MAX_SENDS, numSends);
1882 UpdateClockBase(device);
1884 device->UpdateSize = (ALuint64)device->UpdateSize * freq /
1885 device->Frequency;
1886 /* SSE and Neon do best with the update size being a multiple of 4 */
1887 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
1888 device->UpdateSize = (device->UpdateSize+3)&~3;
1890 device->Frequency = freq;
1891 device->NumMonoSources = numMono;
1892 device->NumStereoSources = numStereo;
1893 device->NumAuxSends = numSends;
1896 if((device->Flags&DEVICE_RUNNING))
1897 return ALC_NO_ERROR;
1899 al_free(device->DryBuffer);
1900 device->DryBuffer = NULL;
1902 UpdateClockBase(device);
1904 if(device->Type != Loopback && ((device->Flags&DEVICE_HRTF_REQUEST) || GetConfigValueBool(NULL, "hrtf", 0)))
1906 if(!FindHrtfFormat(&device->FmtChans, &device->Frequency))
1907 device->Flags &= ~DEVICE_HRTF_REQUEST;
1908 else
1909 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST |
1910 DEVICE_HRTF_REQUEST;
1912 if(device->Type == Loopback && (device->Flags&DEVICE_HRTF_REQUEST))
1914 enum DevFmtChannels chans = device->FmtChans;
1915 ALCuint freq = device->Frequency;
1916 if(!FindHrtfFormat(&chans, &freq) || chans != device->FmtChans || freq != device->Frequency)
1918 ERR("Requested format not HRTF compatible: %s, %uhz\n",
1919 DevFmtChannelsString(device->FmtChans), device->Frequency);
1920 device->Flags &= ~DEVICE_HRTF_REQUEST;
1924 oldFreq = device->Frequency;
1925 oldChans = device->FmtChans;
1926 oldType = device->FmtType;
1928 TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
1929 (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
1930 (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
1931 (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
1932 device->UpdateSize, device->NumUpdates
1935 if(V0(device->Backend,reset)() == ALC_FALSE)
1936 return ALC_INVALID_DEVICE;
1938 if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
1940 ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans),
1941 DevFmtChannelsString(device->FmtChans));
1942 device->Flags &= ~DEVICE_CHANNELS_REQUEST;
1944 if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST))
1946 ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType),
1947 DevFmtTypeString(device->FmtType));
1948 device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST;
1950 if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST))
1952 ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency);
1953 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
1956 TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
1957 DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
1958 device->Frequency, device->UpdateSize, device->NumUpdates
1961 if((device->UpdateSize&3) != 0)
1963 if((CPUCapFlags&CPU_CAP_SSE))
1964 WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1965 if((CPUCapFlags&CPU_CAP_NEON))
1966 WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
1969 device->Hrtf = NULL;
1970 if(device->FmtChans != DevFmtStereo)
1972 free(device->Bs2b);
1973 device->Bs2b = NULL;
1975 else
1977 bool headphones = device->IsHeadphones;
1978 const char *mode;
1979 int bs2blevel;
1980 int usehrtf;
1982 if(device->Type != Loopback && ConfigValueStr(NULL, "stereo-mode", &mode))
1984 if(strcasecmp(mode, "headphones") == 0)
1985 headphones = true;
1986 else if(strcasecmp(mode, "speakers") == 0)
1987 headphones = false;
1988 else if(strcasecmp(mode, "auto") != 0)
1989 ERR("Unexpected stereo-mode: %s\n", mode);
1992 if(device->Type == Loopback || !ConfigValueBool(NULL, "hrtf", &usehrtf))
1993 usehrtf = ((device->Flags&DEVICE_HRTF_REQUEST) || headphones);
1995 if(usehrtf)
1996 device->Hrtf = GetHrtf(device->FmtChans, device->Frequency);
1997 if(device->Hrtf)
1998 TRACE("HRTF enabled\n");
1999 else
2001 device->Flags &= ~DEVICE_HRTF_REQUEST;
2002 TRACE("HRTF disabled\n");
2004 bs2blevel = (headphones ? 5 : 0);
2005 if(device->Type != Loopback)
2006 ConfigValueInt(NULL, "cf_level", &bs2blevel);
2007 if(bs2blevel > 0 && bs2blevel <= 6)
2009 if(!device->Bs2b)
2011 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
2012 bs2b_clear(device->Bs2b);
2014 bs2b_set_srate(device->Bs2b, device->Frequency);
2015 bs2b_set_level(device->Bs2b, bs2blevel);
2016 TRACE("BS2B enabled\n");
2018 else
2020 free(device->Bs2b);
2021 device->Bs2b = NULL;
2022 TRACE("BS2B disabled\n");
2027 aluInitPanning(device);
2029 /* With HRTF enabled, virtual channels are allocated for B-Format and
2030 * effects renfering. Two extra channels are allocated for the actual HRTF-
2031 * filtered output.
2033 size = sizeof(device->DryBuffer[0]) * (device->NumChannels + (device->Hrtf ? 2 : 0));
2034 device->DryBuffer = al_calloc(16, size);
2035 if(!device->DryBuffer)
2037 ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
2038 return ALC_INVALID_DEVICE;
2041 V(device->Synth,update)(device);
2043 SetMixerFPUMode(&oldMode);
2044 V0(device->Backend,lock)();
2045 context = ATOMIC_LOAD(&device->ContextList);
2046 while(context)
2048 ALsizei pos;
2050 ATOMIC_STORE(&context->UpdateSources, AL_FALSE);
2051 LockUIntMapRead(&context->EffectSlotMap);
2052 for(pos = 0;pos < context->EffectSlotMap.size;pos++)
2054 ALeffectslot *slot = context->EffectSlotMap.array[pos].value;
2056 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2058 UnlockUIntMapRead(&context->EffectSlotMap);
2059 V0(device->Backend,unlock)();
2060 RestoreFPUMode(&oldMode);
2061 return ALC_INVALID_DEVICE;
2063 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2064 V(slot->EffectState,update)(device, slot);
2066 UnlockUIntMapRead(&context->EffectSlotMap);
2068 LockUIntMapRead(&context->SourceMap);
2069 for(pos = 0;pos < context->SourceMap.size;pos++)
2071 ALsource *source = context->SourceMap.array[pos].value;
2072 ALuint s = device->NumAuxSends;
2073 while(s < MAX_SENDS)
2075 if(source->Send[s].Slot)
2076 DecrementRef(&source->Send[s].Slot->ref);
2077 source->Send[s].Slot = NULL;
2078 source->Send[s].Gain = 1.0f;
2079 source->Send[s].GainHF = 1.0f;
2080 s++;
2082 ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE);
2084 UnlockUIntMapRead(&context->SourceMap);
2086 for(pos = 0;pos < context->VoiceCount;pos++)
2088 ALvoice *voice = &context->Voices[pos];
2089 ALsource *source = voice->Source;
2090 ALuint s = device->NumAuxSends;
2092 while(s < MAX_SENDS)
2094 voice->Send[s].Moving = AL_FALSE;
2095 voice->Send[s].Counter = 0;
2096 s++;
2099 if(source)
2101 ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE);
2102 voice->Update(voice, source, context);
2106 context = context->next;
2108 if(device->DefaultSlot)
2110 ALeffectslot *slot = device->DefaultSlot;
2112 if(V(slot->EffectState,deviceUpdate)(device) == AL_FALSE)
2114 V0(device->Backend,unlock)();
2115 RestoreFPUMode(&oldMode);
2116 return ALC_INVALID_DEVICE;
2118 ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE);
2119 V(slot->EffectState,update)(device, slot);
2121 V0(device->Backend,unlock)();
2122 RestoreFPUMode(&oldMode);
2124 if(!(device->Flags&DEVICE_PAUSED))
2126 if(V0(device->Backend,start)() == ALC_FALSE)
2127 return ALC_INVALID_DEVICE;
2128 device->Flags |= DEVICE_RUNNING;
2131 return ALC_NO_ERROR;
2134 /* FreeDevice
2136 * Frees the device structure, and destroys any objects the app failed to
2137 * delete. Called once there's no more references on the device.
2139 static ALCvoid FreeDevice(ALCdevice *device)
2141 TRACE("%p\n", device);
2143 V0(device->Backend,close)();
2144 DELETE_OBJ(device->Backend);
2145 device->Backend = NULL;
2147 DELETE_OBJ(device->Synth);
2148 device->Synth = NULL;
2150 if(device->DefaultSlot)
2152 ALeffectState *state = device->DefaultSlot->EffectState;
2153 device->DefaultSlot = NULL;
2154 DELETE_OBJ(state);
2157 if(device->DefaultSfont)
2158 ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
2159 device->DefaultSfont = NULL;
2161 if(device->BufferMap.size > 0)
2163 WARN("(%p) Deleting %d Buffer(s)\n", device, device->BufferMap.size);
2164 ReleaseALBuffers(device);
2166 ResetUIntMap(&device->BufferMap);
2168 if(device->EffectMap.size > 0)
2170 WARN("(%p) Deleting %d Effect(s)\n", device, device->EffectMap.size);
2171 ReleaseALEffects(device);
2173 ResetUIntMap(&device->EffectMap);
2175 if(device->FilterMap.size > 0)
2177 WARN("(%p) Deleting %d Filter(s)\n", device, device->FilterMap.size);
2178 ReleaseALFilters(device);
2180 ResetUIntMap(&device->FilterMap);
2182 if(device->SfontMap.size > 0)
2184 WARN("(%p) Deleting %d Soundfont(s)\n", device, device->SfontMap.size);
2185 ReleaseALSoundfonts(device);
2187 ResetUIntMap(&device->SfontMap);
2189 if(device->PresetMap.size > 0)
2191 WARN("(%p) Deleting %d Preset(s)\n", device, device->PresetMap.size);
2192 ReleaseALPresets(device);
2194 ResetUIntMap(&device->PresetMap);
2196 if(device->FontsoundMap.size > 0)
2198 WARN("(%p) Deleting %d Fontsound(s)\n", device, device->FontsoundMap.size);
2199 ReleaseALFontsounds(device);
2201 ResetUIntMap(&device->FontsoundMap);
2203 free(device->Bs2b);
2204 device->Bs2b = NULL;
2206 AL_STRING_DEINIT(device->DeviceName);
2208 al_free(device->DryBuffer);
2209 device->DryBuffer = NULL;
2211 al_free(device);
2215 void ALCdevice_IncRef(ALCdevice *device)
2217 uint ref;
2218 ref = IncrementRef(&device->ref);
2219 TRACEREF("%p increasing refcount to %u\n", device, ref);
2222 void ALCdevice_DecRef(ALCdevice *device)
2224 uint ref;
2225 ref = DecrementRef(&device->ref);
2226 TRACEREF("%p decreasing refcount to %u\n", device, ref);
2227 if(ref == 0) FreeDevice(device);
2230 /* VerifyDevice
2232 * Checks if the device handle is valid, and increments its ref count if so.
2234 static ALCdevice *VerifyDevice(ALCdevice *device)
2236 ALCdevice *tmpDevice;
2238 if(!device)
2239 return NULL;
2241 LockLists();
2242 tmpDevice = ATOMIC_LOAD(&DeviceList);
2243 while(tmpDevice && tmpDevice != device)
2244 tmpDevice = tmpDevice->next;
2246 if(tmpDevice)
2247 ALCdevice_IncRef(tmpDevice);
2248 UnlockLists();
2249 return tmpDevice;
2253 /* InitContext
2255 * Initializes context fields
2257 static ALvoid InitContext(ALCcontext *Context)
2259 //Initialise listener
2260 Context->Listener->Gain = 1.0f;
2261 Context->Listener->MetersPerUnit = 1.0f;
2262 aluVectorSet(&Context->Listener->Position, 0.0f, 0.0f, 0.0f, 1.0f);
2263 aluVectorSet(&Context->Listener->Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2264 Context->Listener->Forward[0] = 0.0f;
2265 Context->Listener->Forward[1] = 0.0f;
2266 Context->Listener->Forward[2] = -1.0f;
2267 Context->Listener->Up[0] = 0.0f;
2268 Context->Listener->Up[1] = 1.0f;
2269 Context->Listener->Up[2] = 0.0f;
2270 aluMatrixSet(&Context->Listener->Params.Matrix,
2271 1.0f, 0.0f, 0.0f, 0.0f,
2272 0.0f, 1.0f, 0.0f, 0.0f,
2273 0.0f, 0.0f, 1.0f, 0.0f,
2274 0.0f, 0.0f, 0.0f, 1.0f
2276 aluVectorSet(&Context->Listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
2278 //Validate Context
2279 ATOMIC_INIT(&Context->LastError, AL_NO_ERROR);
2280 ATOMIC_INIT(&Context->UpdateSources, AL_FALSE);
2281 InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources);
2282 InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax);
2284 //Set globals
2285 Context->DistanceModel = DefaultDistanceModel;
2286 Context->SourceDistanceModel = AL_FALSE;
2287 Context->DopplerFactor = 1.0f;
2288 Context->DopplerVelocity = 1.0f;
2289 Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
2290 Context->DeferUpdates = AL_FALSE;
2292 Context->ExtensionList = alExtList;
2296 /* FreeContext
2298 * Cleans up the context, and destroys any remaining objects the app failed to
2299 * delete. Called once there's no more references on the context.
2301 static void FreeContext(ALCcontext *context)
2303 TRACE("%p\n", context);
2305 if(context->SourceMap.size > 0)
2307 WARN("(%p) Deleting %d Source(s)\n", context, context->SourceMap.size);
2308 ReleaseALSources(context);
2310 ResetUIntMap(&context->SourceMap);
2312 if(context->EffectSlotMap.size > 0)
2314 WARN("(%p) Deleting %d AuxiliaryEffectSlot(s)\n", context, context->EffectSlotMap.size);
2315 ReleaseALAuxiliaryEffectSlots(context);
2317 ResetUIntMap(&context->EffectSlotMap);
2319 al_free(context->Voices);
2320 context->Voices = NULL;
2321 context->VoiceCount = 0;
2322 context->MaxVoices = 0;
2324 VECTOR_DEINIT(context->ActiveAuxSlots);
2326 ALCdevice_DecRef(context->Device);
2327 context->Device = NULL;
2329 //Invalidate context
2330 memset(context, 0, sizeof(ALCcontext));
2331 al_free(context);
2334 /* ReleaseContext
2336 * Removes the context reference from the given device and removes it from
2337 * being current on the running thread or globally.
2339 static void ReleaseContext(ALCcontext *context, ALCdevice *device)
2341 ALCcontext *nextctx;
2342 ALCcontext *origctx;
2344 if(altss_get(LocalContext) == context)
2346 WARN("%p released while current on thread\n", context);
2347 altss_set(LocalContext, NULL);
2348 ALCcontext_DecRef(context);
2351 origctx = context;
2352 if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL))
2353 ALCcontext_DecRef(context);
2355 ALCdevice_Lock(device);
2356 origctx = context;
2357 nextctx = context->next;
2358 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx))
2360 ALCcontext *list;
2361 do {
2362 list = origctx;
2363 origctx = context;
2364 } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx));
2366 ALCdevice_Unlock(device);
2368 ALCcontext_DecRef(context);
2371 void ALCcontext_IncRef(ALCcontext *context)
2373 uint ref;
2374 ref = IncrementRef(&context->ref);
2375 TRACEREF("%p increasing refcount to %u\n", context, ref);
2378 void ALCcontext_DecRef(ALCcontext *context)
2380 uint ref;
2381 ref = DecrementRef(&context->ref);
2382 TRACEREF("%p decreasing refcount to %u\n", context, ref);
2383 if(ref == 0) FreeContext(context);
2386 static void ReleaseThreadCtx(void *ptr)
2388 WARN("%p current for thread being destroyed\n", ptr);
2389 ALCcontext_DecRef(ptr);
2392 /* VerifyContext
2394 * Checks that the given context is valid, and increments its reference count.
2396 static ALCcontext *VerifyContext(ALCcontext *context)
2398 ALCdevice *dev;
2400 LockLists();
2401 dev = ATOMIC_LOAD(&DeviceList);
2402 while(dev)
2404 ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList);
2405 while(ctx)
2407 if(ctx == context)
2409 ALCcontext_IncRef(ctx);
2410 UnlockLists();
2411 return ctx;
2413 ctx = ctx->next;
2415 dev = dev->next;
2417 UnlockLists();
2419 return NULL;
2423 /* GetContextRef
2425 * Returns the currently active context for this thread, and adds a reference
2426 * without locking it.
2428 ALCcontext *GetContextRef(void)
2430 ALCcontext *context;
2432 context = altss_get(LocalContext);
2433 if(context)
2434 ALCcontext_IncRef(context);
2435 else
2437 LockLists();
2438 context = ATOMIC_LOAD(&GlobalContext);
2439 if(context)
2440 ALCcontext_IncRef(context);
2441 UnlockLists();
2444 return context;
2448 /************************************************
2449 * Standard ALC functions
2450 ************************************************/
2452 /* alcGetError
2454 * Return last ALC generated error code for the given device
2456 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
2458 ALCenum errorCode;
2460 if(VerifyDevice(device))
2462 errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR);
2463 ALCdevice_DecRef(device);
2465 else
2466 errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR);
2468 return errorCode;
2472 /* alcSuspendContext
2474 * Suspends updates for the given context
2476 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context)
2478 if(!SuspendDefers)
2479 return;
2481 context = VerifyContext(context);
2482 if(!context)
2483 alcSetError(NULL, ALC_INVALID_CONTEXT);
2484 else
2486 ALCcontext_DeferUpdates(context);
2487 ALCcontext_DecRef(context);
2491 /* alcProcessContext
2493 * Resumes processing updates for the given context
2495 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
2497 if(!SuspendDefers)
2498 return;
2500 context = VerifyContext(context);
2501 if(!context)
2502 alcSetError(NULL, ALC_INVALID_CONTEXT);
2503 else
2505 ALCcontext_ProcessUpdates(context);
2506 ALCcontext_DecRef(context);
2511 /* alcGetString
2513 * Returns information about the device, and error strings
2515 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
2517 const ALCchar *value = NULL;
2519 switch(param)
2521 case ALC_NO_ERROR:
2522 value = alcNoError;
2523 break;
2525 case ALC_INVALID_ENUM:
2526 value = alcErrInvalidEnum;
2527 break;
2529 case ALC_INVALID_VALUE:
2530 value = alcErrInvalidValue;
2531 break;
2533 case ALC_INVALID_DEVICE:
2534 value = alcErrInvalidDevice;
2535 break;
2537 case ALC_INVALID_CONTEXT:
2538 value = alcErrInvalidContext;
2539 break;
2541 case ALC_OUT_OF_MEMORY:
2542 value = alcErrOutOfMemory;
2543 break;
2545 case ALC_DEVICE_SPECIFIER:
2546 value = alcDefaultName;
2547 break;
2549 case ALC_ALL_DEVICES_SPECIFIER:
2550 if(VerifyDevice(Device))
2552 value = al_string_get_cstr(Device->DeviceName);
2553 ALCdevice_DecRef(Device);
2555 else
2557 ProbeAllDevicesList();
2558 value = al_string_get_cstr(alcAllDevicesList);
2560 break;
2562 case ALC_CAPTURE_DEVICE_SPECIFIER:
2563 if(VerifyDevice(Device))
2565 value = al_string_get_cstr(Device->DeviceName);
2566 ALCdevice_DecRef(Device);
2568 else
2570 ProbeCaptureDeviceList();
2571 value = al_string_get_cstr(alcCaptureDeviceList);
2573 break;
2575 /* Default devices are always first in the list */
2576 case ALC_DEFAULT_DEVICE_SPECIFIER:
2577 value = alcDefaultName;
2578 break;
2580 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
2581 if(al_string_empty(alcAllDevicesList))
2582 ProbeAllDevicesList();
2584 Device = VerifyDevice(Device);
2586 free(alcDefaultAllDevicesSpecifier);
2587 alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList));
2588 if(!alcDefaultAllDevicesSpecifier)
2589 alcSetError(Device, ALC_OUT_OF_MEMORY);
2591 value = alcDefaultAllDevicesSpecifier;
2592 if(Device) ALCdevice_DecRef(Device);
2593 break;
2595 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
2596 if(al_string_empty(alcCaptureDeviceList))
2597 ProbeCaptureDeviceList();
2599 Device = VerifyDevice(Device);
2601 free(alcCaptureDefaultDeviceSpecifier);
2602 alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList));
2603 if(!alcCaptureDefaultDeviceSpecifier)
2604 alcSetError(Device, ALC_OUT_OF_MEMORY);
2606 value = alcCaptureDefaultDeviceSpecifier;
2607 if(Device) ALCdevice_DecRef(Device);
2608 break;
2610 case ALC_EXTENSIONS:
2611 if(!VerifyDevice(Device))
2612 value = alcNoDeviceExtList;
2613 else
2615 value = alcExtensionList;
2616 ALCdevice_DecRef(Device);
2618 break;
2620 default:
2621 Device = VerifyDevice(Device);
2622 alcSetError(Device, ALC_INVALID_ENUM);
2623 if(Device) ALCdevice_DecRef(Device);
2624 break;
2627 return value;
2631 static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2633 ALCsizei i;
2635 if(size <= 0 || values == NULL)
2637 alcSetError(device, ALC_INVALID_VALUE);
2638 return 0;
2641 if(!device)
2643 switch(param)
2645 case ALC_MAJOR_VERSION:
2646 values[0] = alcMajorVersion;
2647 return 1;
2648 case ALC_MINOR_VERSION:
2649 values[0] = alcMinorVersion;
2650 return 1;
2652 case ALC_ATTRIBUTES_SIZE:
2653 case ALC_ALL_ATTRIBUTES:
2654 case ALC_FREQUENCY:
2655 case ALC_REFRESH:
2656 case ALC_SYNC:
2657 case ALC_MONO_SOURCES:
2658 case ALC_STEREO_SOURCES:
2659 case ALC_CAPTURE_SAMPLES:
2660 case ALC_FORMAT_CHANNELS_SOFT:
2661 case ALC_FORMAT_TYPE_SOFT:
2662 alcSetError(NULL, ALC_INVALID_DEVICE);
2663 return 0;
2665 default:
2666 alcSetError(NULL, ALC_INVALID_ENUM);
2667 return 0;
2669 return 0;
2672 if(device->Type == Capture)
2674 switch(param)
2676 case ALC_CAPTURE_SAMPLES:
2677 V0(device->Backend,lock)();
2678 values[0] = V0(device->Backend,availableSamples)();
2679 V0(device->Backend,unlock)();
2680 return 1;
2682 case ALC_CONNECTED:
2683 values[0] = device->Connected;
2684 return 1;
2686 default:
2687 alcSetError(device, ALC_INVALID_ENUM);
2688 return 0;
2690 return 0;
2693 /* render device */
2694 switch(param)
2696 case ALC_MAJOR_VERSION:
2697 values[0] = alcMajorVersion;
2698 return 1;
2700 case ALC_MINOR_VERSION:
2701 values[0] = alcMinorVersion;
2702 return 1;
2704 case ALC_EFX_MAJOR_VERSION:
2705 values[0] = alcEFXMajorVersion;
2706 return 1;
2708 case ALC_EFX_MINOR_VERSION:
2709 values[0] = alcEFXMinorVersion;
2710 return 1;
2712 case ALC_ATTRIBUTES_SIZE:
2713 values[0] = 15;
2714 return 1;
2716 case ALC_ALL_ATTRIBUTES:
2717 if(size < 15)
2719 alcSetError(device, ALC_INVALID_VALUE);
2720 return 0;
2723 i = 0;
2724 values[i++] = ALC_FREQUENCY;
2725 values[i++] = device->Frequency;
2727 if(device->Type != Loopback)
2729 values[i++] = ALC_REFRESH;
2730 values[i++] = device->Frequency / device->UpdateSize;
2732 values[i++] = ALC_SYNC;
2733 values[i++] = ALC_FALSE;
2735 else
2737 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2738 values[i++] = device->FmtChans;
2740 values[i++] = ALC_FORMAT_TYPE_SOFT;
2741 values[i++] = device->FmtType;
2744 values[i++] = ALC_MONO_SOURCES;
2745 values[i++] = device->NumMonoSources;
2747 values[i++] = ALC_STEREO_SOURCES;
2748 values[i++] = device->NumStereoSources;
2750 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2751 values[i++] = device->NumAuxSends;
2753 values[i++] = ALC_HRTF_SOFT;
2754 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2756 values[i++] = 0;
2757 return i;
2759 case ALC_FREQUENCY:
2760 values[0] = device->Frequency;
2761 return 1;
2763 case ALC_REFRESH:
2764 if(device->Type == Loopback)
2766 alcSetError(device, ALC_INVALID_DEVICE);
2767 return 0;
2769 values[0] = device->Frequency / device->UpdateSize;
2770 return 1;
2772 case ALC_SYNC:
2773 if(device->Type == Loopback)
2775 alcSetError(device, ALC_INVALID_DEVICE);
2776 return 0;
2778 values[0] = ALC_FALSE;
2779 return 1;
2781 case ALC_FORMAT_CHANNELS_SOFT:
2782 if(device->Type != Loopback)
2784 alcSetError(device, ALC_INVALID_DEVICE);
2785 return 0;
2787 values[0] = device->FmtChans;
2788 return 1;
2790 case ALC_FORMAT_TYPE_SOFT:
2791 if(device->Type != Loopback)
2793 alcSetError(device, ALC_INVALID_DEVICE);
2794 return 0;
2796 values[0] = device->FmtType;
2797 return 1;
2799 case ALC_MONO_SOURCES:
2800 values[0] = device->NumMonoSources;
2801 return 1;
2803 case ALC_STEREO_SOURCES:
2804 values[0] = device->NumStereoSources;
2805 return 1;
2807 case ALC_MAX_AUXILIARY_SENDS:
2808 values[0] = device->NumAuxSends;
2809 return 1;
2811 case ALC_CONNECTED:
2812 values[0] = device->Connected;
2813 return 1;
2815 case ALC_HRTF_SOFT:
2816 values[0] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2817 return 1;
2819 default:
2820 alcSetError(device, ALC_INVALID_ENUM);
2821 return 0;
2823 return 0;
2826 /* alcGetIntegerv
2828 * Returns information about the device and the version of OpenAL
2830 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
2832 device = VerifyDevice(device);
2833 if(size <= 0 || values == NULL)
2834 alcSetError(device, ALC_INVALID_VALUE);
2835 else
2836 GetIntegerv(device, param, size, values);
2837 if(device) ALCdevice_DecRef(device);
2840 ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
2842 ALCint *ivals;
2843 ALsizei i;
2845 device = VerifyDevice(device);
2846 if(size <= 0 || values == NULL)
2847 alcSetError(device, ALC_INVALID_VALUE);
2848 else if(!device || device->Type == Capture)
2850 ivals = malloc(size * sizeof(ALCint));
2851 size = GetIntegerv(device, pname, size, ivals);
2852 for(i = 0;i < size;i++)
2853 values[i] = ivals[i];
2854 free(ivals);
2856 else /* render device */
2858 switch(pname)
2860 case ALC_ATTRIBUTES_SIZE:
2861 *values = 17;
2862 break;
2864 case ALC_ALL_ATTRIBUTES:
2865 if(size < 17)
2866 alcSetError(device, ALC_INVALID_VALUE);
2867 else
2869 int i = 0;
2871 V0(device->Backend,lock)();
2872 values[i++] = ALC_FREQUENCY;
2873 values[i++] = device->Frequency;
2875 if(device->Type != Loopback)
2877 values[i++] = ALC_REFRESH;
2878 values[i++] = device->Frequency / device->UpdateSize;
2880 values[i++] = ALC_SYNC;
2881 values[i++] = ALC_FALSE;
2883 else
2885 values[i++] = ALC_FORMAT_CHANNELS_SOFT;
2886 values[i++] = device->FmtChans;
2888 values[i++] = ALC_FORMAT_TYPE_SOFT;
2889 values[i++] = device->FmtType;
2892 values[i++] = ALC_MONO_SOURCES;
2893 values[i++] = device->NumMonoSources;
2895 values[i++] = ALC_STEREO_SOURCES;
2896 values[i++] = device->NumStereoSources;
2898 values[i++] = ALC_MAX_AUXILIARY_SENDS;
2899 values[i++] = device->NumAuxSends;
2901 values[i++] = ALC_HRTF_SOFT;
2902 values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE);
2904 values[i++] = ALC_DEVICE_CLOCK_SOFT;
2905 values[i++] = device->ClockBase +
2906 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2908 values[i++] = 0;
2909 V0(device->Backend,unlock)();
2911 break;
2913 case ALC_DEVICE_CLOCK_SOFT:
2914 V0(device->Backend,lock)();
2915 *values = device->ClockBase +
2916 (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency);
2917 V0(device->Backend,unlock)();
2918 break;
2920 default:
2921 ivals = malloc(size * sizeof(ALCint));
2922 size = GetIntegerv(device, pname, size, ivals);
2923 for(i = 0;i < size;i++)
2924 values[i] = ivals[i];
2925 free(ivals);
2926 break;
2929 if(device)
2930 ALCdevice_DecRef(device);
2934 /* alcIsExtensionPresent
2936 * Determines if there is support for a particular extension
2938 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
2940 ALCboolean bResult = ALC_FALSE;
2942 device = VerifyDevice(device);
2944 if(!extName)
2945 alcSetError(device, ALC_INVALID_VALUE);
2946 else
2948 size_t len = strlen(extName);
2949 const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
2950 while(ptr && *ptr)
2952 if(strncasecmp(ptr, extName, len) == 0 &&
2953 (ptr[len] == '\0' || isspace(ptr[len])))
2955 bResult = ALC_TRUE;
2956 break;
2958 if((ptr=strchr(ptr, ' ')) != NULL)
2960 do {
2961 ++ptr;
2962 } while(isspace(*ptr));
2966 if(device)
2967 ALCdevice_DecRef(device);
2968 return bResult;
2972 /* alcGetProcAddress
2974 * Retrieves the function address for a particular extension function
2976 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
2978 ALCvoid *ptr = NULL;
2980 if(!funcName)
2982 device = VerifyDevice(device);
2983 alcSetError(device, ALC_INVALID_VALUE);
2984 if(device) ALCdevice_DecRef(device);
2986 else
2988 ALsizei i = 0;
2989 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0)
2990 i++;
2991 ptr = alcFunctions[i].address;
2994 return ptr;
2998 /* alcGetEnumValue
3000 * Get the value for a particular ALC enumeration name
3002 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
3004 ALCenum val = 0;
3006 if(!enumName)
3008 device = VerifyDevice(device);
3009 alcSetError(device, ALC_INVALID_VALUE);
3010 if(device) ALCdevice_DecRef(device);
3012 else
3014 ALsizei i = 0;
3015 while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0)
3016 i++;
3017 val = enumeration[i].value;
3020 return val;
3024 /* alcCreateContext
3026 * Create and attach a context to the given device.
3028 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
3030 ALCcontext *ALContext;
3031 ALCenum err;
3033 LockLists();
3034 if(!(device=VerifyDevice(device)) || device->Type == Capture || !device->Connected)
3036 UnlockLists();
3037 alcSetError(device, ALC_INVALID_DEVICE);
3038 if(device) ALCdevice_DecRef(device);
3039 return NULL;
3042 ATOMIC_STORE(&device->LastError, ALC_NO_ERROR);
3044 if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
3046 UnlockLists();
3047 alcSetError(device, err);
3048 if(err == ALC_INVALID_DEVICE)
3050 V0(device->Backend,lock)();
3051 aluHandleDisconnect(device);
3052 V0(device->Backend,unlock)();
3054 ALCdevice_DecRef(device);
3055 return NULL;
3058 ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener));
3059 if(ALContext)
3061 InitRef(&ALContext->ref, 1);
3062 ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
3064 VECTOR_INIT(ALContext->ActiveAuxSlots);
3066 ALContext->VoiceCount = 0;
3067 ALContext->MaxVoices = 256;
3068 ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0]));
3070 if(!ALContext || !ALContext->Voices)
3072 if(!ATOMIC_LOAD(&device->ContextList))
3074 V0(device->Backend,stop)();
3075 device->Flags &= ~DEVICE_RUNNING;
3077 UnlockLists();
3079 if(ALContext)
3081 al_free(ALContext->Voices);
3082 ALContext->Voices = NULL;
3084 VECTOR_DEINIT(ALContext->ActiveAuxSlots);
3086 al_free(ALContext);
3087 ALContext = NULL;
3090 alcSetError(device, ALC_OUT_OF_MEMORY);
3091 ALCdevice_DecRef(device);
3092 return NULL;
3095 ALContext->Device = device;
3096 ALCdevice_IncRef(device);
3097 InitContext(ALContext);
3100 ALCcontext *head = ATOMIC_LOAD(&device->ContextList);
3101 do {
3102 ALContext->next = head;
3103 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext));
3105 UnlockLists();
3107 ALCdevice_DecRef(device);
3109 TRACE("Created context %p\n", ALContext);
3110 return ALContext;
3113 /* alcDestroyContext
3115 * Remove a context from its device
3117 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context)
3119 ALCdevice *Device;
3121 LockLists();
3122 /* alcGetContextsDevice sets an error for invalid contexts */
3123 Device = alcGetContextsDevice(context);
3124 if(Device)
3126 ReleaseContext(context, Device);
3127 if(!ATOMIC_LOAD(&Device->ContextList))
3129 V0(Device->Backend,stop)();
3130 Device->Flags &= ~DEVICE_RUNNING;
3133 UnlockLists();
3137 /* alcGetCurrentContext
3139 * Returns the currently active context on the calling thread
3141 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
3143 ALCcontext *Context = altss_get(LocalContext);
3144 if(!Context) Context = ATOMIC_LOAD(&GlobalContext);
3145 return Context;
3148 /* alcGetThreadContext
3150 * Returns the currently active thread-local context
3152 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
3154 return altss_get(LocalContext);
3158 /* alcMakeContextCurrent
3160 * Makes the given context the active process-wide context, and removes the
3161 * thread-local context for the calling thread.
3163 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
3165 /* context must be valid or NULL */
3166 if(context && !(context=VerifyContext(context)))
3168 alcSetError(NULL, ALC_INVALID_CONTEXT);
3169 return ALC_FALSE;
3171 /* context's reference count is already incremented */
3172 context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context);
3173 if(context) ALCcontext_DecRef(context);
3175 if((context=altss_get(LocalContext)) != NULL)
3177 altss_set(LocalContext, NULL);
3178 ALCcontext_DecRef(context);
3181 return ALC_TRUE;
3184 /* alcSetThreadContext
3186 * Makes the given context the active context for the current thread
3188 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
3190 ALCcontext *old;
3192 /* context must be valid or NULL */
3193 if(context && !(context=VerifyContext(context)))
3195 alcSetError(NULL, ALC_INVALID_CONTEXT);
3196 return ALC_FALSE;
3198 /* context's reference count is already incremented */
3199 old = altss_get(LocalContext);
3200 altss_set(LocalContext, context);
3201 if(old) ALCcontext_DecRef(old);
3203 return ALC_TRUE;
3207 /* alcGetContextsDevice
3209 * Returns the device that a particular context is attached to
3211 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context)
3213 ALCdevice *Device;
3215 if(!(Context=VerifyContext(Context)))
3217 alcSetError(NULL, ALC_INVALID_CONTEXT);
3218 return NULL;
3220 Device = Context->Device;
3221 ALCcontext_DecRef(Context);
3223 return Device;
3227 /* alcOpenDevice
3229 * Opens the named device.
3231 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
3233 const ALCchar *fmt;
3234 ALCdevice *device;
3235 ALCenum err;
3237 DO_INITCONFIG();
3239 if(!PlaybackBackend.name)
3241 alcSetError(NULL, ALC_INVALID_VALUE);
3242 return NULL;
3245 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3246 deviceName = NULL;
3248 device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot));
3249 if(!device)
3251 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3252 return NULL;
3255 //Validate device
3256 InitRef(&device->ref, 1);
3257 device->Connected = ALC_TRUE;
3258 device->Type = Playback;
3259 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3261 device->Flags = 0;
3262 device->Bs2b = NULL;
3263 AL_STRING_INIT(device->DeviceName);
3264 device->DryBuffer = NULL;
3266 ATOMIC_INIT(&device->ContextList, NULL);
3268 device->ClockBase = 0;
3269 device->SamplesDone = 0;
3271 device->MaxNoOfSources = 256;
3272 device->AuxiliaryEffectSlotMax = 4;
3273 device->NumAuxSends = MAX_SENDS;
3275 InitUIntMap(&device->BufferMap, ~0);
3276 InitUIntMap(&device->EffectMap, ~0);
3277 InitUIntMap(&device->FilterMap, ~0);
3278 InitUIntMap(&device->SfontMap, ~0);
3279 InitUIntMap(&device->PresetMap, ~0);
3280 InitUIntMap(&device->FontsoundMap, ~0);
3282 //Set output format
3283 device->FmtChans = DevFmtChannelsDefault;
3284 device->FmtType = DevFmtTypeDefault;
3285 device->Frequency = DEFAULT_OUTPUT_RATE;
3286 device->IsHeadphones = AL_FALSE;
3287 device->NumUpdates = 4;
3288 device->UpdateSize = 1024;
3290 if(!PlaybackBackend.getFactory)
3291 device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs,
3292 ALCbackend_Playback);
3293 else
3295 ALCbackendFactory *factory = PlaybackBackend.getFactory();
3296 device->Backend = V(factory,createBackend)(device, ALCbackend_Playback);
3298 if(!device->Backend)
3300 al_free(device);
3301 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3302 return NULL;
3306 if(ConfigValueStr(NULL, "channels", &fmt))
3308 static const struct {
3309 const char name[16];
3310 enum DevFmtChannels chans;
3311 } chanlist[] = {
3312 { "mono", DevFmtMono },
3313 { "stereo", DevFmtStereo },
3314 { "quad", DevFmtQuad },
3315 { "surround51", DevFmtX51 },
3316 { "surround61", DevFmtX61 },
3317 { "surround71", DevFmtX71 },
3318 { "surround51rear", DevFmtX51Rear },
3320 size_t i;
3322 for(i = 0;i < COUNTOF(chanlist);i++)
3324 if(strcasecmp(chanlist[i].name, fmt) == 0)
3326 device->FmtChans = chanlist[i].chans;
3327 device->Flags |= DEVICE_CHANNELS_REQUEST;
3328 break;
3331 if(i == COUNTOF(chanlist))
3332 ERR("Unsupported channels: %s\n", fmt);
3334 if(ConfigValueStr(NULL, "sample-type", &fmt))
3336 static const struct {
3337 const char name[16];
3338 enum DevFmtType type;
3339 } typelist[] = {
3340 { "int8", DevFmtByte },
3341 { "uint8", DevFmtUByte },
3342 { "int16", DevFmtShort },
3343 { "uint16", DevFmtUShort },
3344 { "int32", DevFmtInt },
3345 { "uint32", DevFmtUInt },
3346 { "float32", DevFmtFloat },
3348 size_t i;
3350 for(i = 0;i < COUNTOF(typelist);i++)
3352 if(strcasecmp(typelist[i].name, fmt) == 0)
3354 device->FmtType = typelist[i].type;
3355 device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST;
3356 break;
3359 if(i == COUNTOF(typelist))
3360 ERR("Unsupported sample-type: %s\n", fmt);
3363 if(ConfigValueUInt(NULL, "frequency", &device->Frequency))
3365 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3366 if(device->Frequency < MIN_OUTPUT_RATE)
3367 ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE);
3368 device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE);
3371 ConfigValueUInt(NULL, "periods", &device->NumUpdates);
3372 device->NumUpdates = clampu(device->NumUpdates, 2, 16);
3374 ConfigValueUInt(NULL, "period_size", &device->UpdateSize);
3375 device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
3376 if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
3377 device->UpdateSize = (device->UpdateSize+3)&~3;
3379 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3380 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3382 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3383 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3385 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3386 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3388 device->NumStereoSources = 1;
3389 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3391 device->Synth = SynthCreate(device);
3392 if(!device->Synth)
3394 DELETE_OBJ(device->Backend);
3395 al_free(device);
3396 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3397 return NULL;
3400 // Find a playback device to open
3401 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3403 DELETE_OBJ(device->Synth);
3404 DELETE_OBJ(device->Backend);
3405 al_free(device);
3406 alcSetError(NULL, err);
3407 return NULL;
3410 if(DefaultEffect.type != AL_EFFECT_NULL)
3412 device->DefaultSlot = (ALeffectslot*)device->_slot_mem;
3413 if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR)
3415 device->DefaultSlot = NULL;
3416 ERR("Failed to initialize the default effect slot\n");
3418 else if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR)
3420 ALeffectState *state = device->DefaultSlot->EffectState;
3421 device->DefaultSlot = NULL;
3422 DELETE_OBJ(state);
3423 ERR("Failed to initialize the default effect\n");
3428 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3429 do {
3430 device->next = head;
3431 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3434 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3435 return device;
3438 /* alcCloseDevice
3440 * Closes the given device.
3442 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
3444 ALCdevice *list, *origdev, *nextdev;
3445 ALCcontext *ctx;
3447 LockLists();
3448 list = ATOMIC_LOAD(&DeviceList);
3449 do {
3450 if(list == device)
3451 break;
3452 } while((list=list->next) != NULL);
3453 if(!list || list->Type == Capture)
3455 alcSetError(list, ALC_INVALID_DEVICE);
3456 UnlockLists();
3457 return ALC_FALSE;
3460 origdev = device;
3461 nextdev = device->next;
3462 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev))
3464 do {
3465 list = origdev;
3466 origdev = device;
3467 } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev));
3469 UnlockLists();
3471 ctx = ATOMIC_LOAD(&device->ContextList);
3472 while(ctx != NULL)
3474 ALCcontext *next = ctx->next;
3475 WARN("Releasing context %p\n", ctx);
3476 ReleaseContext(ctx, device);
3477 ctx = next;
3479 if((device->Flags&DEVICE_RUNNING))
3480 V0(device->Backend,stop)();
3481 device->Flags &= ~DEVICE_RUNNING;
3483 ALCdevice_DecRef(device);
3485 return ALC_TRUE;
3489 /************************************************
3490 * ALC capture functions
3491 ************************************************/
3492 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples)
3494 ALCdevice *device = NULL;
3495 ALCenum err;
3497 DO_INITCONFIG();
3499 if(!CaptureBackend.name)
3501 alcSetError(NULL, ALC_INVALID_VALUE);
3502 return NULL;
3505 if(samples <= 0)
3507 alcSetError(NULL, ALC_INVALID_VALUE);
3508 return NULL;
3511 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
3512 deviceName = NULL;
3514 device = al_calloc(16, sizeof(ALCdevice));
3515 if(!device)
3517 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3518 return NULL;
3521 //Validate device
3522 InitRef(&device->ref, 1);
3523 device->Connected = ALC_TRUE;
3524 device->Type = Capture;
3526 AL_STRING_INIT(device->DeviceName);
3527 device->DryBuffer = NULL;
3529 InitUIntMap(&device->BufferMap, ~0);
3530 InitUIntMap(&device->EffectMap, ~0);
3531 InitUIntMap(&device->FilterMap, ~0);
3532 InitUIntMap(&device->SfontMap, ~0);
3533 InitUIntMap(&device->PresetMap, ~0);
3534 InitUIntMap(&device->FontsoundMap, ~0);
3536 if(!CaptureBackend.getFactory)
3537 device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs,
3538 ALCbackend_Capture);
3539 else
3541 ALCbackendFactory *factory = CaptureBackend.getFactory();
3542 device->Backend = V(factory,createBackend)(device, ALCbackend_Capture);
3544 if(!device->Backend)
3546 al_free(device);
3547 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3548 return NULL;
3551 device->Flags |= DEVICE_FREQUENCY_REQUEST;
3552 device->Frequency = frequency;
3554 device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
3555 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
3557 al_free(device);
3558 alcSetError(NULL, ALC_INVALID_ENUM);
3559 return NULL;
3561 device->IsHeadphones = AL_FALSE;
3563 device->UpdateSize = samples;
3564 device->NumUpdates = 1;
3566 if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR)
3568 al_free(device);
3569 alcSetError(NULL, err);
3570 return NULL;
3574 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3575 do {
3576 device->next = head;
3577 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3580 TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName));
3581 return device;
3584 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
3586 ALCdevice *list, *next, *nextdev;
3588 LockLists();
3589 list = ATOMIC_LOAD(&DeviceList);
3590 do {
3591 if(list == device)
3592 break;
3593 } while((list=list->next) != NULL);
3594 if(!list || list->Type != Capture)
3596 alcSetError(list, ALC_INVALID_DEVICE);
3597 UnlockLists();
3598 return ALC_FALSE;
3601 next = device;
3602 nextdev = device->next;
3603 if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev))
3605 do {
3606 list = next;
3607 next = device;
3608 } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev));
3610 UnlockLists();
3612 ALCdevice_DecRef(device);
3614 return ALC_TRUE;
3617 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
3619 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3620 alcSetError(device, ALC_INVALID_DEVICE);
3621 else
3623 V0(device->Backend,lock)();
3624 if(device->Connected)
3626 if(!(device->Flags&DEVICE_RUNNING))
3627 V0(device->Backend,start)();
3628 device->Flags |= DEVICE_RUNNING;
3630 V0(device->Backend,unlock)();
3633 if(device) ALCdevice_DecRef(device);
3636 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
3638 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3639 alcSetError(device, ALC_INVALID_DEVICE);
3640 else
3642 V0(device->Backend,lock)();
3643 if((device->Flags&DEVICE_RUNNING))
3644 V0(device->Backend,stop)();
3645 device->Flags &= ~DEVICE_RUNNING;
3646 V0(device->Backend,unlock)();
3649 if(device) ALCdevice_DecRef(device);
3652 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3654 if(!(device=VerifyDevice(device)) || device->Type != Capture)
3655 alcSetError(device, ALC_INVALID_DEVICE);
3656 else
3658 ALCenum err = ALC_INVALID_VALUE;
3660 V0(device->Backend,lock)();
3661 if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
3662 err = V(device->Backend,captureSamples)(buffer, samples);
3663 V0(device->Backend,unlock)();
3665 if(err != ALC_NO_ERROR)
3666 alcSetError(device, err);
3668 if(device) ALCdevice_DecRef(device);
3672 /************************************************
3673 * ALC loopback functions
3674 ************************************************/
3676 /* alcLoopbackOpenDeviceSOFT
3678 * Open a loopback device, for manual rendering.
3680 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName)
3682 ALCbackendFactory *factory;
3683 ALCdevice *device;
3685 DO_INITCONFIG();
3687 /* Make sure the device name, if specified, is us. */
3688 if(deviceName && strcmp(deviceName, alcDefaultName) != 0)
3690 alcSetError(NULL, ALC_INVALID_VALUE);
3691 return NULL;
3694 device = al_calloc(16, sizeof(ALCdevice));
3695 if(!device)
3697 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3698 return NULL;
3701 //Validate device
3702 InitRef(&device->ref, 1);
3703 device->Connected = ALC_TRUE;
3704 device->Type = Loopback;
3705 ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
3707 device->Flags = 0;
3708 device->Bs2b = NULL;
3709 AL_STRING_INIT(device->DeviceName);
3710 device->DryBuffer = NULL;
3712 ATOMIC_INIT(&device->ContextList, NULL);
3714 device->ClockBase = 0;
3715 device->SamplesDone = 0;
3717 device->MaxNoOfSources = 256;
3718 device->AuxiliaryEffectSlotMax = 4;
3719 device->NumAuxSends = MAX_SENDS;
3721 InitUIntMap(&device->BufferMap, ~0);
3722 InitUIntMap(&device->EffectMap, ~0);
3723 InitUIntMap(&device->FilterMap, ~0);
3724 InitUIntMap(&device->SfontMap, ~0);
3725 InitUIntMap(&device->PresetMap, ~0);
3726 InitUIntMap(&device->FontsoundMap, ~0);
3728 factory = ALCloopbackFactory_getFactory();
3729 device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback);
3730 if(!device->Backend)
3732 al_free(device);
3733 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3734 return NULL;
3737 //Set output format
3738 device->NumUpdates = 0;
3739 device->UpdateSize = 0;
3741 device->Frequency = DEFAULT_OUTPUT_RATE;
3742 device->FmtChans = DevFmtChannelsDefault;
3743 device->FmtType = DevFmtTypeDefault;
3744 device->IsHeadphones = AL_FALSE;
3746 ConfigValueUInt(NULL, "sources", &device->MaxNoOfSources);
3747 if(device->MaxNoOfSources == 0) device->MaxNoOfSources = 256;
3749 ConfigValueUInt(NULL, "slots", &device->AuxiliaryEffectSlotMax);
3750 if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4;
3752 ConfigValueUInt(NULL, "sends", &device->NumAuxSends);
3753 if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS;
3755 device->NumStereoSources = 1;
3756 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
3758 device->Synth = SynthCreate(device);
3759 if(!device->Synth)
3761 DELETE_OBJ(device->Backend);
3762 al_free(device);
3763 alcSetError(NULL, ALC_OUT_OF_MEMORY);
3764 return NULL;
3767 // Open the "backend"
3768 V(device->Backend,open)("Loopback");
3771 ALCdevice *head = ATOMIC_LOAD(&DeviceList);
3772 do {
3773 device->next = head;
3774 } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device));
3777 TRACE("Created device %p\n", device);
3778 return device;
3781 /* alcIsRenderFormatSupportedSOFT
3783 * Determines if the loopback device supports the given format for rendering.
3785 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
3787 ALCboolean ret = ALC_FALSE;
3789 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3790 alcSetError(device, ALC_INVALID_DEVICE);
3791 else if(freq <= 0)
3792 alcSetError(device, ALC_INVALID_VALUE);
3793 else
3795 if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 &&
3796 IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 &&
3797 freq >= MIN_OUTPUT_RATE)
3798 ret = ALC_TRUE;
3800 if(device) ALCdevice_DecRef(device);
3802 return ret;
3805 /* alcRenderSamplesSOFT
3807 * Renders some samples into a buffer, using the format last set by the
3808 * attributes given to alcCreateContext.
3810 FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
3812 if(!(device=VerifyDevice(device)) || device->Type != Loopback)
3813 alcSetError(device, ALC_INVALID_DEVICE);
3814 else if(samples < 0 || (samples > 0 && buffer == NULL))
3815 alcSetError(device, ALC_INVALID_VALUE);
3816 else
3817 aluMixData(device, buffer, samples);
3818 if(device) ALCdevice_DecRef(device);
3822 /************************************************
3823 * ALC DSP pause/resume functions
3824 ************************************************/
3826 /* alcDevicePauseSOFT
3828 * Pause the DSP to stop audio processing.
3830 ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
3832 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3833 alcSetError(device, ALC_INVALID_DEVICE);
3834 else
3836 LockLists();
3837 if((device->Flags&DEVICE_RUNNING))
3838 V0(device->Backend,stop)();
3839 device->Flags &= ~DEVICE_RUNNING;
3840 device->Flags |= DEVICE_PAUSED;
3841 UnlockLists();
3843 if(device) ALCdevice_DecRef(device);
3846 /* alcDeviceResumeSOFT
3848 * Resume the DSP to restart audio processing.
3850 ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
3852 if(!(device=VerifyDevice(device)) || device->Type != Playback)
3853 alcSetError(device, ALC_INVALID_DEVICE);
3854 else
3856 LockLists();
3857 if((device->Flags&DEVICE_PAUSED))
3859 device->Flags &= ~DEVICE_PAUSED;
3860 if(ATOMIC_LOAD(&device->ContextList) != NULL)
3862 if(V0(device->Backend,start)() != ALC_FALSE)
3863 device->Flags |= DEVICE_RUNNING;
3864 else
3866 alcSetError(device, ALC_INVALID_DEVICE);
3867 V0(device->Backend,lock)();
3868 aluHandleDisconnect(device);
3869 V0(device->Backend,unlock)();
3873 UnlockLists();
3875 if(device) ALCdevice_DecRef(device);