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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * Most thread locking is complete. There may be a few race
23 * conditions still lurking.
25 * Tested with a Soundblaster clone, a Gravis UltraSound Classic,
26 * and a Turtle Beach Tropez+.
29 * Implement SetCooperativeLevel properly (need to address focus issues)
30 * Implement DirectSound3DBuffers (stubs in place)
31 * Use hardware 3D support if available
32 * Add critical section locking inside Release and AddRef methods
33 * Handle static buffers - put those in hardware, non-static not in hardware
34 * Hardware DuplicateSoundBuffer
35 * Proper volume calculation, and setting volume in HEL primary buffer
36 * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
42 #include <sys/types.h>
43 #include <sys/fcntl.h>
47 #include <math.h> /* Insomnia - pow() function */
57 #include "wine/windef16.h"
58 #include "wine/debug.h"
61 #include "dsound_private.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
66 /*******************************************************************************
67 * IDirectSound3DBuffer
70 /* IUnknown methods */
71 static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
72 LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
74 ICOM_THIS(IDirectSound3DBufferImpl,iface);
76 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
77 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
80 static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
82 ICOM_THIS(IDirectSound3DBufferImpl,iface);
85 TRACE("(%p) ref was %ld\n", This, This->ref);
86 ulReturn = InterlockedIncrement(&This->ref);
88 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
92 static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
94 ICOM_THIS(IDirectSound3DBufferImpl,iface);
97 TRACE("(%p) ref was %ld\n", This, This->ref);
99 ulReturn = InterlockedDecrement(&This->ref);
104 BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D);
106 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
109 return 0; /* leave it to IDirectSoundBufferImpl_Release */
112 if (This->dsb->ds3db == This) This->dsb->ds3db = NULL;
114 DeleteCriticalSection(&This->lock);
116 HeapFree(GetProcessHeap(),0,This);
121 /* IDirectSound3DBuffer methods */
122 static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
123 LPDIRECTSOUND3DBUFFER iface,
124 LPDS3DBUFFER lpDs3dBuffer)
130 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
131 LPDIRECTSOUND3DBUFFER iface,
132 LPDWORD lpdwInsideConeAngle,
133 LPDWORD lpdwOutsideConeAngle)
139 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
140 LPDIRECTSOUND3DBUFFER iface,
141 LPD3DVECTOR lpvConeOrientation)
147 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
148 LPDIRECTSOUND3DBUFFER iface,
149 LPLONG lplConeOutsideVolume)
155 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
156 LPDIRECTSOUND3DBUFFER iface,
157 LPD3DVALUE lpfMaxDistance)
163 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
164 LPDIRECTSOUND3DBUFFER iface,
165 LPD3DVALUE lpfMinDistance)
171 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
172 LPDIRECTSOUND3DBUFFER iface,
179 static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
180 LPDIRECTSOUND3DBUFFER iface,
181 LPD3DVECTOR lpvPosition)
187 static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
188 LPDIRECTSOUND3DBUFFER iface,
189 LPD3DVECTOR lpvVelocity)
195 static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
196 LPDIRECTSOUND3DBUFFER iface,
197 LPCDS3DBUFFER lpcDs3dBuffer,
204 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
205 LPDIRECTSOUND3DBUFFER iface,
206 DWORD dwInsideConeAngle,
207 DWORD dwOutsideConeAngle,
214 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
215 LPDIRECTSOUND3DBUFFER iface,
216 D3DVALUE x, D3DVALUE y, D3DVALUE z,
223 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
224 LPDIRECTSOUND3DBUFFER iface,
225 LONG lConeOutsideVolume,
232 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
233 LPDIRECTSOUND3DBUFFER iface,
234 D3DVALUE fMaxDistance,
241 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
242 LPDIRECTSOUND3DBUFFER iface,
243 D3DVALUE fMinDistance,
250 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
251 LPDIRECTSOUND3DBUFFER iface,
255 ICOM_THIS(IDirectSound3DBufferImpl,iface);
256 TRACE("mode = %lx\n", dwMode);
257 This->ds3db.dwMode = dwMode;
261 static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
262 LPDIRECTSOUND3DBUFFER iface,
263 D3DVALUE x, D3DVALUE y, D3DVALUE z,
270 static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
271 LPDIRECTSOUND3DBUFFER iface,
272 D3DVALUE x, D3DVALUE y, D3DVALUE z,
279 static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
281 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
282 /* IUnknown methods */
283 IDirectSound3DBufferImpl_QueryInterface,
284 IDirectSound3DBufferImpl_AddRef,
285 IDirectSound3DBufferImpl_Release,
286 /* IDirectSound3DBuffer methods */
287 IDirectSound3DBufferImpl_GetAllParameters,
288 IDirectSound3DBufferImpl_GetConeAngles,
289 IDirectSound3DBufferImpl_GetConeOrientation,
290 IDirectSound3DBufferImpl_GetConeOutsideVolume,
291 IDirectSound3DBufferImpl_GetMaxDistance,
292 IDirectSound3DBufferImpl_GetMinDistance,
293 IDirectSound3DBufferImpl_GetMode,
294 IDirectSound3DBufferImpl_GetPosition,
295 IDirectSound3DBufferImpl_GetVelocity,
296 IDirectSound3DBufferImpl_SetAllParameters,
297 IDirectSound3DBufferImpl_SetConeAngles,
298 IDirectSound3DBufferImpl_SetConeOrientation,
299 IDirectSound3DBufferImpl_SetConeOutsideVolume,
300 IDirectSound3DBufferImpl_SetMaxDistance,
301 IDirectSound3DBufferImpl_SetMinDistance,
302 IDirectSound3DBufferImpl_SetMode,
303 IDirectSound3DBufferImpl_SetPosition,
304 IDirectSound3DBufferImpl_SetVelocity,
307 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
308 IDirectSoundBufferImpl *This,
309 IDirectSound3DBufferImpl **pds3db)
311 IDirectSound3DBufferImpl *ds3db;
313 ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*ds3db));
316 ICOM_VTBL(ds3db) = &ds3dbvt;
317 InitializeCriticalSection(&ds3db->lock);
319 ds3db->ds3db.dwSize = sizeof(DS3DBUFFER);
320 ds3db->ds3db.vPosition.u1.x = 0.0;
321 ds3db->ds3db.vPosition.u2.y = 0.0;
322 ds3db->ds3db.vPosition.u3.z = 0.0;
323 ds3db->ds3db.vVelocity.u1.x = 0.0;
324 ds3db->ds3db.vVelocity.u2.y = 0.0;
325 ds3db->ds3db.vVelocity.u3.z = 0.0;
326 ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
327 ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
328 ds3db->ds3db.vConeOrientation.u1.x = 0.0;
329 ds3db->ds3db.vConeOrientation.u2.y = 0.0;
330 ds3db->ds3db.vConeOrientation.u3.z = 0.0;
331 ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
332 ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
333 ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
334 ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
340 /*******************************************************************************
341 * IDirectSound3DListener
344 /* IUnknown methods */
345 static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
346 LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
348 ICOM_THIS(IDirectSound3DListenerImpl,iface);
350 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
351 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
354 static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
356 ICOM_THIS(IDirectSound3DListenerImpl,iface);
357 return InterlockedIncrement(&This->ref);
360 static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
362 ICOM_THIS(IDirectSound3DListenerImpl,iface);
365 TRACE("(%p) ref was %ld\n", This, This->ref);
367 ulReturn = InterlockedDecrement(&This->ref);
369 /* Free all resources */
370 if( ulReturn == 0 ) {
372 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
373 DeleteCriticalSection(&This->lock);
374 HeapFree(GetProcessHeap(),0,This);
380 /* IDirectSound3DListener methods */
381 static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
382 LPDIRECTSOUND3DLISTENER iface,
383 LPDS3DLISTENER lpDS3DL)
389 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
390 LPDIRECTSOUND3DLISTENER iface,
391 LPD3DVALUE lpfDistanceFactor)
397 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
398 LPDIRECTSOUND3DLISTENER iface,
399 LPD3DVALUE lpfDopplerFactor)
405 static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
406 LPDIRECTSOUND3DLISTENER iface,
407 LPD3DVECTOR lpvOrientFront,
408 LPD3DVECTOR lpvOrientTop)
414 static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
415 LPDIRECTSOUND3DLISTENER iface,
416 LPD3DVECTOR lpvPosition)
422 static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
423 LPDIRECTSOUND3DLISTENER iface,
424 LPD3DVALUE lpfRolloffFactor)
430 static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
431 LPDIRECTSOUND3DLISTENER iface,
432 LPD3DVECTOR lpvVelocity)
438 static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
439 LPDIRECTSOUND3DLISTENER iface,
440 LPCDS3DLISTENER lpcDS3DL,
447 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
448 LPDIRECTSOUND3DLISTENER iface,
449 D3DVALUE fDistanceFactor,
456 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
457 LPDIRECTSOUND3DLISTENER iface,
458 D3DVALUE fDopplerFactor,
465 static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
466 LPDIRECTSOUND3DLISTENER iface,
467 D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
468 D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
475 static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
476 LPDIRECTSOUND3DLISTENER iface,
477 D3DVALUE x, D3DVALUE y, D3DVALUE z,
484 static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
485 LPDIRECTSOUND3DLISTENER iface,
486 D3DVALUE fRolloffFactor,
493 static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
494 LPDIRECTSOUND3DLISTENER iface,
495 D3DVALUE x, D3DVALUE y, D3DVALUE z,
502 static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
503 LPDIRECTSOUND3DLISTENER iface)
510 static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt =
512 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
513 /* IUnknown methods */
514 IDirectSound3DListenerImpl_QueryInterface,
515 IDirectSound3DListenerImpl_AddRef,
516 IDirectSound3DListenerImpl_Release,
517 /* IDirectSound3DListener methods */
518 IDirectSound3DListenerImpl_GetAllParameter,
519 IDirectSound3DListenerImpl_GetDistanceFactor,
520 IDirectSound3DListenerImpl_GetDopplerFactor,
521 IDirectSound3DListenerImpl_GetOrientation,
522 IDirectSound3DListenerImpl_GetPosition,
523 IDirectSound3DListenerImpl_GetRolloffFactor,
524 IDirectSound3DListenerImpl_GetVelocity,
525 IDirectSound3DListenerImpl_SetAllParameters,
526 IDirectSound3DListenerImpl_SetDistanceFactor,
527 IDirectSound3DListenerImpl_SetDopplerFactor,
528 IDirectSound3DListenerImpl_SetOrientation,
529 IDirectSound3DListenerImpl_SetPosition,
530 IDirectSound3DListenerImpl_SetRolloffFactor,
531 IDirectSound3DListenerImpl_SetVelocity,
532 IDirectSound3DListenerImpl_CommitDeferredSettings,
535 HRESULT WINAPI IDirectSound3DListenerImpl_Create(
536 PrimaryBufferImpl *This,
537 IDirectSound3DListenerImpl **pdsl)
539 IDirectSound3DListenerImpl *dsl;
541 dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsl));
543 ICOM_VTBL(dsl) = &ds3dlvt;
545 dsl->ds3dl.dwSize = sizeof(DS3DLISTENER);
546 dsl->ds3dl.vPosition.u1.x = 0.0;
547 dsl->ds3dl.vPosition.u2.y = 0.0;
548 dsl->ds3dl.vPosition.u3.z = 0.0;
549 dsl->ds3dl.vVelocity.u1.x = 0.0;
550 dsl->ds3dl.vVelocity.u2.y = 0.0;
551 dsl->ds3dl.vVelocity.u3.z = 0.0;
552 dsl->ds3dl.vOrientFront.u1.x = 0.0;
553 dsl->ds3dl.vOrientFront.u2.y = 0.0;
554 dsl->ds3dl.vOrientFront.u3.z = 1.0;
555 dsl->ds3dl.vOrientTop.u1.x = 0.0;
556 dsl->ds3dl.vOrientTop.u2.y = 1.0;
557 dsl->ds3dl.vOrientTop.u3.z = 0.0;
558 dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
559 dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
561 InitializeCriticalSection(&dsl->lock);
564 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);