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)
32 #include <OpenAL/al.h>
33 #include <OpenAL/alc.h>
50 #define TRACE(fmt,args...) do { \
52 fprintf(stderr, "%04x:trace:dsound:%s " fmt, (UINT)GetCurrentThreadId(), __FUNCTION__, ##args); \
54 #define WARN(fmt,args...) do { \
56 fprintf(stderr, "%04x:warn:dsound:%s " fmt, (UINT)GetCurrentThreadId(), __FUNCTION__, ##args); \
58 #define FIXME(fmt,args...) do { \
60 fprintf(stderr, "%04x:fixme:dsound:%s " fmt, (UINT)GetCurrentThreadId(), __FUNCTION__, ##args); \
62 #define ERR(fmt,args...) do { \
64 fprintf(stderr, "%04x:err:dsound:%s " fmt, (UINT)GetCurrentThreadId(), __FUNCTION__, ##args); \
67 #define TRACE(args...)
69 #define FIXME(args...)
73 const char *wine_dbg_sprintf( const char *format
, ... );
74 const char *wine_dbgstr_wn( const WCHAR
*str
, int n
);
76 static inline const char *debugstr_guid( const GUID
*id
)
78 if (!id
) return "(null)";
79 if (!((ULONG_PTR
)id
>> 16)) return wine_dbg_sprintf( "<guid-0x%04hx>", (WORD
)(ULONG_PTR
)id
);
80 return wine_dbg_sprintf( "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
81 id
->Data1
, id
->Data2
, id
->Data3
,
82 id
->Data4
[0], id
->Data4
[1], id
->Data4
[2], id
->Data4
[3],
83 id
->Data4
[4], id
->Data4
[5], id
->Data4
[6], id
->Data4
[7] );
86 static inline const char *debugstr_w( const WCHAR
*s
) { return wine_dbgstr_wn( s
, -1 ); }
95 /* Set to 1 to build a DLL that can be used in an app that uses OpenAL itself.
96 * Thread-local contexts are needed for true concurrency, however. Disallowing
97 * concurrency can avoid a save and restore of the context. */
98 #define ALLOW_CONCURRENT_AL 0
100 /* All openal functions */
101 extern int openal_loaded
;
102 #ifdef SONAME_LIBOPENAL
103 extern LPALCCREATECONTEXT palcCreateContext
;
104 extern LPALCMAKECONTEXTCURRENT palcMakeContextCurrent
;
105 extern LPALCPROCESSCONTEXT palcProcessContext
;
106 extern LPALCSUSPENDCONTEXT palcSuspendContext
;
107 extern LPALCDESTROYCONTEXT palcDestroyContext
;
108 extern LPALCGETCURRENTCONTEXT palcGetCurrentContext
;
109 extern LPALCGETCONTEXTSDEVICE palcGetContextsDevice
;
110 extern LPALCOPENDEVICE palcOpenDevice
;
111 extern LPALCCLOSEDEVICE palcCloseDevice
;
112 extern LPALCGETERROR palcGetError
;
113 extern LPALCISEXTENSIONPRESENT palcIsExtensionPresent
;
114 extern LPALCGETPROCADDRESS palcGetProcAddress
;
115 extern LPALCGETENUMVALUE palcGetEnumValue
;
116 extern LPALCGETSTRING palcGetString
;
117 extern LPALCGETINTEGERV palcGetIntegerv
;
118 extern LPALCCAPTUREOPENDEVICE palcCaptureOpenDevice
;
119 extern LPALCCAPTURECLOSEDEVICE palcCaptureCloseDevice
;
120 extern LPALCCAPTURESTART palcCaptureStart
;
121 extern LPALCCAPTURESTOP palcCaptureStop
;
122 extern LPALCCAPTURESAMPLES palcCaptureSamples
;
123 extern LPALENABLE palEnable
;
124 extern LPALDISABLE palDisable
;
125 extern LPALISENABLED palIsEnabled
;
126 extern LPALGETSTRING palGetString
;
127 extern LPALGETBOOLEANV palGetBooleanv
;
128 extern LPALGETINTEGERV palGetIntegerv
;
129 extern LPALGETFLOATV palGetFloatv
;
130 extern LPALGETDOUBLEV palGetDoublev
;
131 extern LPALGETBOOLEAN palGetBoolean
;
132 extern LPALGETINTEGER palGetInteger
;
133 extern LPALGETFLOAT palGetFloat
;
134 extern LPALGETDOUBLE palGetDouble
;
135 extern LPALGETERROR palGetError
;
136 extern LPALISEXTENSIONPRESENT palIsExtensionPresent
;
137 extern LPALGETPROCADDRESS palGetProcAddress
;
138 extern LPALGETENUMVALUE palGetEnumValue
;
139 extern LPALLISTENERF palListenerf
;
140 extern LPALLISTENER3F palListener3f
;
141 extern LPALLISTENERFV palListenerfv
;
142 extern LPALLISTENERI palListeneri
;
143 extern LPALLISTENER3I palListener3i
;
144 extern LPALLISTENERIV palListeneriv
;
145 extern LPALGETLISTENERF palGetListenerf
;
146 extern LPALGETLISTENER3F palGetListener3f
;
147 extern LPALGETLISTENERFV palGetListenerfv
;
148 extern LPALGETLISTENERI palGetListeneri
;
149 extern LPALGETLISTENER3I palGetListener3i
;
150 extern LPALGETLISTENERIV palGetListeneriv
;
151 extern LPALGENSOURCES palGenSources
;
152 extern LPALDELETESOURCES palDeleteSources
;
153 extern LPALISSOURCE palIsSource
;
154 extern LPALSOURCEF palSourcef
;
155 extern LPALSOURCE3F palSource3f
;
156 extern LPALSOURCEFV palSourcefv
;
157 extern LPALSOURCEI palSourcei
;
158 extern LPALSOURCE3I palSource3i
;
159 extern LPALSOURCEIV palSourceiv
;
160 extern LPALGETSOURCEF palGetSourcef
;
161 extern LPALGETSOURCE3F palGetSource3f
;
162 extern LPALGETSOURCEFV palGetSourcefv
;
163 extern LPALGETSOURCEI palGetSourcei
;
164 extern LPALGETSOURCE3I palGetSource3i
;
165 extern LPALGETSOURCEIV palGetSourceiv
;
166 extern LPALSOURCEPLAYV palSourcePlayv
;
167 extern LPALSOURCESTOPV palSourceStopv
;
168 extern LPALSOURCEREWINDV palSourceRewindv
;
169 extern LPALSOURCEPAUSEV palSourcePausev
;
170 extern LPALSOURCEPLAY palSourcePlay
;
171 extern LPALSOURCESTOP palSourceStop
;
172 extern LPALSOURCEREWIND palSourceRewind
;
173 extern LPALSOURCEPAUSE palSourcePause
;
174 extern LPALSOURCEQUEUEBUFFERS palSourceQueueBuffers
;
175 extern LPALSOURCEUNQUEUEBUFFERS palSourceUnqueueBuffers
;
176 extern LPALGENBUFFERS palGenBuffers
;
177 extern LPALDELETEBUFFERS palDeleteBuffers
;
178 extern LPALISBUFFER palIsBuffer
;
179 extern LPALBUFFERF palBufferf
;
180 extern LPALBUFFER3F palBuffer3f
;
181 extern LPALBUFFERFV palBufferfv
;
182 extern LPALBUFFERI palBufferi
;
183 extern LPALBUFFER3I palBuffer3i
;
184 extern LPALBUFFERIV palBufferiv
;
185 extern LPALGETBUFFERF palGetBufferf
;
186 extern LPALGETBUFFER3F palGetBuffer3f
;
187 extern LPALGETBUFFERFV palGetBufferfv
;
188 extern LPALGETBUFFERI palGetBufferi
;
189 extern LPALGETBUFFER3I palGetBuffer3i
;
190 extern LPALGETBUFFERIV palGetBufferiv
;
191 extern LPALBUFFERDATA palBufferData
;
192 extern LPALDOPPLERFACTOR palDopplerFactor
;
193 extern LPALDOPPLERVELOCITY palDopplerVelocity
;
194 extern LPALDISTANCEMODEL palDistanceModel
;
195 extern LPALSPEEDOFSOUND palSpeedOfSound
;
197 #define alcCreateContext palcCreateContext
198 #define alcMakeContextCurrent palcMakeContextCurrent
199 #define alcProcessContext palcProcessContext
200 #define alcSuspendContext palcSuspendContext
201 #define alcDestroyContext palcDestroyContext
202 #define alcGetCurrentContext palcGetCurrentContext
203 #define alcGetContextsDevice palcGetContextsDevice
204 #define alcOpenDevice palcOpenDevice
205 #define alcCloseDevice palcCloseDevice
206 #define alcGetError palcGetError
207 #define alcIsExtensionPresent palcIsExtensionPresent
208 #define alcGetProcAddress palcGetProcAddress
209 #define alcGetEnumValue palcGetEnumValue
210 #define alcGetString palcGetString
211 #define alcGetIntegerv palcGetIntegerv
212 #define alcCaptureOpenDevice palcCaptureOpenDevice
213 #define alcCaptureCloseDevice palcCaptureCloseDevice
214 #define alcCaptureStart palcCaptureStart
215 #define alcCaptureStop palcCaptureStop
216 #define alcCaptureSamples palcCaptureSamples
217 #define alEnable palEnable
218 #define alDisable palDisable
219 #define alIsEnabled palIsEnabled
220 #define alGetString palGetString
221 #define alGetBooleanv palGetBooleanv
222 #define alGetIntegerv palGetIntegerv
223 #define alGetFloatv palGetFloatv
224 #define alGetDoublev palGetDoublev
225 #define alGetBoolean palGetBoolean
226 #define alGetInteger palGetInteger
227 #define alGetFloat palGetFloat
228 #define alGetDouble palGetDouble
229 #define alGetError palGetError
230 #define alIsExtensionPresent palIsExtensionPresent
231 #define alGetProcAddress palGetProcAddress
232 #define alGetEnumValue palGetEnumValue
233 #define alListenerf palListenerf
234 #define alListener3f palListener3f
235 #define alListenerfv palListenerfv
236 #define alListeneri palListeneri
237 #define alListener3i palListener3i
238 #define alListeneriv palListeneriv
239 #define alGetListenerf palGetListenerf
240 #define alGetListener3f palGetListener3f
241 #define alGetListenerfv palGetListenerfv
242 #define alGetListeneri palGetListeneri
243 #define alGetListener3i palGetListener3i
244 #define alGetListeneriv palGetListeneriv
245 #define alGenSources palGenSources
246 #define alDeleteSources palDeleteSources
247 #define alIsSource palIsSource
248 #define alSourcef palSourcef
249 #define alSource3f palSource3f
250 #define alSourcefv palSourcefv
251 #define alSourcei palSourcei
252 #define alSource3i palSource3i
253 #define alSourceiv palSourceiv
254 #define alGetSourcef palGetSourcef
255 #define alGetSource3f palGetSource3f
256 #define alGetSourcefv palGetSourcefv
257 #define alGetSourcei palGetSourcei
258 #define alGetSource3i palGetSource3i
259 #define alGetSourceiv palGetSourceiv
260 #define alSourcePlayv palSourcePlayv
261 #define alSourceStopv palSourceStopv
262 #define alSourceRewindv palSourceRewindv
263 #define alSourcePausev palSourcePausev
264 #define alSourcePlay palSourcePlay
265 #define alSourceStop palSourceStop
266 #define alSourceRewind palSourceRewind
267 #define alSourcePause palSourcePause
268 #define alSourceQueueBuffers palSourceQueueBuffers
269 #define alSourceUnqueueBuffers palSourceUnqueueBuffers
270 #define alGenBuffers palGenBuffers
271 #define alDeleteBuffers palDeleteBuffers
272 #define alIsBuffer palIsBuffer
273 #define alBufferf palBufferf
274 #define alBuffer3f palBuffer3f
275 #define alBufferfv palBufferfv
276 #define alBufferi palBufferi
277 #define alBuffer3i palBuffer3i
278 #define alBufferiv palBufferiv
279 #define alGetBufferf palGetBufferf
280 #define alGetBuffer3f palGetBuffer3f
281 #define alGetBufferfv palGetBufferfv
282 #define alGetBufferi palGetBufferi
283 #define alGetBuffer3i palGetBuffer3i
284 #define alGetBufferiv palGetBufferiv
285 #define alBufferData palBufferData
286 #define alDopplerFactor palDopplerFactor
287 #define alDopplerVelocity palDopplerVelocity
288 #define alDistanceModel palDistanceModel
289 #define alSpeedOfSound palSpeedOfSound
296 /* OpenAL only allows for 1 single access to the device at the same time */
297 extern CRITICAL_SECTION openal_crst
;
299 extern const ALCchar
*DSOUND_getdevicestrings(void);
300 extern const ALCchar
*DSOUND_getcapturedevicestrings(void);
302 extern LPALCMAKECONTEXTCURRENT set_context
;
303 extern LPALCGETCURRENTCONTEXT get_context
;
304 extern BOOL local_contexts
;
306 /* Device implementation */
307 typedef struct DS8Primary DS8Primary
;
308 typedef struct DS8Buffer DS8Buffer
;
310 typedef struct DS8Impl
312 IDirectSound8 IDirectSound8_iface
;
313 IDirectSound IDirectSound_iface
;
322 DWORD speaker_config
;
328 #define AL_BYTE 0x1400
329 #define AL_UNSIGNED_BYTE 0x1401
330 #define AL_SHORT 0x1402
331 #define AL_UNSIGNED_SHORT 0x1403
332 #define AL_INT 0x1404
333 #define AL_UNSIGNED_INT 0x1405
334 #define AL_FLOAT 0x1406
335 #define AL_DOUBLE 0x1407
336 #define AL_BYTE3 0x1408
337 #define AL_UNSIGNED_BYTE3 0x1409
338 #define AL_MULAW 0x1410
339 #define AL_IMA4 0x1411
341 /* Channel configurations */
342 #define AL_MONO 0x1500
343 #define AL_STEREO 0x1501
344 #define AL_REAR 0x1502
345 #define AL_QUAD 0x1503
346 #define AL_5POINT1 0x1504 /* (WFX order) */
347 #define AL_6POINT1 0x1505 /* (WFX order) */
348 #define AL_7POINT1 0x1506 /* (WFX order) */
350 /* Storage formats */
351 #define AL_MONO8 0x1100
352 #define AL_MONO16 0x1101
353 #define AL_MONO32F 0x10010
354 #define AL_STEREO8 0x1102
355 #define AL_STEREO16 0x1103
356 #define AL_STEREO32F 0x10011
357 #define AL_QUAD8 0x1204
358 #define AL_QUAD16 0x1205
359 #define AL_QUAD32F 0x1206
360 #define AL_REAR8 0x1207
361 #define AL_REAR16 0x1208
362 #define AL_REAR32F 0x1209
363 #define AL_5POINT1_8 0x120A
364 #define AL_5POINT1_16 0x120B
365 #define AL_5POINT1_32F 0x120C
366 #define AL_6POINT1_8 0x120D
367 #define AL_6POINT1_16 0x120E
368 #define AL_6POINT1_32F 0x120F
369 #define AL_7POINT1_8 0x1210
370 #define AL_7POINT1_16 0x1211
371 #define AL_7POINT1_32F 0x1212
379 SOFT_BUFFER_SUB_DATA
,
380 SOFT_DEFERRED_UPDATES
,
385 typedef struct ExtALFuncs
387 PFNALBUFFERSUBDATASOFTPROC BufferSubData
;
388 PFNALBUFFERDATASTATICPROC BufferDataStatic
;
390 LPALGENEFFECTS GenEffects
;
391 LPALDELETEEFFECTS DeleteEffects
;
395 LPALGENAUXILIARYEFFECTSLOTS GenAuxiliaryEffectSlots
;
396 LPALDELETEAUXILIARYEFFECTSLOTS DeleteAuxiliaryEffectSlots
;
397 LPALAUXILIARYEFFECTSLOTI AuxiliaryEffectSloti
;
399 void (AL_APIENTRY
*BufferSamplesSOFT
)(ALuint
,ALuint
,ALenum
,ALsizei
,ALenum
,ALenum
,const ALvoid
*);
400 void (AL_APIENTRY
*BufferSubSamplesSOFT
)(ALuint
,ALsizei
,ALsizei
,ALenum
,ALenum
,const ALvoid
*);
401 void (AL_APIENTRY
*GetBufferSamplesSOFT
)(ALuint
,ALsizei
,ALsizei
,ALenum
,ALenum
,ALvoid
*);
402 ALboolean (AL_APIENTRY
*IsBufferFormatSupportedSOFT
)(ALenum
);
404 void (AL_APIENTRY
*DeferUpdates
)(void);
405 void (AL_APIENTRY
*ProcessUpdates
)(void);
410 IDirectSoundBuffer IDirectSoundBuffer_iface
;
411 IDirectSound3DListener IDirectSound3DListener_iface
;
412 IKsPropertySet IKsPropertySet_iface
;
414 LONG ref
, ds3d_ref
, prop_ref
;
415 IDirectSoundBuffer8
*write_emu
;
418 CRITICAL_SECTION crst
;
423 WAVEFORMATEXTENSIBLE format
;
426 ALboolean SupportedExt
[MAX_EXTENSIONS
];
429 DWORD nsources
, sizesources
;
432 DWORD nbuffers
, sizebuffers
;
433 DS8Buffer
**notifies
;
434 DWORD nnotifies
, sizenotifies
;
443 EAXLISTENERPROPERTIES eax_prop
;
450 BOOL orientation
: 1;
451 BOOL distancefactor
: 1;
452 BOOL rollofffactor
: 1;
453 BOOL dopplerfactor
: 1;
458 ALfloat rollofffactor
;
463 typedef struct DS8Data
{
466 /* Lock was called and unlock isn't? */
469 WAVEFORMATEXTENSIBLE format
;
473 ALenum in_type
, in_chans
;
481 /* Amount of buffers that have to be queued when
482 * bufferdatastatic and buffersubdata are not available */
487 IDirectSoundBuffer8 IDirectSoundBuffer8_iface
;
488 IDirectSoundBuffer IDirectSoundBuffer_iface
;
489 IDirectSound3DBuffer IDirectSound3DBuffer_iface
;
490 IDirectSoundNotify IDirectSoundNotify_iface
;
491 IKsPropertySet IKsPropertySet_iface
;
493 LONG ref
, ds3d_ref
, not_ref
, prop_ref
;
501 BOOL isplaying
, islooping
, bufferlost
;
504 CRITICAL_SECTION
*crst
;
506 DS3DBUFFER ds3dbuffer
;
511 BOOL cone_angles
: 1;
512 BOOL cone_orient
: 1;
513 BOOL cone_outsidevolume
: 1;
514 BOOL min_distance
: 1;
515 BOOL max_distance
: 1;
521 DWORD nnotify
, lastpos
;
522 DSBPOSITIONNOTIFY
*notify
;
525 extern HRESULT
DS8Primary_Create(DS8Primary
**prim
, DS8Impl
*parent
);
526 extern void DS8Primary_Destroy(DS8Primary
*prim
);
528 extern HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*parent
, IDirectSoundBuffer
*orig
);
529 extern void DS8Buffer_Destroy(DS8Buffer
*buf
);
531 static inline ALdouble
gain_to_mB(ALdouble gain
)
533 return log10(gain
) * 2000.0;
535 static inline ALdouble
mB_to_gain(ALdouble millibels
)
537 return pow(10.0, millibels
/2000.0);
540 static inline LONG
clampI(LONG val
, LONG minval
, LONG maxval
)
542 if(val
>= maxval
) return maxval
;
543 if(val
<= minval
) return minval
;
546 static inline ULONG
clampU(ULONG val
, ULONG minval
, ULONG maxval
)
548 if(val
>= maxval
) return maxval
;
549 if(val
<= minval
) return minval
;
552 static inline FLOAT
clampF(FLOAT val
, FLOAT minval
, FLOAT maxval
)
554 if(val
>= maxval
) return maxval
;
555 if(val
<= minval
) return minval
;
560 #define getALError() \
562 ALenum err = alGetError(); \
563 if(err != AL_NO_ERROR) \
564 ERR(">>>>>>>>>>>> Received AL error %#x on context %p, %s:%u\n", err, get_context(), __FUNCTION__, __LINE__); \
567 #define getALCError(dev) \
569 ALenum err = alcGetError(dev); \
570 if(err != ALC_NO_ERROR) \
571 ERR(">>>>>>>>>>>> Received ALC error %#x on device %p, %s:%u\n", err, dev, __FUNCTION__, __LINE__); \
574 #if ALLOW_CONCURRENT_AL
576 #define setALContext(actx) \
578 ALCcontext *__old_ctx, *cur_ctx = actx; \
579 if (!local_contexts) EnterCriticalSection(&openal_crst); \
580 __old_ctx = get_context(); \
581 if (__old_ctx != cur_ctx && set_context(cur_ctx) == ALC_FALSE) {\
582 ERR("Couldn't set current context!!\n"); \
583 getALCError(alcGetContextsDevice(cur_ctx)); \
586 /* Only restore a NULL context if using global contexts, for TLS contexts always restore */
587 #define popALContext() \
588 if (__old_ctx != cur_ctx && \
589 (local_contexts || __old_ctx) && \
590 set_context(__old_ctx) == ALC_FALSE) { \
591 ERR("Couldn't restore old context!!\n"); \
592 getALCError(alcGetContextsDevice(__old_ctx)); \
594 if (!local_contexts) LeaveCriticalSection(&openal_crst); \
599 #define setALContext(actx) \
601 ALCcontext *cur_ctx = actx; \
602 if (!local_contexts) EnterCriticalSection(&openal_crst); \
603 if (set_context(cur_ctx) == ALC_FALSE) { \
604 ERR("Couldn't set current context!!\n"); \
605 getALCError(alcGetContextsDevice(cur_ctx)); \
608 #define popALContext() \
609 if (!local_contexts) LeaveCriticalSection(&openal_crst); \
614 HRESULT
DSOUND_Create(REFIID riid
, void **ppDS
);
615 HRESULT
DSOUND_Create8(REFIID riid
, void **ppDS
);
616 HRESULT
DSOUND_FullDuplexCreate(REFIID riid
, void **ppDSFD
);
617 HRESULT
IKsPrivatePropertySetImpl_Create(REFIID riid
, void **piks
);
618 HRESULT
DSOUND_CaptureCreate(REFIID riid
, void **ppDSC
);
619 HRESULT
DSOUND_CaptureCreate8(REFIID riid
, void **ppDSC8
);
621 extern const GUID DSOUND_renderer_guid
;
622 extern const GUID DSOUND_capture_guid
;