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>
49 #include <math.h> /* Insomnia - pow() function */
59 #include "wine/windef16.h"
60 #include "wine/debug.h"
63 #include "dsound_private.h"
65 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
68 /*******************************************************************************
69 * IDirectSound3DBuffer
72 /* IUnknown methods */
73 static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
74 LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
76 ICOM_THIS(IDirectSound3DBufferImpl,iface);
78 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
79 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
82 static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
84 ICOM_THIS(IDirectSound3DBufferImpl,iface);
87 TRACE("(%p) ref was %ld\n", This, This->ref);
88 ulReturn = InterlockedIncrement(&This->ref);
90 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
94 static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
96 ICOM_THIS(IDirectSound3DBufferImpl,iface);
99 TRACE("(%p) ref was %ld\n", This, This->ref);
101 ulReturn = InterlockedDecrement(&This->ref);
106 BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D);
108 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
111 return 0; /* leave it to IDirectSoundBufferImpl_Release */
114 if (This->dsb->ds3db == This) This->dsb->ds3db = NULL;
116 DeleteCriticalSection(&This->lock);
118 HeapFree(GetProcessHeap(),0,This);
123 /* IDirectSound3DBuffer methods */
124 static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
125 LPDIRECTSOUND3DBUFFER iface,
126 LPDS3DBUFFER lpDs3dBuffer)
132 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
133 LPDIRECTSOUND3DBUFFER iface,
134 LPDWORD lpdwInsideConeAngle,
135 LPDWORD lpdwOutsideConeAngle)
141 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
142 LPDIRECTSOUND3DBUFFER iface,
143 LPD3DVECTOR lpvConeOrientation)
149 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
150 LPDIRECTSOUND3DBUFFER iface,
151 LPLONG lplConeOutsideVolume)
157 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
158 LPDIRECTSOUND3DBUFFER iface,
159 LPD3DVALUE lpfMaxDistance)
165 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
166 LPDIRECTSOUND3DBUFFER iface,
167 LPD3DVALUE lpfMinDistance)
173 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
174 LPDIRECTSOUND3DBUFFER iface,
181 static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
182 LPDIRECTSOUND3DBUFFER iface,
183 LPD3DVECTOR lpvPosition)
189 static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
190 LPDIRECTSOUND3DBUFFER iface,
191 LPD3DVECTOR lpvVelocity)
197 static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
198 LPDIRECTSOUND3DBUFFER iface,
199 LPCDS3DBUFFER lpcDs3dBuffer,
206 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
207 LPDIRECTSOUND3DBUFFER iface,
208 DWORD dwInsideConeAngle,
209 DWORD dwOutsideConeAngle,
216 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
217 LPDIRECTSOUND3DBUFFER iface,
218 D3DVALUE x, D3DVALUE y, D3DVALUE z,
225 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
226 LPDIRECTSOUND3DBUFFER iface,
227 LONG lConeOutsideVolume,
234 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
235 LPDIRECTSOUND3DBUFFER iface,
236 D3DVALUE fMaxDistance,
243 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
244 LPDIRECTSOUND3DBUFFER iface,
245 D3DVALUE fMinDistance,
252 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
253 LPDIRECTSOUND3DBUFFER iface,
257 ICOM_THIS(IDirectSound3DBufferImpl,iface);
258 TRACE("mode = %lx\n", dwMode);
259 This->ds3db.dwMode = dwMode;
263 static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
264 LPDIRECTSOUND3DBUFFER iface,
265 D3DVALUE x, D3DVALUE y, D3DVALUE z,
272 static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
273 LPDIRECTSOUND3DBUFFER iface,
274 D3DVALUE x, D3DVALUE y, D3DVALUE z,
281 static ICOM_VTABLE(IDirectSound3DBuffer) ds3dbvt =
283 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
284 /* IUnknown methods */
285 IDirectSound3DBufferImpl_QueryInterface,
286 IDirectSound3DBufferImpl_AddRef,
287 IDirectSound3DBufferImpl_Release,
288 /* IDirectSound3DBuffer methods */
289 IDirectSound3DBufferImpl_GetAllParameters,
290 IDirectSound3DBufferImpl_GetConeAngles,
291 IDirectSound3DBufferImpl_GetConeOrientation,
292 IDirectSound3DBufferImpl_GetConeOutsideVolume,
293 IDirectSound3DBufferImpl_GetMaxDistance,
294 IDirectSound3DBufferImpl_GetMinDistance,
295 IDirectSound3DBufferImpl_GetMode,
296 IDirectSound3DBufferImpl_GetPosition,
297 IDirectSound3DBufferImpl_GetVelocity,
298 IDirectSound3DBufferImpl_SetAllParameters,
299 IDirectSound3DBufferImpl_SetConeAngles,
300 IDirectSound3DBufferImpl_SetConeOrientation,
301 IDirectSound3DBufferImpl_SetConeOutsideVolume,
302 IDirectSound3DBufferImpl_SetMaxDistance,
303 IDirectSound3DBufferImpl_SetMinDistance,
304 IDirectSound3DBufferImpl_SetMode,
305 IDirectSound3DBufferImpl_SetPosition,
306 IDirectSound3DBufferImpl_SetVelocity,
309 HRESULT WINAPI IDirectSound3DBufferImpl_Create(
310 IDirectSoundBufferImpl *This,
311 IDirectSound3DBufferImpl **pds3db)
313 IDirectSound3DBufferImpl *ds3db;
315 ds3db = (IDirectSound3DBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*ds3db));
318 ICOM_VTBL(ds3db) = &ds3dbvt;
319 InitializeCriticalSection(&ds3db->lock);
321 ds3db->ds3db.dwSize = sizeof(DS3DBUFFER);
322 ds3db->ds3db.vPosition.u1.x = 0.0;
323 ds3db->ds3db.vPosition.u2.y = 0.0;
324 ds3db->ds3db.vPosition.u3.z = 0.0;
325 ds3db->ds3db.vVelocity.u1.x = 0.0;
326 ds3db->ds3db.vVelocity.u2.y = 0.0;
327 ds3db->ds3db.vVelocity.u3.z = 0.0;
328 ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
329 ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
330 ds3db->ds3db.vConeOrientation.u1.x = 0.0;
331 ds3db->ds3db.vConeOrientation.u2.y = 0.0;
332 ds3db->ds3db.vConeOrientation.u3.z = 0.0;
333 ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
334 ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
335 ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
336 ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
342 /*******************************************************************************
343 * IDirectSound3DListener
346 /* IUnknown methods */
347 static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
348 LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
350 ICOM_THIS(IDirectSound3DListenerImpl,iface);
352 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
353 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
356 static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
358 ICOM_THIS(IDirectSound3DListenerImpl,iface);
359 return InterlockedIncrement(&This->ref);
362 static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
364 ICOM_THIS(IDirectSound3DListenerImpl,iface);
367 TRACE("(%p) ref was %ld\n", This, This->ref);
369 ulReturn = InterlockedDecrement(&This->ref);
371 /* Free all resources */
372 if( ulReturn == 0 ) {
374 IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
375 DeleteCriticalSection(&This->lock);
376 HeapFree(GetProcessHeap(),0,This);
382 /* IDirectSound3DListener methods */
383 static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
384 LPDIRECTSOUND3DLISTENER iface,
385 LPDS3DLISTENER lpDS3DL)
391 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
392 LPDIRECTSOUND3DLISTENER iface,
393 LPD3DVALUE lpfDistanceFactor)
399 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
400 LPDIRECTSOUND3DLISTENER iface,
401 LPD3DVALUE lpfDopplerFactor)
407 static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
408 LPDIRECTSOUND3DLISTENER iface,
409 LPD3DVECTOR lpvOrientFront,
410 LPD3DVECTOR lpvOrientTop)
416 static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
417 LPDIRECTSOUND3DLISTENER iface,
418 LPD3DVECTOR lpvPosition)
424 static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
425 LPDIRECTSOUND3DLISTENER iface,
426 LPD3DVALUE lpfRolloffFactor)
432 static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
433 LPDIRECTSOUND3DLISTENER iface,
434 LPD3DVECTOR lpvVelocity)
440 static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
441 LPDIRECTSOUND3DLISTENER iface,
442 LPCDS3DLISTENER lpcDS3DL,
449 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
450 LPDIRECTSOUND3DLISTENER iface,
451 D3DVALUE fDistanceFactor,
458 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
459 LPDIRECTSOUND3DLISTENER iface,
460 D3DVALUE fDopplerFactor,
467 static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
468 LPDIRECTSOUND3DLISTENER iface,
469 D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
470 D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
477 static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
478 LPDIRECTSOUND3DLISTENER iface,
479 D3DVALUE x, D3DVALUE y, D3DVALUE z,
486 static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
487 LPDIRECTSOUND3DLISTENER iface,
488 D3DVALUE fRolloffFactor,
495 static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
496 LPDIRECTSOUND3DLISTENER iface,
497 D3DVALUE x, D3DVALUE y, D3DVALUE z,
504 static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
505 LPDIRECTSOUND3DLISTENER iface)
512 static ICOM_VTABLE(IDirectSound3DListener) ds3dlvt =
514 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
515 /* IUnknown methods */
516 IDirectSound3DListenerImpl_QueryInterface,
517 IDirectSound3DListenerImpl_AddRef,
518 IDirectSound3DListenerImpl_Release,
519 /* IDirectSound3DListener methods */
520 IDirectSound3DListenerImpl_GetAllParameter,
521 IDirectSound3DListenerImpl_GetDistanceFactor,
522 IDirectSound3DListenerImpl_GetDopplerFactor,
523 IDirectSound3DListenerImpl_GetOrientation,
524 IDirectSound3DListenerImpl_GetPosition,
525 IDirectSound3DListenerImpl_GetRolloffFactor,
526 IDirectSound3DListenerImpl_GetVelocity,
527 IDirectSound3DListenerImpl_SetAllParameters,
528 IDirectSound3DListenerImpl_SetDistanceFactor,
529 IDirectSound3DListenerImpl_SetDopplerFactor,
530 IDirectSound3DListenerImpl_SetOrientation,
531 IDirectSound3DListenerImpl_SetPosition,
532 IDirectSound3DListenerImpl_SetRolloffFactor,
533 IDirectSound3DListenerImpl_SetVelocity,
534 IDirectSound3DListenerImpl_CommitDeferredSettings,
537 HRESULT WINAPI IDirectSound3DListenerImpl_Create(
538 PrimaryBufferImpl *This,
539 IDirectSound3DListenerImpl **pdsl)
541 IDirectSound3DListenerImpl *dsl;
543 dsl = (IDirectSound3DListenerImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsl));
545 ICOM_VTBL(dsl) = &ds3dlvt;
547 dsl->ds3dl.dwSize = sizeof(DS3DLISTENER);
548 dsl->ds3dl.vPosition.u1.x = 0.0;
549 dsl->ds3dl.vPosition.u2.y = 0.0;
550 dsl->ds3dl.vPosition.u3.z = 0.0;
551 dsl->ds3dl.vVelocity.u1.x = 0.0;
552 dsl->ds3dl.vVelocity.u2.y = 0.0;
553 dsl->ds3dl.vVelocity.u3.z = 0.0;
554 dsl->ds3dl.vOrientFront.u1.x = 0.0;
555 dsl->ds3dl.vOrientFront.u2.y = 0.0;
556 dsl->ds3dl.vOrientFront.u3.z = 1.0;
557 dsl->ds3dl.vOrientTop.u1.x = 0.0;
558 dsl->ds3dl.vOrientTop.u2.y = 1.0;
559 dsl->ds3dl.vOrientTop.u3.z = 0.0;
560 dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
561 dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
563 InitializeCriticalSection(&dsl->lock);
566 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);