Fix appveyor env vars
[dsound-openal.git] / dsound_private.h
blobf5e40ce811b93d842cf1ca40ef5eb65b6bf00fc8
1 /* DirectSound
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 /* Linux does not support better timing than 10ms */
23 #define DS_TIME_RES 2 /* Resolution of multimedia timer */
24 #define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */
25 /* Default refresh count, can be overridden */
26 #define FAKE_REFRESH_COUNT (1000/DS_TIME_DEL/2)
29 #include <stdio.h>
30 #include <math.h>
31 #include <dsound.h>
32 #include <mmdeviceapi.h>
33 #include <devpropdef.h>
35 #include "wingdi.h"
36 #include "mmreg.h"
38 #include "alc.h"
39 #include "al.h"
40 #include "alext.h"
42 #include "eax.h"
44 #ifndef AL_SOFT_map_buffer
45 #define AL_SOFT_map_buffer 1
46 typedef unsigned int ALbitfieldSOFT;
47 #define AL_MAP_READ_BIT_SOFT 0x00000001
48 #define AL_MAP_WRITE_BIT_SOFT 0x00000002
49 #define AL_MAP_PERSISTENT_BIT_SOFT 0x00000004
50 #define AL_PRESERVE_DATA_BIT_SOFT 0x00000008
51 typedef void (AL_APIENTRY*LPALBUFFERSTORAGESOFT)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags);
52 typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access);
53 typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer);
54 typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length);
55 #endif
58 #ifdef __GNUC__
59 #define LIKELY(x) __builtin_expect(!!(x), !0)
60 #define UNLIKELY(x) __builtin_expect(!!(x), !!0)
61 #else
62 #define LIKELY(x) (!!(x))
63 #define UNLIKELY(x) (!!(x))
64 #endif
67 extern int LogLevel;
68 extern FILE *LogFile;
70 #define DO_PRINT(a, ...) do { \
71 fprintf(LogFile, a, __VA_ARGS__); \
72 fflush(LogFile); \
73 } while(0)
75 #ifdef _MSC_VER
76 #define TRACE(fmt, ...) do { \
77 if(UNLIKELY(LogLevel >= 3)) \
78 DO_PRINT("%04x:trace:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
79 __FUNCTION__, __VA_ARGS__); \
80 } while(0)
81 #define WARN(fmt, ...) do { \
82 if(UNLIKELY(LogLevel >= 2)) \
83 DO_PRINT("%04x:warn:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
84 __FUNCTION__, __VA_ARGS__); \
85 } while(0)
86 #define FIXME(fmt, ...) do { \
87 if(UNLIKELY(LogLevel >= 1)) \
88 DO_PRINT("%04x:fixme:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
89 __FUNCTION__, __VA_ARGS__); \
90 } while(0)
91 #define ERR(fmt, ...) do { \
92 if(UNLIKELY(LogLevel >= 0)) \
93 DO_PRINT("%04x:err:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
94 __FUNCTION__, __VA_ARGS__); \
95 } while(0)
97 #else
99 #define TRACE(fmt, ...) do { \
100 if(UNLIKELY(LogLevel >= 3)) \
101 DO_PRINT("%04x:trace:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
102 __FUNCTION__, ## __VA_ARGS__); \
103 } while(0)
104 #define WARN(fmt, ...) do { \
105 if(UNLIKELY(LogLevel >= 2)) \
106 DO_PRINT("%04x:warn:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
107 __FUNCTION__, ## __VA_ARGS__); \
108 } while(0)
109 #define FIXME(fmt, ...) do { \
110 if(UNLIKELY(LogLevel >= 1)) \
111 DO_PRINT("%04x:fixme:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
112 __FUNCTION__, ## __VA_ARGS__); \
113 } while(0)
114 #define ERR(fmt, ...) do { \
115 if(UNLIKELY(LogLevel >= 0)) \
116 DO_PRINT("%04x:err:dsound:%s " fmt, (UINT)GetCurrentThreadId(), \
117 __FUNCTION__, ## __VA_ARGS__); \
118 } while(0)
119 #endif
121 const char *wine_dbg_sprintf( const char *format, ... );
122 const char *wine_dbgstr_wn( const WCHAR *str, int n );
123 const char *debugstr_guid( const GUID *id );
125 static inline const char *debugstr_w( const WCHAR *s ) { return wine_dbgstr_wn( s, -1 ); }
128 #ifndef U64
129 #if defined(_MSC_VER)
130 #define U64(x) (x##ui64)
131 #elif SIZEOF_LONG == 8
132 #define U64(x) (x##ul)
133 #else
134 #define U64(x) (x##ull)
135 #endif
136 #endif
138 /* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
139 * is *UNDEFINED* if the value is 0.
141 #ifdef __GNUC__
143 #if SIZEOF_LONG == 8
144 #define POPCNT64 __builtin_popcountl
145 #define CTZ64 __builtin_ctzl
146 #else
147 #define POPCNT64 __builtin_popcountll
148 #define CTZ64 __builtin_ctzll
149 #endif
151 #else
153 /* There be black magics here. The popcnt64 method is derived from
154 * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
156 static inline int fallback_popcnt64(DWORD64 v)
158 v = v - ((v >> 1) & U64(0x5555555555555555));
159 v = (v & U64(0x3333333333333333)) + ((v >> 2) & U64(0x3333333333333333));
160 v = (v + (v >> 4)) & U64(0x0f0f0f0f0f0f0f0f);
161 return (int)((v * U64(0x0101010101010101)) >> 56);
163 #define POPCNT64 fallback_popcnt64
165 #if defined(HAVE_BITSCANFORWARD64_INTRINSIC)
167 static inline int msvc64_ctz64(DWORD64 v)
169 unsigned long idx = 64;
170 _BitScanForward64(&idx, v);
171 return (int)idx;
173 #define CTZ64 msvc64_ctz64
175 #elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
177 static inline int msvc_ctz64(DWORD64 v)
179 unsigned long idx = 64;
180 if(!_BitScanForward(&idx, v&0xffffffff))
182 if(_BitScanForward(&idx, v>>32))
183 idx += 32;
185 return (int)idx;
187 #define CTZ64 msvc_ctz64
189 #else
191 static inline int fallback_ctz64(DWORD64 value)
193 return fallback_popcnt64(~value & (value - 1));
195 #define CTZ64 fallback_ctz64
196 #endif
197 #endif
200 /* All openal functions */
201 extern int openal_loaded;
202 extern LPALCCREATECONTEXT palcCreateContext;
203 extern LPALCMAKECONTEXTCURRENT palcMakeContextCurrent;
204 extern LPALCPROCESSCONTEXT palcProcessContext;
205 extern LPALCSUSPENDCONTEXT palcSuspendContext;
206 extern LPALCDESTROYCONTEXT palcDestroyContext;
207 extern LPALCGETCURRENTCONTEXT palcGetCurrentContext;
208 extern LPALCGETCONTEXTSDEVICE palcGetContextsDevice;
209 extern LPALCOPENDEVICE palcOpenDevice;
210 extern LPALCCLOSEDEVICE palcCloseDevice;
211 extern LPALCGETERROR palcGetError;
212 extern LPALCISEXTENSIONPRESENT palcIsExtensionPresent;
213 extern LPALCGETPROCADDRESS palcGetProcAddress;
214 extern LPALCGETENUMVALUE palcGetEnumValue;
215 extern LPALCGETSTRING palcGetString;
216 extern LPALCGETINTEGERV palcGetIntegerv;
217 extern LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice;
218 extern LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice;
219 extern LPALCCAPTURESTART palcCaptureStart;
220 extern LPALCCAPTURESTOP palcCaptureStop;
221 extern LPALCCAPTURESAMPLES palcCaptureSamples;
222 extern LPALENABLE palEnable;
223 extern LPALDISABLE palDisable;
224 extern LPALISENABLED palIsEnabled;
225 extern LPALGETSTRING palGetString;
226 extern LPALGETBOOLEANV palGetBooleanv;
227 extern LPALGETINTEGERV palGetIntegerv;
228 extern LPALGETFLOATV palGetFloatv;
229 extern LPALGETDOUBLEV palGetDoublev;
230 extern LPALGETBOOLEAN palGetBoolean;
231 extern LPALGETINTEGER palGetInteger;
232 extern LPALGETFLOAT palGetFloat;
233 extern LPALGETDOUBLE palGetDouble;
234 extern LPALGETERROR palGetError;
235 extern LPALISEXTENSIONPRESENT palIsExtensionPresent;
236 extern LPALGETPROCADDRESS palGetProcAddress;
237 extern LPALGETENUMVALUE palGetEnumValue;
238 extern LPALLISTENERF palListenerf;
239 extern LPALLISTENER3F palListener3f;
240 extern LPALLISTENERFV palListenerfv;
241 extern LPALLISTENERI palListeneri;
242 extern LPALLISTENER3I palListener3i;
243 extern LPALLISTENERIV palListeneriv;
244 extern LPALGETLISTENERF palGetListenerf;
245 extern LPALGETLISTENER3F palGetListener3f;
246 extern LPALGETLISTENERFV palGetListenerfv;
247 extern LPALGETLISTENERI palGetListeneri;
248 extern LPALGETLISTENER3I palGetListener3i;
249 extern LPALGETLISTENERIV palGetListeneriv;
250 extern LPALGENSOURCES palGenSources;
251 extern LPALDELETESOURCES palDeleteSources;
252 extern LPALISSOURCE palIsSource;
253 extern LPALSOURCEF palSourcef;
254 extern LPALSOURCE3F palSource3f;
255 extern LPALSOURCEFV palSourcefv;
256 extern LPALSOURCEI palSourcei;
257 extern LPALSOURCE3I palSource3i;
258 extern LPALSOURCEIV palSourceiv;
259 extern LPALGETSOURCEF palGetSourcef;
260 extern LPALGETSOURCE3F palGetSource3f;
261 extern LPALGETSOURCEFV palGetSourcefv;
262 extern LPALGETSOURCEI palGetSourcei;
263 extern LPALGETSOURCE3I palGetSource3i;
264 extern LPALGETSOURCEIV palGetSourceiv;
265 extern LPALSOURCEPLAYV palSourcePlayv;
266 extern LPALSOURCESTOPV palSourceStopv;
267 extern LPALSOURCEREWINDV palSourceRewindv;
268 extern LPALSOURCEPAUSEV palSourcePausev;
269 extern LPALSOURCEPLAY palSourcePlay;
270 extern LPALSOURCESTOP palSourceStop;
271 extern LPALSOURCEREWIND palSourceRewind;
272 extern LPALSOURCEPAUSE palSourcePause;
273 extern LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers;
274 extern LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers;
275 extern LPALGENBUFFERS palGenBuffers;
276 extern LPALDELETEBUFFERS palDeleteBuffers;
277 extern LPALISBUFFER palIsBuffer;
278 extern LPALBUFFERF palBufferf;
279 extern LPALBUFFER3F palBuffer3f;
280 extern LPALBUFFERFV palBufferfv;
281 extern LPALBUFFERI palBufferi;
282 extern LPALBUFFER3I palBuffer3i;
283 extern LPALBUFFERIV palBufferiv;
284 extern LPALGETBUFFERF palGetBufferf;
285 extern LPALGETBUFFER3F palGetBuffer3f;
286 extern LPALGETBUFFERFV palGetBufferfv;
287 extern LPALGETBUFFERI palGetBufferi;
288 extern LPALGETBUFFER3I palGetBuffer3i;
289 extern LPALGETBUFFERIV palGetBufferiv;
290 extern LPALBUFFERDATA palBufferData;
291 extern LPALDOPPLERFACTOR palDopplerFactor;
292 extern LPALDOPPLERVELOCITY palDopplerVelocity;
293 extern LPALDISTANCEMODEL palDistanceModel;
294 extern LPALSPEEDOFSOUND palSpeedOfSound;
296 #define alcCreateContext palcCreateContext
297 #define alcMakeContextCurrent palcMakeContextCurrent
298 #define alcProcessContext palcProcessContext
299 #define alcSuspendContext palcSuspendContext
300 #define alcDestroyContext palcDestroyContext
301 #define alcGetCurrentContext palcGetCurrentContext
302 #define alcGetContextsDevice palcGetContextsDevice
303 #define alcOpenDevice palcOpenDevice
304 #define alcCloseDevice palcCloseDevice
305 #define alcGetError palcGetError
306 #define alcIsExtensionPresent palcIsExtensionPresent
307 #define alcGetProcAddress palcGetProcAddress
308 #define alcGetEnumValue palcGetEnumValue
309 #define alcGetString palcGetString
310 #define alcGetIntegerv palcGetIntegerv
311 #define alcCaptureOpenDevice palcCaptureOpenDevice
312 #define alcCaptureCloseDevice palcCaptureCloseDevice
313 #define alcCaptureStart palcCaptureStart
314 #define alcCaptureStop palcCaptureStop
315 #define alcCaptureSamples palcCaptureSamples
316 #define alEnable palEnable
317 #define alDisable palDisable
318 #define alIsEnabled palIsEnabled
319 #define alGetString palGetString
320 #define alGetBooleanv palGetBooleanv
321 #define alGetIntegerv palGetIntegerv
322 #define alGetFloatv palGetFloatv
323 #define alGetDoublev palGetDoublev
324 #define alGetBoolean palGetBoolean
325 #define alGetInteger palGetInteger
326 #define alGetFloat palGetFloat
327 #define alGetDouble palGetDouble
328 #define alGetError palGetError
329 #define alIsExtensionPresent palIsExtensionPresent
330 #define alGetProcAddress palGetProcAddress
331 #define alGetEnumValue palGetEnumValue
332 #define alListenerf palListenerf
333 #define alListener3f palListener3f
334 #define alListenerfv palListenerfv
335 #define alListeneri palListeneri
336 #define alListener3i palListener3i
337 #define alListeneriv palListeneriv
338 #define alGetListenerf palGetListenerf
339 #define alGetListener3f palGetListener3f
340 #define alGetListenerfv palGetListenerfv
341 #define alGetListeneri palGetListeneri
342 #define alGetListener3i palGetListener3i
343 #define alGetListeneriv palGetListeneriv
344 #define alGenSources palGenSources
345 #define alDeleteSources palDeleteSources
346 #define alIsSource palIsSource
347 #define alSourcef palSourcef
348 #define alSource3f palSource3f
349 #define alSourcefv palSourcefv
350 #define alSourcei palSourcei
351 #define alSource3i palSource3i
352 #define alSourceiv palSourceiv
353 #define alGetSourcef palGetSourcef
354 #define alGetSource3f palGetSource3f
355 #define alGetSourcefv palGetSourcefv
356 #define alGetSourcei palGetSourcei
357 #define alGetSource3i palGetSource3i
358 #define alGetSourceiv palGetSourceiv
359 #define alSourcePlayv palSourcePlayv
360 #define alSourceStopv palSourceStopv
361 #define alSourceRewindv palSourceRewindv
362 #define alSourcePausev palSourcePausev
363 #define alSourcePlay palSourcePlay
364 #define alSourceStop palSourceStop
365 #define alSourceRewind palSourceRewind
366 #define alSourcePause palSourcePause
367 #define alSourceQueueBuffers palSourceQueueBuffers
368 #define alSourceUnqueueBuffers palSourceUnqueueBuffers
369 #define alGenBuffers palGenBuffers
370 #define alDeleteBuffers palDeleteBuffers
371 #define alIsBuffer palIsBuffer
372 #define alBufferf palBufferf
373 #define alBuffer3f palBuffer3f
374 #define alBufferfv palBufferfv
375 #define alBufferi palBufferi
376 #define alBuffer3i palBuffer3i
377 #define alBufferiv palBufferiv
378 #define alGetBufferf palGetBufferf
379 #define alGetBuffer3f palGetBuffer3f
380 #define alGetBufferfv palGetBufferfv
381 #define alGetBufferi palGetBufferi
382 #define alGetBuffer3i palGetBuffer3i
383 #define alGetBufferiv palGetBufferiv
384 #define alBufferData palBufferData
385 #define alDopplerFactor palDopplerFactor
386 #define alDopplerVelocity palDopplerVelocity
387 #define alDistanceModel palDistanceModel
388 #define alSpeedOfSound palSpeedOfSound
390 /* Extension functions. Technically device- or driver-specific, but as long as
391 * they're pulled from the NULL device it should be routed correctly.
393 extern LPALGENFILTERS palGenFilters;
394 extern LPALDELETEFILTERS palDeleteFilters;
395 extern LPALFILTERI palFilteri;
396 extern LPALFILTERF palFilterf;
397 extern LPALGENEFFECTS palGenEffects;
398 extern LPALDELETEEFFECTS palDeleteEffects;
399 extern LPALEFFECTI palEffecti;
400 extern LPALEFFECTF palEffectf;
401 extern LPALEFFECTFV palEffectfv;
402 extern LPALGENAUXILIARYEFFECTSLOTS palGenAuxiliaryEffectSlots;
403 extern LPALDELETEAUXILIARYEFFECTSLOTS palDeleteAuxiliaryEffectSlots;
404 extern LPALAUXILIARYEFFECTSLOTI palAuxiliaryEffectSloti;
405 extern LPALAUXILIARYEFFECTSLOTF palAuxiliaryEffectSlotf;
406 extern LPALDEFERUPDATESSOFT palDeferUpdatesSOFT;
407 extern LPALPROCESSUPDATESSOFT palProcessUpdatesSOFT;
408 extern LPALBUFFERSTORAGESOFT palBufferStorageSOFT;
409 extern LPALMAPBUFFERSOFT palMapBufferSOFT;
410 extern LPALUNMAPBUFFERSOFT palUnmapBufferSOFT;
411 extern LPALFLUSHMAPPEDBUFFERSOFT palFlushMappedBufferSOFT;
413 #define alGenFilters palGenFilters
414 #define alDeleteFilters palDeleteFilters
415 #define alFilteri palFilteri
416 #define alFilterf palFilterf
417 #define alGenEffects palGenEffects
418 #define alDeleteEffects palDeleteEffects
419 #define alEffecti palEffecti
420 #define alEffectf palEffectf
421 #define alEffectfv palEffectfv
422 #define alGenAuxiliaryEffectSlots palGenAuxiliaryEffectSlots
423 #define alDeleteAuxiliaryEffectSlots palDeleteAuxiliaryEffectSlots
424 #define alAuxiliaryEffectSloti palAuxiliaryEffectSloti
425 #define alAuxiliaryEffectSlotf palAuxiliaryEffectSlotf
426 #define alDeferUpdatesSOFT palDeferUpdatesSOFT
427 #define alProcessUpdatesSOFT palProcessUpdatesSOFT
428 #define alBufferStorageSOFT palBufferStorageSOFT
429 #define alMapBufferSOFT palMapBufferSOFT
430 #define alUnmapBufferSOFT palUnmapBufferSOFT
431 #define alFlushMappedBufferSOFT palFlushMappedBufferSOFT
434 #ifndef E_PROP_ID_UNSUPPORTED
435 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
436 #endif
438 /* OpenAL only allows for 1 single access to the device at the same time */
439 extern CRITICAL_SECTION openal_crst;
441 extern LPALCMAKECONTEXTCURRENT set_context;
442 extern LPALCGETCURRENTCONTEXT get_context;
443 extern BOOL local_contexts;
446 extern DWORD TlsThreadPtr;
447 extern void (*EnterALSection)(ALCcontext *ctx);
448 extern void (*LeaveALSection)(void);
451 typedef struct DSDevice DSDevice;
452 typedef struct DSPrimary DSPrimary;
453 typedef struct DSBuffer DSBuffer;
456 enum {
457 EXT_EFX,
458 EXT_FLOAT32,
459 EXT_MCFORMATS,
460 SOFT_DEFERRED_UPDATES,
461 SOFT_SOURCE_SPATIALIZE,
462 SOFTX_FILTER_GAIN_EX,
463 SOFTX_MAP_BUFFER,
465 MAX_EXTENSIONS
469 #define BITFIELD_ARRAY_SIZE(b) ((b+7) / 8)
470 #define BITFIELD_SET(arr, b) ((arr)[(b)>>3] |= 1<<((b)&7))
471 #define BITFIELD_TEST(arr, b) ((arr)[(b)>>3] & (1<<((b)&7)))
473 /* Maximum number of emulated hardware buffers. May be less depending on source
474 * availability.
476 #define MAX_HWBUFFERS 256
478 #define MAX_SOURCES 512
479 typedef struct SourceCollection {
480 DWORD maxhw_alloc, availhw_num;
481 DWORD maxsw_alloc, availsw_num;
482 /* "Hardware" sources start at 0, and "software" sources start at
483 * maxhw_alloc. Total sources is maxhw_alloc+maxsw_alloc.
485 ALuint ids[MAX_SOURCES];
486 } SourceCollection;
488 typedef struct DeviceShare {
489 LONG ref;
491 ALCdevice *device;
492 ALCcontext *ctx;
493 ALCint refresh;
494 ALCint num_sends;
496 ALboolean Exts[BITFIELD_ARRAY_SIZE(MAX_EXTENSIONS)];
498 CRITICAL_SECTION crst;
500 SourceCollection sources;
502 ALuint auxslot[EAX_MAX_FXSLOTS];
503 ALsizei num_slots;
505 HANDLE thread_hdl;
506 DWORD thread_id;
508 HANDLE queue_timer;
509 HANDLE timer_evt;
510 volatile LONG quit_now;
512 ALsizei nprimaries;
513 DSPrimary **primaries;
515 GUID guid;
516 DWORD speaker_config;
517 } DeviceShare;
519 #define HAS_EXTENSION(s, e) BITFIELD_TEST((s)->Exts, e)
522 typedef struct DSData {
523 LONG ref;
525 DSPrimary *primary;
527 /* Lock was called and unlock isn't? */
528 LONG locked;
530 WAVEFORMATEXTENSIBLE format;
532 ALsizei buf_size;
533 ALenum buf_format;
534 DWORD dsbflags;
535 BYTE *data;
536 ALuint bid;
537 } DSData;
538 /* Amount of buffers that have to be queued when
539 * bufferdatastatic and buffersubdata are not available */
540 #define QBUFFERS 4
542 union BufferParamFlags {
543 LONG flags;
544 struct {
545 BOOL pos : 1;
546 BOOL vel : 1;
547 BOOL cone_angles : 1;
548 BOOL cone_orient : 1;
549 BOOL cone_outsidevolume : 1;
550 BOOL min_distance : 1;
551 BOOL max_distance : 1;
552 BOOL mode : 1;
554 BOOL dry_filter : 1;
555 BOOL send_filters : 1;
556 BOOL doppler : 1;
557 BOOL rolloff : 1;
558 BOOL room_rolloff : 1;
559 BOOL cone_outsidevolumehf : 1;
560 BOOL air_absorb : 1;
561 BOOL flags : 1;
562 } bit;
565 enum {
566 FXSLOT_TARGET_0,
567 FXSLOT_TARGET_1,
568 FXSLOT_TARGET_2,
569 FXSLOT_TARGET_3,
570 FXSLOT_TARGET_PRIMARY,
571 FXSLOT_TARGET_NULL,
574 struct Send {
575 long lSend;
576 long lSendHF;
577 long lOcclusion;
578 float flOcclusionLFRatio;
579 float flOcclusionRoomRatio;
580 float flOcclusionDirectRatio;
581 long lExclusion;
582 float flExclusionLFRatio;
585 struct DSBuffer {
586 IDirectSoundBuffer8 IDirectSoundBuffer8_iface;
587 IDirectSound3DBuffer IDirectSound3DBuffer_iface;
588 IDirectSoundNotify IDirectSoundNotify_iface;
589 IKsPropertySet IKsPropertySet_iface;
591 LONG ref, ds3d_ref, not_ref, prop_ref;
592 LONG all_ref;
594 DeviceShare *share;
595 DSPrimary *primary;
597 /* From the primary */
598 ALCcontext *ctx;
600 DSData *buffer;
601 ALuint source;
603 ALsizei segsize;
604 ALsizei data_offset;
605 ALsizei queue_base;
606 ALsizei curidx;
607 ALuint stream_bids[QBUFFERS];
609 BOOL init_done : 1;
610 BOOL isplaying : 1;
611 BOOL islooping : 1;
612 BOOL bufferlost : 1;
614 /* Must be 0 (deferred, not yet placed), DSBSTATUS_LOCSOFTWARE, or
615 * DSBSTATUS_LOCHARDWARE.
617 DWORD loc_status;
619 struct {
620 LONG vol, pan;
621 DWORD frequency;
622 DS3DBUFFER ds3d;
623 EAXSOURCEPROPERTIES eax;
624 /* See FXSLOT_TARGET enums */
625 DWORD fxslot_targets[EAX_MAX_ACTIVE_FXSLOTS];
626 struct Send send[EAX_MAX_FXSLOTS];
627 float eax1_reverbmix; /* Mirrored by eax.lRoom. */
628 } current;
629 struct {
630 DS3DBUFFER ds3d;
631 EAXSOURCEPROPERTIES eax;
632 DWORD fxslot_targets[EAX_MAX_ACTIVE_FXSLOTS];
633 struct Send send[EAX_MAX_FXSLOTS];
634 float eax1_reverbmix;
635 } deferred;
636 union BufferParamFlags dirty;
638 ALfloat filter_mBLimit;
639 ALuint filter[1+EAX_MAX_FXSLOTS];
641 DWORD nnotify, lastpos;
642 DSBPOSITIONNOTIFY *notify;
646 struct DSBufferGroup {
647 DWORD64 FreeBuffers;
648 DSBuffer *Buffers;
652 enum {
653 FXSLOT_EFFECT_REVERB,
654 FXSLOT_EFFECT_CHORUS,
656 FXSLOT_EFFECT_NULL,
659 struct FXSlot {
660 /* See FXSLOT_EFFECT enums */
661 DWORD effect_type;
662 union {
663 EAXREVERBPROPERTIES reverb;
664 EAXCHORUSPROPERTIES chorus;
665 } fx;
666 EAXFXSLOTPROPERTIES props;
669 union PrimaryParamFlags {
670 LONG flags;
671 struct {
672 LONG pos : 1;
673 LONG vel : 1;
674 LONG orientation : 1;
675 LONG distancefactor : 1;
676 LONG rollofffactor : 1;
677 LONG dopplerfactor : 1;
679 LONG prim_slotid : 1;
680 LONG distancefactor2 : 1;
681 LONG air_absorbhf : 1;
682 LONG hfreference : 1;
684 /* Can't use a proper array for the fxslots here since this is a
685 * bitfield, and each slot only needs 4 bits. So make a sub-bitfield
686 * with macros to access it.
688 #define FXSLOT_EFFECT_BIT 0
689 #define FXSLOT_VOL_BIT 1
690 #define FXSLOT_LOCK_BIT 2
691 #define FXSLOT_FLAGS_BIT 3
692 #define FXSLOT_NUM_BITS 4
694 #define FXSLOT_IS_DIRTY(_flags, _idx, _bit) \
695 (((_flags).fxslots & (1 << ((_idx)*FXSLOT_NUM_BITS + (_bit)))) != 0)
696 #define FXSLOT_SET_DIRTY(_flags, _idx, _bit) \
697 ((_flags).fxslots |= (1 << ((_idx)*FXSLOT_NUM_BITS + (_bit))))
699 LONG fxslots : (FXSLOT_NUM_BITS*EAX_MAX_FXSLOTS);
700 } bit;
703 struct DSPrimary {
704 IDirectSoundBuffer IDirectSoundBuffer_iface;
705 IDirectSound3DListener IDirectSound3DListener_iface;
706 IKsPropertySet IKsPropertySet_iface;
708 LONG ref, ds3d_ref, prop_ref;
709 IDirectSoundBuffer *write_emu;
710 DSDevice *parent;
712 DeviceShare *share;
713 /* Taken from the share */
714 ALCcontext *ctx;
715 ALCint refresh;
716 ALuint auxslot[EAX_MAX_FXSLOTS];
718 DWORD buf_size;
719 BOOL stopped;
720 DWORD flags;
721 WAVEFORMATEXTENSIBLE format;
723 DSBuffer **notifies;
724 DWORD nnotifies, sizenotifies;
726 ALfloat filter_mBLimit;
728 ALuint effect[EAX_MAX_FXSLOTS];
729 ALint primary_idx;
730 LONG eax_error;
732 struct {
733 DS3DLISTENER ds3d;
734 EAXCONTEXTPROPERTIES ctx;
735 struct FXSlot fxslot[EAX_MAX_FXSLOTS];
736 float eax1_volume; /* Mirrored by fxslot[0].fx.reverb.lRoom. */
737 float eax1_dampening; /* Not used. */
738 } current;
739 struct {
740 DS3DLISTENER ds3d;
741 EAXCONTEXTPROPERTIES ctx;
742 struct FXSlot fxslot[EAX_MAX_FXSLOTS];
743 float eax1_volume;
744 float eax1_dampening;
745 } deferred;
746 union PrimaryParamFlags dirty;
748 DWORD NumBufferGroups;
749 struct DSBufferGroup *BufferGroups;
753 /* Device implementation */
754 struct DSDevice {
755 IDirectSound8 IDirectSound8_iface;
756 IDirectSound IDirectSound_iface;
757 IUnknown IUnknown_iface;
759 LONG ref, unkref, dsref;
760 BOOL is_8;
762 DeviceShare *share;
764 /* Taken from the share */
765 ALCdevice *device;
767 DSPrimary primary;
769 DWORD prio_level;
773 DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
775 DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x00, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
777 DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x00, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
779 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
780 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
782 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
784 DEFINE_GUID(DSPROPSETID_VoiceManager, 0x62a69bae, 0xdf9d, 0x11d1, 0x99, 0xa6, 0x00, 0xc0, 0x4f, 0xc9, 0x9d, 0x46);
785 DEFINE_GUID(DSPROPSETID_ZOOMFX_BufferProperties, 0xcd5368e0, 0x3450, 0x11d3, 0x8b, 0x6e, 0x00, 0x10, 0x5a, 0x9b, 0x7b, 0xbc);
786 DEFINE_GUID(DSPROPSETID_I3DL2_ListenerProperties, 0xda0f0520, 0x300a, 0x11d3, 0x8a, 0x2b, 0x00, 0x60, 0x97, 0x0d, 0xb0, 0x11);
787 DEFINE_GUID(DSPROPSETID_I3DL2_BufferProperties, 0xda0f0521, 0x300a, 0x11d3, 0x8a, 0x2b, 0x00, 0x60, 0x97, 0x0d, 0xb0, 0x11);
790 HRESULT DSPrimary_PreInit(DSPrimary *prim, DSDevice *parent);
791 void DSPrimary_Clear(DSPrimary *prim);
792 void DSPrimary_triggernots(DSPrimary *prim);
793 void DSPrimary_streamfeeder(DSPrimary *prim, BYTE *scratch_mem/*2K non-permanent memory*/);
794 HRESULT WINAPI DSPrimary_Initialize(IDirectSoundBuffer *iface, IDirectSound *ds, const DSBUFFERDESC *desc);
795 HRESULT WINAPI DSPrimary3D_CommitDeferredSettings(IDirectSound3DListener *iface);
797 HRESULT DSBuffer_Create(DSBuffer **ppv, DSPrimary *parent, IDirectSoundBuffer *orig);
798 void DSBuffer_Destroy(DSBuffer *buf);
799 HRESULT DSBuffer_GetInterface(DSBuffer *buf, REFIID riid, void **ppv);
800 void DSBuffer_SetParams(DSBuffer *buffer, const DS3DBUFFER *params, LONG flags);
801 HRESULT WINAPI DSBuffer_GetCurrentPosition(IDirectSoundBuffer8 *iface, DWORD *playpos, DWORD *curpos);
802 HRESULT WINAPI DSBuffer_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status);
803 HRESULT WINAPI DSBuffer_Initialize(IDirectSoundBuffer8 *iface, IDirectSound *ds, const DSBUFFERDESC *desc);
805 HRESULT EAX1_Query(DSPrimary *prim, DWORD propid, ULONG *pTypeSupport);
806 HRESULT EAX1_Set(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
807 HRESULT EAX1_Get(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
808 HRESULT EAX1Buffer_Query(DSBuffer *buf, DWORD propid, ULONG *pTypeSupport);
809 HRESULT EAX1Buffer_Set(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
810 HRESULT EAX1Buffer_Get(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
812 HRESULT EAX2_Query(DSPrimary *prim, DWORD propid, ULONG *pTypeSupport);
813 HRESULT EAX2_Set(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
814 HRESULT EAX2_Get(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
815 HRESULT EAX2Buffer_Query(DSBuffer *buf, DWORD propid, ULONG *pTypeSupport);
816 HRESULT EAX2Buffer_Set(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
817 HRESULT EAX2Buffer_Get(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
819 HRESULT EAX3_Query(DSPrimary *prim, DWORD propid, ULONG *pTypeSupport);
820 HRESULT EAX3_Set(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
821 HRESULT EAX3_Get(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
822 HRESULT EAX3Buffer_Query(DSBuffer *buf, DWORD propid, ULONG *pTypeSupport);
823 HRESULT EAX3Buffer_Set(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
824 HRESULT EAX3Buffer_Get(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
826 HRESULT EAX4Context_Query(DSPrimary *prim, DWORD propid, ULONG *pTypeSupport);
827 HRESULT EAX4Context_Set(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
828 HRESULT EAX4Context_Get(DSPrimary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
830 HRESULT EAX4Slot_Query(DSPrimary *prim, LONG idx, DWORD propid, ULONG *pTypeSupport);
831 HRESULT EAX4Slot_Set(DSPrimary *prim, LONG idx, DWORD propid, void *pPropData, ULONG cbPropData);
832 HRESULT EAX4Slot_Get(DSPrimary *prim, LONG idx, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
834 HRESULT EAX4Source_Query(DSBuffer *buf, DWORD propid, ULONG *pTypeSupport);
835 HRESULT EAX4Source_Set(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
836 HRESULT EAX4Source_Get(DSBuffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
838 HRESULT EAXReverb_Set(DSPrimary *prim, LONG idx, DWORD propid, void *pPropData, ULONG cbPropData);
839 HRESULT EAXReverb_Get(DSPrimary *prim, DWORD idx, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
841 HRESULT EAXChorus_Set(DSPrimary *prim, LONG idx, DWORD propid, void *pPropData, ULONG cbPropData);
842 HRESULT EAXChorus_Get(DSPrimary *prim, DWORD idx, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
844 static inline LONG gain_to_mB(float gain)
846 return (gain > 1e-5f) ? (LONG)(log10f(gain) * 2000.0f) : -10000l;
848 static inline float mB_to_gain(float millibels)
850 return (millibels > -10000.0f) ? powf(10.0f, millibels/2000.0f) : 0.0f;
853 static inline LONG clampI(LONG val, LONG minval, LONG maxval)
855 if(val >= maxval) return maxval;
856 if(val <= minval) return minval;
857 return val;
859 static inline ULONG clampU(ULONG val, ULONG minval, ULONG maxval)
861 if(val >= maxval) return maxval;
862 if(val <= minval) return minval;
863 return val;
865 static inline FLOAT clampF(FLOAT val, FLOAT minval, FLOAT maxval)
867 if(val >= maxval) return maxval;
868 if(val <= minval) return minval;
869 return val;
872 static inline LONG minI(LONG a, LONG b)
873 { return (a < b) ? a : b; }
874 static inline float minF(float a, float b)
875 { return (a < b) ? a : b; }
877 static inline float maxF(float a, float b)
878 { return (a > b) ? a : b; }
881 #define checkALError() do { \
882 ALenum err = alGetError(); \
883 if(err != AL_NO_ERROR) \
884 ERR(">>>>>>>>>>>> Received AL error %#x on context %p, %s:%u\n", \
885 err, get_context(), __FUNCTION__, __LINE__); \
886 } while (0)
888 #define checkALCError(dev) do { \
889 ALenum err = alcGetError(dev); \
890 if(err != ALC_NO_ERROR) \
891 ERR(">>>>>>>>>>>> Received ALC error %#x on device %p, %s:%u\n", \
892 err, dev, __FUNCTION__, __LINE__); \
893 } while(0)
896 #define setALContext(actx) EnterALSection(actx)
897 #define popALContext() LeaveALSection()
900 HRESULT DSOUND_Create(REFIID riid, void **ppDS);
901 HRESULT DSOUND_Create8(REFIID riid, void **ppDS);
902 HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppDSFD);
903 HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **piks);
904 HRESULT DSOUND_CaptureCreate(REFIID riid, void **ppDSC);
905 HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppDSC);
907 typedef BOOL (CALLBACK *PRVTENUMCALLBACK)(EDataFlow flow, LPGUID guid, LPCWSTR descW, LPCWSTR modW, LPVOID data);
908 HRESULT enumerate_mmdevices(EDataFlow flow, PRVTENUMCALLBACK cb, void *user);
909 HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device);
911 extern const WCHAR aldriver_name[];
913 #ifndef DECLSPEC_EXPORT
914 #ifdef _WIN32
915 #define DECLSPEC_EXPORT __declspec(dllexport)
916 #else
917 #define DECLSPEC_EXPORT
918 #endif
919 #endif
921 HRESULT WINAPI DSOAL_GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest);