Attempt to improve handling of EAX1 volume settings
[dsound-openal.git] / dsound_private.h
blobbf88eb4a28cdd1a3f8945aa57359bf38e24d67df
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
199 #ifdef __GNUC__
200 #define LIKELY(x) __builtin_expect(!!(x), !0)
201 #define UNLIKELY(x) __builtin_expect(!!(x), !!0)
202 #else
203 #define LIKELY(x) (x)
204 #define UNLIKELY(x) (x)
205 #endif
208 /* All openal functions */
209 extern int openal_loaded;
210 extern LPALCCREATECONTEXT palcCreateContext;
211 extern LPALCMAKECONTEXTCURRENT palcMakeContextCurrent;
212 extern LPALCPROCESSCONTEXT palcProcessContext;
213 extern LPALCSUSPENDCONTEXT palcSuspendContext;
214 extern LPALCDESTROYCONTEXT palcDestroyContext;
215 extern LPALCGETCURRENTCONTEXT palcGetCurrentContext;
216 extern LPALCGETCONTEXTSDEVICE palcGetContextsDevice;
217 extern LPALCOPENDEVICE palcOpenDevice;
218 extern LPALCCLOSEDEVICE palcCloseDevice;
219 extern LPALCGETERROR palcGetError;
220 extern LPALCISEXTENSIONPRESENT palcIsExtensionPresent;
221 extern LPALCGETPROCADDRESS palcGetProcAddress;
222 extern LPALCGETENUMVALUE palcGetEnumValue;
223 extern LPALCGETSTRING palcGetString;
224 extern LPALCGETINTEGERV palcGetIntegerv;
225 extern LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice;
226 extern LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice;
227 extern LPALCCAPTURESTART palcCaptureStart;
228 extern LPALCCAPTURESTOP palcCaptureStop;
229 extern LPALCCAPTURESAMPLES palcCaptureSamples;
230 extern LPALENABLE palEnable;
231 extern LPALDISABLE palDisable;
232 extern LPALISENABLED palIsEnabled;
233 extern LPALGETSTRING palGetString;
234 extern LPALGETBOOLEANV palGetBooleanv;
235 extern LPALGETINTEGERV palGetIntegerv;
236 extern LPALGETFLOATV palGetFloatv;
237 extern LPALGETDOUBLEV palGetDoublev;
238 extern LPALGETBOOLEAN palGetBoolean;
239 extern LPALGETINTEGER palGetInteger;
240 extern LPALGETFLOAT palGetFloat;
241 extern LPALGETDOUBLE palGetDouble;
242 extern LPALGETERROR palGetError;
243 extern LPALISEXTENSIONPRESENT palIsExtensionPresent;
244 extern LPALGETPROCADDRESS palGetProcAddress;
245 extern LPALGETENUMVALUE palGetEnumValue;
246 extern LPALLISTENERF palListenerf;
247 extern LPALLISTENER3F palListener3f;
248 extern LPALLISTENERFV palListenerfv;
249 extern LPALLISTENERI palListeneri;
250 extern LPALLISTENER3I palListener3i;
251 extern LPALLISTENERIV palListeneriv;
252 extern LPALGETLISTENERF palGetListenerf;
253 extern LPALGETLISTENER3F palGetListener3f;
254 extern LPALGETLISTENERFV palGetListenerfv;
255 extern LPALGETLISTENERI palGetListeneri;
256 extern LPALGETLISTENER3I palGetListener3i;
257 extern LPALGETLISTENERIV palGetListeneriv;
258 extern LPALGENSOURCES palGenSources;
259 extern LPALDELETESOURCES palDeleteSources;
260 extern LPALISSOURCE palIsSource;
261 extern LPALSOURCEF palSourcef;
262 extern LPALSOURCE3F palSource3f;
263 extern LPALSOURCEFV palSourcefv;
264 extern LPALSOURCEI palSourcei;
265 extern LPALSOURCE3I palSource3i;
266 extern LPALSOURCEIV palSourceiv;
267 extern LPALGETSOURCEF palGetSourcef;
268 extern LPALGETSOURCE3F palGetSource3f;
269 extern LPALGETSOURCEFV palGetSourcefv;
270 extern LPALGETSOURCEI palGetSourcei;
271 extern LPALGETSOURCE3I palGetSource3i;
272 extern LPALGETSOURCEIV palGetSourceiv;
273 extern LPALSOURCEPLAYV palSourcePlayv;
274 extern LPALSOURCESTOPV palSourceStopv;
275 extern LPALSOURCEREWINDV palSourceRewindv;
276 extern LPALSOURCEPAUSEV palSourcePausev;
277 extern LPALSOURCEPLAY palSourcePlay;
278 extern LPALSOURCESTOP palSourceStop;
279 extern LPALSOURCEREWIND palSourceRewind;
280 extern LPALSOURCEPAUSE palSourcePause;
281 extern LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers;
282 extern LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers;
283 extern LPALGENBUFFERS palGenBuffers;
284 extern LPALDELETEBUFFERS palDeleteBuffers;
285 extern LPALISBUFFER palIsBuffer;
286 extern LPALBUFFERF palBufferf;
287 extern LPALBUFFER3F palBuffer3f;
288 extern LPALBUFFERFV palBufferfv;
289 extern LPALBUFFERI palBufferi;
290 extern LPALBUFFER3I palBuffer3i;
291 extern LPALBUFFERIV palBufferiv;
292 extern LPALGETBUFFERF palGetBufferf;
293 extern LPALGETBUFFER3F palGetBuffer3f;
294 extern LPALGETBUFFERFV palGetBufferfv;
295 extern LPALGETBUFFERI palGetBufferi;
296 extern LPALGETBUFFER3I palGetBuffer3i;
297 extern LPALGETBUFFERIV palGetBufferiv;
298 extern LPALBUFFERDATA palBufferData;
299 extern LPALDOPPLERFACTOR palDopplerFactor;
300 extern LPALDOPPLERVELOCITY palDopplerVelocity;
301 extern LPALDISTANCEMODEL palDistanceModel;
302 extern LPALSPEEDOFSOUND palSpeedOfSound;
304 #define alcCreateContext palcCreateContext
305 #define alcMakeContextCurrent palcMakeContextCurrent
306 #define alcProcessContext palcProcessContext
307 #define alcSuspendContext palcSuspendContext
308 #define alcDestroyContext palcDestroyContext
309 #define alcGetCurrentContext palcGetCurrentContext
310 #define alcGetContextsDevice palcGetContextsDevice
311 #define alcOpenDevice palcOpenDevice
312 #define alcCloseDevice palcCloseDevice
313 #define alcGetError palcGetError
314 #define alcIsExtensionPresent palcIsExtensionPresent
315 #define alcGetProcAddress palcGetProcAddress
316 #define alcGetEnumValue palcGetEnumValue
317 #define alcGetString palcGetString
318 #define alcGetIntegerv palcGetIntegerv
319 #define alcCaptureOpenDevice palcCaptureOpenDevice
320 #define alcCaptureCloseDevice palcCaptureCloseDevice
321 #define alcCaptureStart palcCaptureStart
322 #define alcCaptureStop palcCaptureStop
323 #define alcCaptureSamples palcCaptureSamples
324 #define alEnable palEnable
325 #define alDisable palDisable
326 #define alIsEnabled palIsEnabled
327 #define alGetString palGetString
328 #define alGetBooleanv palGetBooleanv
329 #define alGetIntegerv palGetIntegerv
330 #define alGetFloatv palGetFloatv
331 #define alGetDoublev palGetDoublev
332 #define alGetBoolean palGetBoolean
333 #define alGetInteger palGetInteger
334 #define alGetFloat palGetFloat
335 #define alGetDouble palGetDouble
336 #define alGetError palGetError
337 #define alIsExtensionPresent palIsExtensionPresent
338 #define alGetProcAddress palGetProcAddress
339 #define alGetEnumValue palGetEnumValue
340 #define alListenerf palListenerf
341 #define alListener3f palListener3f
342 #define alListenerfv palListenerfv
343 #define alListeneri palListeneri
344 #define alListener3i palListener3i
345 #define alListeneriv palListeneriv
346 #define alGetListenerf palGetListenerf
347 #define alGetListener3f palGetListener3f
348 #define alGetListenerfv palGetListenerfv
349 #define alGetListeneri palGetListeneri
350 #define alGetListener3i palGetListener3i
351 #define alGetListeneriv palGetListeneriv
352 #define alGenSources palGenSources
353 #define alDeleteSources palDeleteSources
354 #define alIsSource palIsSource
355 #define alSourcef palSourcef
356 #define alSource3f palSource3f
357 #define alSourcefv palSourcefv
358 #define alSourcei palSourcei
359 #define alSource3i palSource3i
360 #define alSourceiv palSourceiv
361 #define alGetSourcef palGetSourcef
362 #define alGetSource3f palGetSource3f
363 #define alGetSourcefv palGetSourcefv
364 #define alGetSourcei palGetSourcei
365 #define alGetSource3i palGetSource3i
366 #define alGetSourceiv palGetSourceiv
367 #define alSourcePlayv palSourcePlayv
368 #define alSourceStopv palSourceStopv
369 #define alSourceRewindv palSourceRewindv
370 #define alSourcePausev palSourcePausev
371 #define alSourcePlay palSourcePlay
372 #define alSourceStop palSourceStop
373 #define alSourceRewind palSourceRewind
374 #define alSourcePause palSourcePause
375 #define alSourceQueueBuffers palSourceQueueBuffers
376 #define alSourceUnqueueBuffers palSourceUnqueueBuffers
377 #define alGenBuffers palGenBuffers
378 #define alDeleteBuffers palDeleteBuffers
379 #define alIsBuffer palIsBuffer
380 #define alBufferf palBufferf
381 #define alBuffer3f palBuffer3f
382 #define alBufferfv palBufferfv
383 #define alBufferi palBufferi
384 #define alBuffer3i palBuffer3i
385 #define alBufferiv palBufferiv
386 #define alGetBufferf palGetBufferf
387 #define alGetBuffer3f palGetBuffer3f
388 #define alGetBufferfv palGetBufferfv
389 #define alGetBufferi palGetBufferi
390 #define alGetBuffer3i palGetBuffer3i
391 #define alGetBufferiv palGetBufferiv
392 #define alBufferData palBufferData
393 #define alDopplerFactor palDopplerFactor
394 #define alDopplerVelocity palDopplerVelocity
395 #define alDistanceModel palDistanceModel
396 #define alSpeedOfSound palSpeedOfSound
398 /* Extension functions. Technically device- or driver-specific, but as long as
399 * they're pulled from the NULL device it should be routed correctly.
401 extern LPALGENFILTERS palGenFilters;
402 extern LPALDELETEFILTERS palDeleteFilters;
403 extern LPALFILTERI palFilteri;
404 extern LPALFILTERF palFilterf;
405 extern LPALGENEFFECTS palGenEffects;
406 extern LPALDELETEEFFECTS palDeleteEffects;
407 extern LPALEFFECTI palEffecti;
408 extern LPALEFFECTF palEffectf;
409 extern LPALGENAUXILIARYEFFECTSLOTS palGenAuxiliaryEffectSlots;
410 extern LPALDELETEAUXILIARYEFFECTSLOTS palDeleteAuxiliaryEffectSlots;
411 extern LPALAUXILIARYEFFECTSLOTI palAuxiliaryEffectSloti;
412 extern LPALDEFERUPDATESSOFT palDeferUpdatesSOFT;
413 extern LPALPROCESSUPDATESSOFT palProcessUpdatesSOFT;
414 extern LPALBUFFERSTORAGESOFT palBufferStorageSOFT;
415 extern LPALMAPBUFFERSOFT palMapBufferSOFT;
416 extern LPALUNMAPBUFFERSOFT palUnmapBufferSOFT;
417 extern LPALFLUSHMAPPEDBUFFERSOFT palFlushMappedBufferSOFT;
419 #define alGenFilters palGenFilters
420 #define alDeleteFilters palDeleteFilters
421 #define alFilteri palFilteri
422 #define alFilterf palFilterf
423 #define alGenEffects palGenEffects
424 #define alDeleteEffects palDeleteEffects
425 #define alEffecti palEffecti
426 #define alEffectf palEffectf
427 #define alGenAuxiliaryEffectSlots palGenAuxiliaryEffectSlots
428 #define alDeleteAuxiliaryEffectSlots palDeleteAuxiliaryEffectSlots
429 #define alAuxiliaryEffectSloti palAuxiliaryEffectSloti
430 #define alDeferUpdatesSOFT palDeferUpdatesSOFT
431 #define alProcessUpdatesSOFT palProcessUpdatesSOFT
432 #define alBufferStorageSOFT palBufferStorageSOFT
433 #define alMapBufferSOFT palMapBufferSOFT
434 #define alUnmapBufferSOFT palUnmapBufferSOFT
435 #define alFlushMappedBufferSOFT palFlushMappedBufferSOFT
438 #ifndef E_PROP_ID_UNSUPPORTED
439 #define E_PROP_ID_UNSUPPORTED ((HRESULT)0x80070490)
440 #endif
442 /* OpenAL only allows for 1 single access to the device at the same time */
443 extern CRITICAL_SECTION openal_crst;
445 extern LPALCMAKECONTEXTCURRENT set_context;
446 extern LPALCGETCURRENTCONTEXT get_context;
447 extern BOOL local_contexts;
450 extern DWORD TlsThreadPtr;
451 extern void (*EnterALSection)(ALCcontext *ctx);
452 extern void (*LeaveALSection)(void);
455 typedef struct DS8Impl DS8Impl;
456 typedef struct DS8Primary DS8Primary;
457 typedef struct DS8Buffer DS8Buffer;
460 enum {
461 EXT_EFX,
462 EXT_FLOAT32,
463 EXT_MCFORMATS,
464 SOFT_DEFERRED_UPDATES,
465 SOFT_SOURCE_SPATIALIZE,
466 SOFTX_MAP_BUFFER,
468 MAX_EXTENSIONS
472 #define BITFIELD_ARRAY_SIZE(b) ((b+7) / 8)
473 #define BITFIELD_SET(arr, b) ((arr)[(b)>>3] |= 1<<((b)&7))
474 #define BITFIELD_TEST(arr, b) ((arr)[(b)>>3] & (1<<((b)&7)))
477 #define MAX_SOURCES 256
478 typedef struct SourceCollection {
479 DWORD max_alloc, avail_num;
480 ALuint ids[MAX_SOURCES];
481 } SourceCollection;
483 typedef struct DeviceShare {
484 LONG ref;
486 ALCdevice *device;
487 ALCcontext *ctx;
488 ALCint refresh;
490 ALboolean Exts[BITFIELD_ARRAY_SIZE(MAX_EXTENSIONS)];
492 CRITICAL_SECTION crst;
494 SourceCollection sources;
496 ALuint auxslot;
498 HANDLE thread_hdl;
499 DWORD thread_id;
501 HANDLE queue_timer;
502 HANDLE timer_evt;
503 volatile LONG quit_now;
505 ALsizei nprimaries;
506 DS8Primary **primaries;
508 GUID guid;
509 DWORD speaker_config;
510 } DeviceShare;
513 typedef struct DS8Data {
514 LONG ref;
516 DS8Primary *primary;
518 /* Lock was called and unlock isn't? */
519 LONG locked;
521 WAVEFORMATEXTENSIBLE format;
523 ALsizei buf_size;
524 ALenum buf_format;
525 DWORD dsbflags;
526 BYTE *data;
527 ALuint bid;
528 } DS8Data;
529 /* Amount of buffers that have to be queued when
530 * bufferdatastatic and buffersubdata are not available */
531 #define QBUFFERS 4
533 union BufferParamFlags {
534 LONG flags;
535 struct {
536 BOOL pos : 1;
537 BOOL vel : 1;
538 BOOL cone_angles : 1;
539 BOOL cone_orient : 1;
540 BOOL cone_outsidevolume : 1;
541 BOOL min_distance : 1;
542 BOOL max_distance : 1;
543 BOOL mode : 1;
545 /* EAX2 */
546 BOOL dry_filter : 1;
547 BOOL wet_filter : 1;
548 BOOL room_rolloff : 1;
549 BOOL cone_outsidevolumehf : 1;
550 BOOL air_absorb : 1;
551 BOOL flags : 1;
552 } bit;
555 struct DS8Buffer {
556 IDirectSoundBuffer8 IDirectSoundBuffer8_iface;
557 IDirectSound3DBuffer IDirectSound3DBuffer_iface;
558 IDirectSoundNotify IDirectSoundNotify_iface;
559 IKsPropertySet IKsPropertySet_iface;
561 LONG ref, ds3d_ref, not_ref, prop_ref;
562 LONG all_ref;
564 DeviceShare *share;
565 DS8Primary *primary;
567 /* From the primary */
568 ALCcontext *ctx;
570 DS8Data *buffer;
571 ALuint source;
573 ALsizei segsize;
574 ALsizei data_offset;
575 ALsizei queue_base;
576 ALsizei curidx;
577 ALuint stream_bids[QBUFFERS];
579 DWORD init_done : 1;
580 DWORD isplaying : 1;
581 DWORD islooping : 1;
582 DWORD bufferlost : 1;
583 DWORD playflags : 28;
584 DWORD ds3dmode;
586 /* Must be 0 (deferred, not yet placed), DSBSTATUS_LOCSOFTWARE, or
587 * DSBSTATUS_LOCHARDWARE.
589 DWORD loc_status;
591 struct {
592 DS3DBUFFER ds3d;
593 EAX20BUFFERPROPERTIES eax;
594 float eax1_reverbmix; /* Mirrored by eax.lRoom. */
595 } deferred;
596 union BufferParamFlags dirty;
598 ALuint filter[2];
600 DWORD nnotify, lastpos;
601 DSBPOSITIONNOTIFY *notify;
605 struct DSBufferGroup {
606 DWORD64 FreeBuffers;
607 DS8Buffer *Buffers;
611 union PrimaryParamFlags {
612 LONG flags;
613 struct {
614 BOOL pos : 1;
615 BOOL vel : 1;
616 BOOL orientation : 1;
617 BOOL distancefactor : 1;
618 BOOL rollofffactor : 1;
619 BOOL dopplerfactor : 1;
620 BOOL effect : 1;
621 } bit;
624 struct DS8Primary {
625 IDirectSoundBuffer IDirectSoundBuffer_iface;
626 IDirectSound3DListener IDirectSound3DListener_iface;
627 IKsPropertySet IKsPropertySet_iface;
629 LONG ref, ds3d_ref, prop_ref;
630 IDirectSoundBuffer8 *write_emu;
631 DS8Buffer writable_buf;
632 DS8Impl *parent;
634 DeviceShare *share;
635 /* Taken from the share */
636 ALCcontext *ctx;
637 ALCint refresh;
638 ALuint auxslot;
640 DWORD buf_size;
641 BOOL stopped;
642 DWORD flags;
643 WAVEFORMATEXTENSIBLE format;
645 DS8Buffer **notifies;
646 DWORD nnotifies, sizenotifies;
648 ALuint effect;
649 ALfloat rollofffactor;
651 struct {
652 DS3DLISTENER ds3d;
653 EAX30LISTENERPROPERTIES eax;
654 float eax1_volume; /* Mirrored by eax.lRoom. */
655 float eax1_dampening; /* Not used. */
656 } deferred;
657 union PrimaryParamFlags dirty;
659 DWORD NumBufferGroups;
660 struct DSBufferGroup *BufferGroups;
664 /* Device implementation */
665 struct DS8Impl {
666 IDirectSound8 IDirectSound8_iface;
667 IDirectSound IDirectSound_iface;
668 IUnknown IUnknown_iface;
670 LONG ref, unkref, dsref;
671 BOOL is_8;
673 DeviceShare *share;
675 /* Taken from the share */
676 ALCdevice *device;
678 DS8Primary primary;
680 DWORD prio_level;
684 DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
686 DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x00, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
688 DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x00, 0xc0, 0x4f, 0xc2, 0x8a, 0xca);
690 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
691 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
693 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
696 HRESULT DS8Primary_PreInit(DS8Primary *prim, DS8Impl *parent);
697 void DS8Primary_Clear(DS8Primary *prim);
698 void DS8Primary_triggernots(DS8Primary *prim);
699 void DS8Primary_streamfeeder(DS8Primary *prim, BYTE *scratch_mem/*2K non-permanent memory*/);
700 HRESULT WINAPI DS8Primary_Initialize(IDirectSoundBuffer *iface, IDirectSound *ds, const DSBUFFERDESC *desc);
701 HRESULT WINAPI DS8Primary3D_CommitDeferredSettings(IDirectSound3DListener *iface);
703 HRESULT DS8Buffer_Create(DS8Buffer **ppv, DS8Primary *parent, IDirectSoundBuffer *orig, BOOL prim_emu);
704 void DS8Buffer_Destroy(DS8Buffer *buf);
705 void DS8Buffer_SetParams(DS8Buffer *buffer, const DS3DBUFFER *params, const EAX20BUFFERPROPERTIES *eax_params, LONG flags);
706 HRESULT WINAPI DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8 *iface, DWORD *playpos, DWORD *curpos);
707 HRESULT WINAPI DS8Buffer_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status);
708 HRESULT WINAPI DS8Buffer_Initialize(IDirectSoundBuffer8 *iface, IDirectSound *ds, const DSBUFFERDESC *desc);
710 HRESULT EAX1_Set(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
711 HRESULT EAX1_Get(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
712 HRESULT EAX1Buffer_Set(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
713 HRESULT EAX1Buffer_Get(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
715 HRESULT EAX2_Set(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData);
716 HRESULT EAX2_Get(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
717 HRESULT EAX2Buffer_Set(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData);
718 HRESULT EAX2Buffer_Get(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned);
721 static inline LONG gain_to_mB(float gain)
723 return (gain > 1e-5f) ? (LONG)(log10f(gain) * 2000.0f) : -10000l;
725 static inline float mB_to_gain(float millibels)
727 return powf(10.0f, millibels/2000.0f);
730 static inline LONG clampI(LONG val, LONG minval, LONG maxval)
732 if(val >= maxval) return maxval;
733 if(val <= minval) return minval;
734 return val;
736 static inline ULONG clampU(ULONG val, ULONG minval, ULONG maxval)
738 if(val >= maxval) return maxval;
739 if(val <= minval) return minval;
740 return val;
742 static inline FLOAT clampF(FLOAT val, FLOAT minval, FLOAT maxval)
744 if(val >= maxval) return maxval;
745 if(val <= minval) return minval;
746 return val;
750 #define checkALError() do { \
751 ALenum err = alGetError(); \
752 if(err != AL_NO_ERROR) \
753 ERR(">>>>>>>>>>>> Received AL error %#x on context %p, %s:%u\n", \
754 err, get_context(), __FUNCTION__, __LINE__); \
755 } while (0)
757 #define checkALCError(dev) do { \
758 ALenum err = alcGetError(dev); \
759 if(err != ALC_NO_ERROR) \
760 ERR(">>>>>>>>>>>> Received ALC error %#x on device %p, %s:%u\n", \
761 err, dev, __FUNCTION__, __LINE__); \
762 } while(0)
765 #define setALContext(actx) EnterALSection(actx)
766 #define popALContext() LeaveALSection()
769 HRESULT DSOUND_Create(REFIID riid, void **ppDS);
770 HRESULT DSOUND_Create8(REFIID riid, void **ppDS);
771 HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppDSFD);
772 HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **piks);
773 HRESULT DSOUND_CaptureCreate(REFIID riid, void **ppDSC);
774 HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppDSC);
776 HRESULT enumerate_mmdevices(EDataFlow flow, LPDSENUMCALLBACKW cb, void *user);
777 HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device);
779 extern const WCHAR wine_vxd_drv[];