xref: /reactos/dll/directx/wine/dsound/sound3d.c (revision c2c66aff)
1 /*  			DirectSound
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2001 TransGaming Technologies, Inc.
6  * Copyright 2002-2003 Rok Mandeljc <rok.mandeljc@gimb.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 /*
23  * Most thread locking is complete. There may be a few race
24  * conditions still lurking.
25  *
26  * Tested with a Soundblaster clone, a Gravis UltraSound Classic,
27  * and a Turtle Beach Tropez+.
28  *
29  * TODO:
30  *	Implement SetCooperativeLevel properly (need to address focus issues)
31  *	Implement DirectSound3DBuffers (stubs in place)
32  *	Use hardware 3D support if available
33  *      Add critical section locking inside Release and AddRef methods
34  *      Handle static buffers - put those in hardware, non-static not in hardware
35  *      Hardware DuplicateSoundBuffer
36  *      Proper volume calculation, and setting volume in HEL primary buffer
37  *      Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN
38  */
39 
40 #include "dsound_private.h"
41 
42 /* default velocity of sound in the air */
43 #define DEFAULT_VELOCITY 340
44 
45 /*******************************************************************************
46  *              Auxiliary functions
47  */
48 
49 /* scalar product (I believe it's called dot product in English) */
ScalarProduct(const D3DVECTOR * a,const D3DVECTOR * b)50 static inline D3DVALUE ScalarProduct (const D3DVECTOR *a, const D3DVECTOR *b)
51 {
52 	D3DVALUE c;
53 	c = (a->x*b->x) + (a->y*b->y) + (a->z*b->z);
54 	TRACE("(%f,%f,%f) * (%f,%f,%f) = %f)\n", a->x, a->y, a->z, b->x, b->y,
55 	      b->z, c);
56 	return c;
57 }
58 
59 /* vector product (I believe it's called cross product in English */
VectorProduct(const D3DVECTOR * a,const D3DVECTOR * b)60 static inline D3DVECTOR VectorProduct (const D3DVECTOR *a, const D3DVECTOR *b)
61 {
62 	D3DVECTOR c;
63 	c.x = (a->y*b->z) - (a->z*b->y);
64 	c.y = (a->z*b->x) - (a->x*b->z);
65 	c.z = (a->x*b->y) - (a->y*b->x);
66 	TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y,
67 	      b->z, c.x, c.y, c.z);
68 	return c;
69 }
70 
71 /* magnitude (length) of vector */
VectorMagnitude(const D3DVECTOR * a)72 static inline D3DVALUE VectorMagnitude (const D3DVECTOR *a)
73 {
74 	D3DVALUE l;
75 	l = sqrt (ScalarProduct (a, a));
76 	TRACE("|(%f,%f,%f)| = %f\n", a->x, a->y, a->z, l);
77 	return l;
78 }
79 
80 /* conversion between radians and degrees */
RadToDeg(D3DVALUE angle)81 static inline D3DVALUE RadToDeg (D3DVALUE angle)
82 {
83 	D3DVALUE newangle;
84 	newangle = angle * (360/(2*M_PI));
85 	TRACE("%f rad = %f deg\n", angle, newangle);
86 	return newangle;
87 }
88 
89 /* angle between vectors - rad version */
AngleBetweenVectorsRad(const D3DVECTOR * a,const D3DVECTOR * b)90 static inline D3DVALUE AngleBetweenVectorsRad (const D3DVECTOR *a, const D3DVECTOR *b)
91 {
92 	D3DVALUE la, lb, product, angle, cos;
93 	/* definition of scalar product: a*b = |a|*|b|*cos... therefore: */
94 	product = ScalarProduct (a,b);
95 	la = VectorMagnitude (a);
96 	lb = VectorMagnitude (b);
97 	if (!la || !lb)
98 		return 0;
99 
100 	cos = product/(la*lb);
101 	angle = acos(cos);
102 	TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians (%f degrees)\n",  a->x, a->y, a->z, b->x,
103 	      b->y, b->z, angle, RadToDeg(angle));
104 	return angle;
105 }
106 
AngleBetweenVectorsDeg(const D3DVECTOR * a,const D3DVECTOR * b)107 static inline D3DVALUE AngleBetweenVectorsDeg (const D3DVECTOR *a, const D3DVECTOR *b)
108 {
109 	return RadToDeg(AngleBetweenVectorsRad(a, b));
110 }
111 
112 /* calculates vector between two points */
VectorBetweenTwoPoints(const D3DVECTOR * a,const D3DVECTOR * b)113 static inline D3DVECTOR VectorBetweenTwoPoints (const D3DVECTOR *a, const D3DVECTOR *b)
114 {
115 	D3DVECTOR c;
116 	c.x = b->x - a->x;
117 	c.y = b->y - a->y;
118 	c.z = b->z - a->z;
119 	TRACE("A (%f,%f,%f), B (%f,%f,%f), AB = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y,
120 	      b->z, c.x, c.y, c.z);
121 	return c;
122 }
123 
124 #ifndef __REACTOS__
125 /* calculates the length of vector's projection on another vector */
ProjectVector(const D3DVECTOR * a,const D3DVECTOR * p)126 static inline D3DVALUE ProjectVector (const D3DVECTOR *a, const D3DVECTOR *p)
127 {
128 	D3DVALUE prod, result;
129 	prod = ScalarProduct(a, p);
130 	result = prod/VectorMagnitude(p);
131 	TRACE("length projection of (%f,%f,%f) on (%f,%f,%f) = %f\n", a->x, a->y, a->z, p->x,
132               p->y, p->z, result);
133 	return result;
134 }
135 #endif
136 
137 /*******************************************************************************
138  *              3D Buffer and Listener mixing
139  */
140 
DSOUND_Calc3DBuffer(IDirectSoundBufferImpl * dsb)141 void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
142 {
143 	/* volume, at which the sound will be played after all calcs. */
144 	D3DVALUE lVolume = 0;
145 	/* stuff for distance related stuff calc. */
146 	D3DVECTOR vDistance;
147 	D3DVALUE flDistance = 0;
148 	/* panning related stuff */
149 	D3DVALUE flAngle;
150 	D3DVECTOR vLeft;
151 	/* doppler shift related stuff */
152 #if 0
153 	D3DVALUE flFreq, flBufferVel, flListenerVel;
154 #endif
155 
156 	TRACE("(%p)\n",dsb);
157 
158 	/* initial buffer volume */
159 	lVolume = dsb->ds3db_lVolume;
160 
161 	switch (dsb->ds3db_ds3db.dwMode)
162 	{
163 		case DS3DMODE_DISABLE:
164 			TRACE("3D processing disabled\n");
165 			/* this one is here only to eliminate annoying warning message */
166 			DSOUND_RecalcVolPan (&dsb->volpan);
167 			break;
168 		case DS3DMODE_NORMAL:
169 			TRACE("Normal 3D processing mode\n");
170 			/* we need to calculate distance between buffer and listener*/
171 			vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->device->ds3dl.vPosition);
172 			flDistance = VectorMagnitude (&vDistance);
173 			break;
174 		case DS3DMODE_HEADRELATIVE:
175 			TRACE("Head-relative 3D processing mode\n");
176 			/* distance between buffer and listener is same as buffer's position */
177 			flDistance = VectorMagnitude (&dsb->ds3db_ds3db.vPosition);
178 			break;
179 	}
180 
181 	if (flDistance > dsb->ds3db_ds3db.flMaxDistance)
182 	{
183 		/* some apps don't want you to hear too distant sounds... */
184 		if (dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE)
185 		{
186 			dsb->volpan.lVolume = DSBVOLUME_MIN;
187 			DSOUND_RecalcVolPan (&dsb->volpan);
188 			/* i guess mixing here would be a waste of power */
189 			return;
190 		}
191 		else
192 			flDistance = dsb->ds3db_ds3db.flMaxDistance;
193 	}
194 
195 	if (flDistance < dsb->ds3db_ds3db.flMinDistance)
196 		flDistance = dsb->ds3db_ds3db.flMinDistance;
197 
198 	/* attenuation proportional to the distance squared, converted to millibels as in lVolume*/
199 	lVolume -= log10(flDistance/dsb->ds3db_ds3db.flMinDistance * flDistance/dsb->ds3db_ds3db.flMinDistance)*1000;
200 	TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %d to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume);
201 
202 	/* conning */
203 	/* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/
204 	if (dsb->ds3db_ds3db.vConeOrientation.x == 0 && dsb->ds3db_ds3db.vConeOrientation.y == 0 && dsb->ds3db_ds3db.vConeOrientation.z == 0)
205 	{
206 		TRACE("conning: cones not set\n");
207 	}
208 	else
209 	{
210 		/* calculate angle */
211 		flAngle = AngleBetweenVectorsDeg(&dsb->ds3db_ds3db.vConeOrientation, &vDistance);
212 		/* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */
213 		if (dsb->ds3db_ds3db.dwInsideConeAngle != dsb->ds3db_ds3db.dwOutsideConeAngle)
214 		{
215 			/* my test show that for my way of calc., we need only half of angles */
216 			DWORD dwInsideConeAngle = dsb->ds3db_ds3db.dwInsideConeAngle/2;
217 			DWORD dwOutsideConeAngle = dsb->ds3db_ds3db.dwOutsideConeAngle/2;
218 			if (dwOutsideConeAngle == dwInsideConeAngle)
219 				++dwOutsideConeAngle;
220 
221 			/* full volume */
222 			if (flAngle < dwInsideConeAngle)
223 				flAngle = dwInsideConeAngle;
224 			/* min (app defined) volume */
225 			if (flAngle > dwOutsideConeAngle)
226 				flAngle = dwOutsideConeAngle;
227 			/* this probably isn't the right thing, but it's ok for the time being */
228 			lVolume += ((dsb->ds3db_ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle;
229 		}
230 		TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %d deg; OutsideConeAngle(/2) = %d deg; ConeOutsideVolume = %d => adjusting volume to %f\n",
231 		       flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume);
232 	}
233 	dsb->volpan.lVolume = lVolume;
234 
235 	/* panning */
236 	if (dsb->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x &&
237 	    dsb->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y &&
238 	    dsb->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) {
239 		dsb->volpan.lPan = 0;
240 		flAngle = 0.0;
241 	}
242 	else
243 	{
244 		vDistance = VectorBetweenTwoPoints(&dsb->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
245 		vLeft = VectorProduct(&dsb->device->ds3dl.vOrientFront, &dsb->device->ds3dl.vOrientTop);
246 		flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
247 		/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */
248 		dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
249 	}
250 	TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan);
251 
252 	/* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
253 #if 0
254 	/* doppler shift*/
255 	if ((VectorMagnitude(&ds3db_ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->device->ds3dl.vVelocity) == 0))
256 	{
257 		TRACE("doppler: Buffer and Listener don't have velocities\n");
258 	}
259 	else if (ds3db_ds3db.vVelocity != dsb->device->ds3dl.vVelocity)
260 	{
261 		/* calculate length of ds3db_ds3db.vVelocity component which causes Doppler Effect
262 		   NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE
263 		         if buffer moves AWAY from listener, it's velocity component is POSITIVE */
264 		flBufferVel = ProjectVector(&dsb->ds3db_ds3db.vVelocity, &vDistance);
265 		/* calculate length of ds3dl.vVelocity component which causes Doppler Effect
266 		   NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE
267 		         if listener moves AWAY from buffer, it's velocity component is NEGATIVE */
268 		flListenerVel = ProjectVector(&dsb->device->ds3dl.vVelocity, &vDistance);
269 		/* formula taken from Gianicoli D.: Physics, 4th edition: */
270 		/* FIXME: replace dsb->freq with appropriate frequency ! */
271 		flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
272 		TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel,
273 		      dsb->freq, flFreq);
274 		/* FIXME: replace following line with correct frequency setting ! */
275 		dsb->freq = flFreq;
276 		DSOUND_RecalcFormat(dsb);
277 		DSOUND_MixToTemporary(dsb, 0, dsb->buflen);
278 	}
279 #endif
280 
281 	/* time for remix */
282 	DSOUND_RecalcVolPan(&dsb->volpan);
283 }
284 
DSOUND_Mix3DBuffer(IDirectSoundBufferImpl * dsb)285 static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb)
286 {
287 	TRACE("(%p)\n",dsb);
288 
289 	DSOUND_Calc3DBuffer(dsb);
290 }
291 
DSOUND_ChangeListener(IDirectSound3DListenerImpl * ds3dl)292 static void DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
293 {
294 	int i;
295 	TRACE("(%p)\n",ds3dl);
296 	for (i = 0; i < ds3dl->device->nrofbuffers; i++)
297 	{
298 		/* check if this buffer is waiting for recalculation */
299 		if (ds3dl->device->buffers[i]->ds3db_need_recalc)
300 		{
301 			DSOUND_Mix3DBuffer(ds3dl->device->buffers[i]);
302 		}
303 	}
304 }
305 
306 /*******************************************************************************
307  *              IDirectSound3DBuffer
308  */
309 
310 /* IUnknown methods */
IDirectSound3DBufferImpl_QueryInterface(LPDIRECTSOUND3DBUFFER iface,REFIID riid,LPVOID * ppobj)311 static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
312 	LPDIRECTSOUND3DBUFFER iface, REFIID riid, LPVOID *ppobj)
313 {
314 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
315 
316 	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
317 	return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
318 }
319 
IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)320 static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
321 {
322     IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
323     ULONG ref = InterlockedIncrement(&(This->ref));
324 
325     TRACE("(%p) ref was %d\n", This, ref - 1);
326 
327     if(ref == 1)
328         InterlockedIncrement(&This->dsb->numIfaces);
329 
330     return ref;
331 }
332 
IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)333 static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
334 {
335     IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
336     ULONG ref = InterlockedDecrement(&(This->ref));
337     TRACE("(%p) ref was %d\n", This, ref + 1);
338 
339     if (!ref) {
340         This->dsb->ds3db = NULL;
341         if (!InterlockedDecrement(&This->dsb->numIfaces))
342             secondarybuffer_destroy(This->dsb);
343         HeapFree(GetProcessHeap(), 0, This);
344         TRACE("(%p) released\n", This);
345     }
346     return ref;
347 }
348 
349 /* IDirectSound3DBuffer methods */
IDirectSound3DBufferImpl_GetAllParameters(LPDIRECTSOUND3DBUFFER iface,LPDS3DBUFFER lpDs3dBuffer)350 static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
351 	LPDIRECTSOUND3DBUFFER iface,
352 	LPDS3DBUFFER lpDs3dBuffer)
353 {
354 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
355 	TRACE("(%p,%p)\n",This,lpDs3dBuffer);
356 
357 	if (lpDs3dBuffer == NULL) {
358 		WARN("invalid parameter: lpDs3dBuffer == NULL\n");
359 		return DSERR_INVALIDPARAM;
360 	}
361 
362 	if (lpDs3dBuffer->dwSize < sizeof(*lpDs3dBuffer)) {
363 		WARN("invalid parameter: lpDs3dBuffer->dwSize = %d\n",lpDs3dBuffer->dwSize);
364 		return DSERR_INVALIDPARAM;
365 	}
366 
367 	TRACE("returning: all parameters\n");
368 	*lpDs3dBuffer = This->dsb->ds3db_ds3db;
369 	return DS_OK;
370 }
371 
IDirectSound3DBufferImpl_GetConeAngles(LPDIRECTSOUND3DBUFFER iface,LPDWORD lpdwInsideConeAngle,LPDWORD lpdwOutsideConeAngle)372 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
373 	LPDIRECTSOUND3DBUFFER iface,
374 	LPDWORD lpdwInsideConeAngle,
375 	LPDWORD lpdwOutsideConeAngle)
376 {
377 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
378 	TRACE("returning: Inside Cone Angle = %d degrees; Outside Cone Angle = %d degrees\n",
379 		This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle);
380 	*lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle;
381 	*lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle;
382 	return DS_OK;
383 }
384 
IDirectSound3DBufferImpl_GetConeOrientation(LPDIRECTSOUND3DBUFFER iface,LPD3DVECTOR lpvConeOrientation)385 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
386 	LPDIRECTSOUND3DBUFFER iface,
387 	LPD3DVECTOR lpvConeOrientation)
388 {
389 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
390 	TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
391 		This->dsb->ds3db_ds3db.vConeOrientation.x,
392 		This->dsb->ds3db_ds3db.vConeOrientation.y,
393 		This->dsb->ds3db_ds3db.vConeOrientation.z);
394 	*lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation;
395 	return DS_OK;
396 }
397 
IDirectSound3DBufferImpl_GetConeOutsideVolume(LPDIRECTSOUND3DBUFFER iface,LPLONG lplConeOutsideVolume)398 static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
399 	LPDIRECTSOUND3DBUFFER iface,
400 	LPLONG lplConeOutsideVolume)
401 {
402 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
403 	TRACE("returning: Cone Outside Volume = %d\n", This->dsb->ds3db_ds3db.lConeOutsideVolume);
404 	*lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume;
405 	return DS_OK;
406 }
407 
IDirectSound3DBufferImpl_GetMaxDistance(LPDIRECTSOUND3DBUFFER iface,LPD3DVALUE lpfMaxDistance)408 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
409 	LPDIRECTSOUND3DBUFFER iface,
410 	LPD3DVALUE lpfMaxDistance)
411 {
412 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
413 	TRACE("returning: Max Distance = %f\n", This->dsb->ds3db_ds3db.flMaxDistance);
414 	*lpfMaxDistance = This->dsb->ds3db_ds3db.flMaxDistance;
415 	return DS_OK;
416 }
417 
IDirectSound3DBufferImpl_GetMinDistance(LPDIRECTSOUND3DBUFFER iface,LPD3DVALUE lpfMinDistance)418 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
419 	LPDIRECTSOUND3DBUFFER iface,
420 	LPD3DVALUE lpfMinDistance)
421 {
422 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
423 	TRACE("returning: Min Distance = %f\n", This->dsb->ds3db_ds3db.flMinDistance);
424 	*lpfMinDistance = This->dsb->ds3db_ds3db.flMinDistance;
425 	return DS_OK;
426 }
427 
IDirectSound3DBufferImpl_GetMode(LPDIRECTSOUND3DBUFFER iface,LPDWORD lpdwMode)428 static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
429 	LPDIRECTSOUND3DBUFFER iface,
430 	LPDWORD lpdwMode)
431 {
432 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
433 	TRACE("returning: Mode = %d\n", This->dsb->ds3db_ds3db.dwMode);
434 	*lpdwMode = This->dsb->ds3db_ds3db.dwMode;
435 	return DS_OK;
436 }
437 
IDirectSound3DBufferImpl_GetPosition(LPDIRECTSOUND3DBUFFER iface,LPD3DVECTOR lpvPosition)438 static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
439 	LPDIRECTSOUND3DBUFFER iface,
440 	LPD3DVECTOR lpvPosition)
441 {
442 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
443 	TRACE("returning: Position vector = (%f,%f,%f)\n",
444 		This->dsb->ds3db_ds3db.vPosition.x,
445 		This->dsb->ds3db_ds3db.vPosition.y,
446 		This->dsb->ds3db_ds3db.vPosition.z);
447 	*lpvPosition = This->dsb->ds3db_ds3db.vPosition;
448 	return DS_OK;
449 }
450 
IDirectSound3DBufferImpl_GetVelocity(LPDIRECTSOUND3DBUFFER iface,LPD3DVECTOR lpvVelocity)451 static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
452 	LPDIRECTSOUND3DBUFFER iface,
453 	LPD3DVECTOR lpvVelocity)
454 {
455 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
456 	TRACE("returning: Velocity vector = (%f,%f,%f)\n",
457 		This->dsb->ds3db_ds3db.vVelocity.x,
458 		This->dsb->ds3db_ds3db.vVelocity.y,
459 		This->dsb->ds3db_ds3db.vVelocity.z);
460 	*lpvVelocity = This->dsb->ds3db_ds3db.vVelocity;
461 	return DS_OK;
462 }
463 
IDirectSound3DBufferImpl_SetAllParameters(LPDIRECTSOUND3DBUFFER iface,LPCDS3DBUFFER lpcDs3dBuffer,DWORD dwApply)464 static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
465 	LPDIRECTSOUND3DBUFFER iface,
466 	LPCDS3DBUFFER lpcDs3dBuffer,
467 	DWORD dwApply)
468 {
469 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
470 	DWORD status = DSERR_INVALIDPARAM;
471 	TRACE("(%p,%p,%x)\n",iface,lpcDs3dBuffer,dwApply);
472 
473 	if (lpcDs3dBuffer == NULL) {
474 		WARN("invalid parameter: lpcDs3dBuffer == NULL\n");
475 		return status;
476 	}
477 
478 	if (lpcDs3dBuffer->dwSize != sizeof(DS3DBUFFER)) {
479 		WARN("invalid parameter: lpcDs3dBuffer->dwSize = %d\n", lpcDs3dBuffer->dwSize);
480 		return status;
481 	}
482 
483 	TRACE("setting: all parameters; dwApply = %d\n", dwApply);
484 	This->dsb->ds3db_ds3db = *lpcDs3dBuffer;
485 
486 	if (dwApply == DS3D_IMMEDIATE)
487 	{
488 		DSOUND_Mix3DBuffer(This->dsb);
489 	}
490 	This->dsb->ds3db_need_recalc = TRUE;
491 	status = DS_OK;
492 
493 	return status;
494 }
495 
IDirectSound3DBufferImpl_SetConeAngles(LPDIRECTSOUND3DBUFFER iface,DWORD dwInsideConeAngle,DWORD dwOutsideConeAngle,DWORD dwApply)496 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
497 	LPDIRECTSOUND3DBUFFER iface,
498 	DWORD dwInsideConeAngle,
499 	DWORD dwOutsideConeAngle,
500 	DWORD dwApply)
501 {
502 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
503 	TRACE("setting: Inside Cone Angle = %d; Outside Cone Angle = %d; dwApply = %d\n",
504 		dwInsideConeAngle, dwOutsideConeAngle, dwApply);
505 	This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle;
506 	This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle;
507 	if (dwApply == DS3D_IMMEDIATE)
508 	{
509 		DSOUND_Mix3DBuffer(This->dsb);
510 	}
511 	This->dsb->ds3db_need_recalc = TRUE;
512 	return DS_OK;
513 }
514 
IDirectSound3DBufferImpl_SetConeOrientation(LPDIRECTSOUND3DBUFFER iface,D3DVALUE x,D3DVALUE y,D3DVALUE z,DWORD dwApply)515 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
516 	LPDIRECTSOUND3DBUFFER iface,
517 	D3DVALUE x, D3DVALUE y, D3DVALUE z,
518 	DWORD dwApply)
519 {
520 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
521 	TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
522 	This->dsb->ds3db_ds3db.vConeOrientation.x = x;
523 	This->dsb->ds3db_ds3db.vConeOrientation.y = y;
524 	This->dsb->ds3db_ds3db.vConeOrientation.z = z;
525 	if (dwApply == DS3D_IMMEDIATE)
526 	{
527 		This->dsb->ds3db_need_recalc = FALSE;
528 		DSOUND_Mix3DBuffer(This->dsb);
529 	}
530 	This->dsb->ds3db_need_recalc = TRUE;
531 	return DS_OK;
532 }
533 
IDirectSound3DBufferImpl_SetConeOutsideVolume(LPDIRECTSOUND3DBUFFER iface,LONG lConeOutsideVolume,DWORD dwApply)534 static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
535 	LPDIRECTSOUND3DBUFFER iface,
536 	LONG lConeOutsideVolume,
537 	DWORD dwApply)
538 {
539 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
540 	TRACE("setting: ConeOutsideVolume = %d; dwApply = %d\n", lConeOutsideVolume, dwApply);
541 	This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume;
542 	if (dwApply == DS3D_IMMEDIATE)
543 	{
544 		This->dsb->ds3db_need_recalc = FALSE;
545 		DSOUND_Mix3DBuffer(This->dsb);
546 	}
547 	This->dsb->ds3db_need_recalc = TRUE;
548 	return DS_OK;
549 }
550 
IDirectSound3DBufferImpl_SetMaxDistance(LPDIRECTSOUND3DBUFFER iface,D3DVALUE fMaxDistance,DWORD dwApply)551 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
552 	LPDIRECTSOUND3DBUFFER iface,
553 	D3DVALUE fMaxDistance,
554 	DWORD dwApply)
555 {
556 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
557 	TRACE("setting: MaxDistance = %f; dwApply = %d\n", fMaxDistance, dwApply);
558 	This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance;
559 	if (dwApply == DS3D_IMMEDIATE)
560 	{
561 		This->dsb->ds3db_need_recalc = FALSE;
562 		DSOUND_Mix3DBuffer(This->dsb);
563 	}
564 	This->dsb->ds3db_need_recalc = TRUE;
565 	return DS_OK;
566 }
567 
IDirectSound3DBufferImpl_SetMinDistance(LPDIRECTSOUND3DBUFFER iface,D3DVALUE fMinDistance,DWORD dwApply)568 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
569 	LPDIRECTSOUND3DBUFFER iface,
570 	D3DVALUE fMinDistance,
571 	DWORD dwApply)
572 {
573 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
574 	TRACE("setting: MinDistance = %f; dwApply = %d\n", fMinDistance, dwApply);
575 	This->dsb->ds3db_ds3db.flMinDistance = fMinDistance;
576 	if (dwApply == DS3D_IMMEDIATE)
577 	{
578 		This->dsb->ds3db_need_recalc = FALSE;
579 		DSOUND_Mix3DBuffer(This->dsb);
580 	}
581 	This->dsb->ds3db_need_recalc = TRUE;
582 	return DS_OK;
583 }
584 
IDirectSound3DBufferImpl_SetMode(LPDIRECTSOUND3DBUFFER iface,DWORD dwMode,DWORD dwApply)585 static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
586 	LPDIRECTSOUND3DBUFFER iface,
587 	DWORD dwMode,
588 	DWORD dwApply)
589 {
590 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
591 	TRACE("setting: Mode = %d; dwApply = %d\n", dwMode, dwApply);
592 	This->dsb->ds3db_ds3db.dwMode = dwMode;
593 	if (dwApply == DS3D_IMMEDIATE)
594 	{
595 		This->dsb->ds3db_need_recalc = FALSE;
596 		DSOUND_Mix3DBuffer(This->dsb);
597 	}
598 	This->dsb->ds3db_need_recalc = TRUE;
599 	return DS_OK;
600 }
601 
IDirectSound3DBufferImpl_SetPosition(LPDIRECTSOUND3DBUFFER iface,D3DVALUE x,D3DVALUE y,D3DVALUE z,DWORD dwApply)602 static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
603 	LPDIRECTSOUND3DBUFFER iface,
604 	D3DVALUE x, D3DVALUE y, D3DVALUE z,
605 	DWORD dwApply)
606 {
607 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
608 	TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
609 	This->dsb->ds3db_ds3db.vPosition.x = x;
610 	This->dsb->ds3db_ds3db.vPosition.y = y;
611 	This->dsb->ds3db_ds3db.vPosition.z = z;
612 	if (dwApply == DS3D_IMMEDIATE)
613 	{
614 		This->dsb->ds3db_need_recalc = FALSE;
615 		DSOUND_Mix3DBuffer(This->dsb);
616 	}
617 	This->dsb->ds3db_need_recalc = TRUE;
618 	return DS_OK;
619 }
620 
IDirectSound3DBufferImpl_SetVelocity(LPDIRECTSOUND3DBUFFER iface,D3DVALUE x,D3DVALUE y,D3DVALUE z,DWORD dwApply)621 static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
622 	LPDIRECTSOUND3DBUFFER iface,
623 	D3DVALUE x, D3DVALUE y, D3DVALUE z,
624 	DWORD dwApply)
625 {
626 	IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface;
627 	TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
628 	This->dsb->ds3db_ds3db.vVelocity.x = x;
629 	This->dsb->ds3db_ds3db.vVelocity.y = y;
630 	This->dsb->ds3db_ds3db.vVelocity.z = z;
631 	if (dwApply == DS3D_IMMEDIATE)
632 	{
633 		This->dsb->ds3db_need_recalc = FALSE;
634 		DSOUND_Mix3DBuffer(This->dsb);
635 	}
636 	This->dsb->ds3db_need_recalc = TRUE;
637 	return DS_OK;
638 }
639 
640 static const IDirectSound3DBufferVtbl ds3dbvt =
641 {
642 	/* IUnknown methods */
643 	IDirectSound3DBufferImpl_QueryInterface,
644 	IDirectSound3DBufferImpl_AddRef,
645 	IDirectSound3DBufferImpl_Release,
646 	/* IDirectSound3DBuffer methods */
647 	IDirectSound3DBufferImpl_GetAllParameters,
648 	IDirectSound3DBufferImpl_GetConeAngles,
649 	IDirectSound3DBufferImpl_GetConeOrientation,
650 	IDirectSound3DBufferImpl_GetConeOutsideVolume,
651 	IDirectSound3DBufferImpl_GetMaxDistance,
652 	IDirectSound3DBufferImpl_GetMinDistance,
653 	IDirectSound3DBufferImpl_GetMode,
654 	IDirectSound3DBufferImpl_GetPosition,
655 	IDirectSound3DBufferImpl_GetVelocity,
656 	IDirectSound3DBufferImpl_SetAllParameters,
657 	IDirectSound3DBufferImpl_SetConeAngles,
658 	IDirectSound3DBufferImpl_SetConeOrientation,
659 	IDirectSound3DBufferImpl_SetConeOutsideVolume,
660 	IDirectSound3DBufferImpl_SetMaxDistance,
661 	IDirectSound3DBufferImpl_SetMinDistance,
662 	IDirectSound3DBufferImpl_SetMode,
663 	IDirectSound3DBufferImpl_SetPosition,
664 	IDirectSound3DBufferImpl_SetVelocity,
665 };
666 
IDirectSound3DBufferImpl_Create(IDirectSoundBufferImpl * dsb,IDirectSound3DBufferImpl ** pds3db)667 HRESULT IDirectSound3DBufferImpl_Create(
668 	IDirectSoundBufferImpl *dsb,
669 	IDirectSound3DBufferImpl **pds3db)
670 {
671 	IDirectSound3DBufferImpl *ds3db;
672 	TRACE("(%p,%p)\n",dsb,pds3db);
673 
674 	ds3db = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*ds3db));
675 
676 	if (ds3db == NULL) {
677 		WARN("out of memory\n");
678 		*pds3db = 0;
679 		return DSERR_OUTOFMEMORY;
680 	}
681 
682 	ds3db->ref = 0;
683 	ds3db->dsb = dsb;
684 	ds3db->lpVtbl = &ds3dbvt;
685 
686 	ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
687 	ds3db->dsb->ds3db_ds3db.vPosition.x = 0.0;
688 	ds3db->dsb->ds3db_ds3db.vPosition.y = 0.0;
689 	ds3db->dsb->ds3db_ds3db.vPosition.z = 0.0;
690 	ds3db->dsb->ds3db_ds3db.vVelocity.x = 0.0;
691 	ds3db->dsb->ds3db_ds3db.vVelocity.y = 0.0;
692 	ds3db->dsb->ds3db_ds3db.vVelocity.z = 0.0;
693 	ds3db->dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
694 	ds3db->dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
695 	ds3db->dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
696 	ds3db->dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
697 	ds3db->dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
698 	ds3db->dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
699 	ds3db->dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
700 	ds3db->dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
701 	ds3db->dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
702 
703 	ds3db->dsb->ds3db_need_recalc = TRUE;
704 
705 	*pds3db = ds3db;
706 	return S_OK;
707 }
708 
IDirectSound3DBufferImpl_Destroy(IDirectSound3DBufferImpl * pds3db)709 HRESULT IDirectSound3DBufferImpl_Destroy(
710     IDirectSound3DBufferImpl *pds3db)
711 {
712     TRACE("(%p)\n",pds3db);
713 
714     while (IDirectSound3DBufferImpl_Release((LPDIRECTSOUND3DBUFFER)pds3db) > 0);
715 
716     return S_OK;
717 }
718 
719 /*******************************************************************************
720  *	      IDirectSound3DListener
721  */
722 
723 /* IUnknown methods */
IDirectSound3DListenerImpl_QueryInterface(LPDIRECTSOUND3DLISTENER iface,REFIID riid,LPVOID * ppobj)724 static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
725 	LPDIRECTSOUND3DLISTENER iface, REFIID riid, LPVOID *ppobj)
726 {
727 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
728 
729 	TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
730 
731 	if (ppobj == NULL) {
732 		WARN("invalid parameter\n");
733 		return E_INVALIDARG;
734 	}
735 
736 	*ppobj = NULL;  /* assume failure */
737 
738 	if ( IsEqualGUID(riid, &IID_IUnknown) ||
739 	     IsEqualGUID(riid, &IID_IDirectSound3DListener ) ) {
740                 IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This);
741 		*ppobj = This;
742 		return S_OK;
743 	}
744 
745 	if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
746                 *ppobj = &This->device->primary->IDirectSoundBuffer8_iface;
747                 IDirectSoundBuffer8_AddRef(&This->device->primary->IDirectSoundBuffer8_iface);
748                 return S_OK;
749 	}
750 
751         FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
752 	return E_NOINTERFACE;
753 }
754 
IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)755 static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
756 {
757     IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
758     ULONG ref = InterlockedIncrement(&(This->ref));
759 
760     TRACE("(%p) ref was %d\n", This, ref - 1);
761 
762     if(ref == 1)
763         InterlockedIncrement(&This->device->primary->numIfaces);
764 
765     return ref;
766 }
767 
IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)768 static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
769 {
770     IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
771     ULONG ref = InterlockedDecrement(&(This->ref));
772     TRACE("(%p) ref was %d\n", This, ref + 1);
773 
774     if (!ref) {
775         This->device->listener = 0;
776         if (!InterlockedDecrement(&This->device->primary->numIfaces))
777             primarybuffer_destroy(This->device->primary);
778         HeapFree(GetProcessHeap(), 0, This);
779         TRACE("(%p) released\n", This);
780     }
781     return ref;
782 }
783 
784 /* IDirectSound3DListener methods */
IDirectSound3DListenerImpl_GetAllParameter(LPDIRECTSOUND3DLISTENER iface,LPDS3DLISTENER lpDS3DL)785 static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
786 	LPDIRECTSOUND3DLISTENER iface,
787 	LPDS3DLISTENER lpDS3DL)
788 {
789 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
790 	TRACE("(%p,%p)\n",This,lpDS3DL);
791 
792 	if (lpDS3DL == NULL) {
793 		WARN("invalid parameter: lpDS3DL == NULL\n");
794 		return DSERR_INVALIDPARAM;
795 	}
796 
797 	if (lpDS3DL->dwSize < sizeof(*lpDS3DL)) {
798 		WARN("invalid parameter: lpDS3DL->dwSize = %d\n",lpDS3DL->dwSize);
799 		return DSERR_INVALIDPARAM;
800 	}
801 
802 	TRACE("returning: all parameters\n");
803 	*lpDS3DL = This->device->ds3dl;
804 	return DS_OK;
805 }
806 
IDirectSound3DListenerImpl_GetDistanceFactor(LPDIRECTSOUND3DLISTENER iface,LPD3DVALUE lpfDistanceFactor)807 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
808 	LPDIRECTSOUND3DLISTENER iface,
809 	LPD3DVALUE lpfDistanceFactor)
810 {
811 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
812 	TRACE("returning: Distance Factor = %f\n", This->device->ds3dl.flDistanceFactor);
813 	*lpfDistanceFactor = This->device->ds3dl.flDistanceFactor;
814 	return DS_OK;
815 }
816 
IDirectSound3DListenerImpl_GetDopplerFactor(LPDIRECTSOUND3DLISTENER iface,LPD3DVALUE lpfDopplerFactor)817 static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
818 	LPDIRECTSOUND3DLISTENER iface,
819 	LPD3DVALUE lpfDopplerFactor)
820 {
821 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
822 	TRACE("returning: Doppler Factor = %f\n", This->device->ds3dl.flDopplerFactor);
823 	*lpfDopplerFactor = This->device->ds3dl.flDopplerFactor;
824 	return DS_OK;
825 }
826 
IDirectSound3DListenerImpl_GetOrientation(LPDIRECTSOUND3DLISTENER iface,LPD3DVECTOR lpvOrientFront,LPD3DVECTOR lpvOrientTop)827 static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
828 	LPDIRECTSOUND3DLISTENER iface,
829 	LPD3DVECTOR lpvOrientFront,
830 	LPD3DVECTOR lpvOrientTop)
831 {
832 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
833 	TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->device->ds3dl.vOrientFront.x,
834 	This->device->ds3dl.vOrientFront.y, This->device->ds3dl.vOrientFront.z, This->device->ds3dl.vOrientTop.x, This->device->ds3dl.vOrientTop.y,
835 	This->device->ds3dl.vOrientTop.z);
836 	*lpvOrientFront = This->device->ds3dl.vOrientFront;
837 	*lpvOrientTop = This->device->ds3dl.vOrientTop;
838 	return DS_OK;
839 }
840 
IDirectSound3DListenerImpl_GetPosition(LPDIRECTSOUND3DLISTENER iface,LPD3DVECTOR lpvPosition)841 static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
842 	LPDIRECTSOUND3DLISTENER iface,
843 	LPD3DVECTOR lpvPosition)
844 {
845 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
846 	TRACE("returning: Position vector = (%f,%f,%f)\n", This->device->ds3dl.vPosition.x, This->device->ds3dl.vPosition.y, This->device->ds3dl.vPosition.z);
847 	*lpvPosition = This->device->ds3dl.vPosition;
848 	return DS_OK;
849 }
850 
IDirectSound3DListenerImpl_GetRolloffFactor(LPDIRECTSOUND3DLISTENER iface,LPD3DVALUE lpfRolloffFactor)851 static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
852 	LPDIRECTSOUND3DLISTENER iface,
853 	LPD3DVALUE lpfRolloffFactor)
854 {
855 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
856 	TRACE("returning: RolloffFactor = %f\n", This->device->ds3dl.flRolloffFactor);
857 	*lpfRolloffFactor = This->device->ds3dl.flRolloffFactor;
858 	return DS_OK;
859 }
860 
IDirectSound3DListenerImpl_GetVelocity(LPDIRECTSOUND3DLISTENER iface,LPD3DVECTOR lpvVelocity)861 static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
862 	LPDIRECTSOUND3DLISTENER iface,
863 	LPD3DVECTOR lpvVelocity)
864 {
865 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
866 	TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->device->ds3dl.vVelocity.x, This->device->ds3dl.vVelocity.y, This->device->ds3dl.vVelocity.z);
867 	*lpvVelocity = This->device->ds3dl.vVelocity;
868 	return DS_OK;
869 }
870 
IDirectSound3DListenerImpl_SetAllParameters(LPDIRECTSOUND3DLISTENER iface,LPCDS3DLISTENER lpcDS3DL,DWORD dwApply)871 static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
872 	LPDIRECTSOUND3DLISTENER iface,
873 	LPCDS3DLISTENER lpcDS3DL,
874 	DWORD dwApply)
875 {
876 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
877 	TRACE("setting: all parameters; dwApply = %d\n", dwApply);
878 	This->device->ds3dl = *lpcDS3DL;
879 	if (dwApply == DS3D_IMMEDIATE)
880 	{
881 		This->device->ds3dl_need_recalc = FALSE;
882 		DSOUND_ChangeListener(This);
883 	}
884 	This->device->ds3dl_need_recalc = TRUE;
885 	return DS_OK;
886 }
887 
IDirectSound3DListenerImpl_SetDistanceFactor(LPDIRECTSOUND3DLISTENER iface,D3DVALUE fDistanceFactor,DWORD dwApply)888 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
889 	LPDIRECTSOUND3DLISTENER iface,
890 	D3DVALUE fDistanceFactor,
891 	DWORD dwApply)
892 {
893 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
894 	TRACE("setting: Distance Factor = %f; dwApply = %d\n", fDistanceFactor, dwApply);
895 	This->device->ds3dl.flDistanceFactor = fDistanceFactor;
896 	if (dwApply == DS3D_IMMEDIATE)
897 	{
898 		This->device->ds3dl_need_recalc = FALSE;
899 		DSOUND_ChangeListener(This);
900 	}
901 	This->device->ds3dl_need_recalc = TRUE;
902 	return DS_OK;
903 }
904 
IDirectSound3DListenerImpl_SetDopplerFactor(LPDIRECTSOUND3DLISTENER iface,D3DVALUE fDopplerFactor,DWORD dwApply)905 static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
906 	LPDIRECTSOUND3DLISTENER iface,
907 	D3DVALUE fDopplerFactor,
908 	DWORD dwApply)
909 {
910 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
911 	TRACE("setting: Doppler Factor = %f; dwApply = %d\n", fDopplerFactor, dwApply);
912 	This->device->ds3dl.flDopplerFactor = fDopplerFactor;
913 	if (dwApply == DS3D_IMMEDIATE)
914 	{
915 		This->device->ds3dl_need_recalc = FALSE;
916 		DSOUND_ChangeListener(This);
917 	}
918 	This->device->ds3dl_need_recalc = TRUE;
919 	return DS_OK;
920 }
921 
IDirectSound3DListenerImpl_SetOrientation(LPDIRECTSOUND3DLISTENER iface,D3DVALUE xFront,D3DVALUE yFront,D3DVALUE zFront,D3DVALUE xTop,D3DVALUE yTop,D3DVALUE zTop,DWORD dwApply)922 static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
923 	LPDIRECTSOUND3DLISTENER iface,
924 	D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront,
925 	D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop,
926 	DWORD dwApply)
927 {
928 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
929 	TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %d\n",
930 	xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
931 	This->device->ds3dl.vOrientFront.x = xFront;
932 	This->device->ds3dl.vOrientFront.y = yFront;
933 	This->device->ds3dl.vOrientFront.z = zFront;
934 	This->device->ds3dl.vOrientTop.x = xTop;
935 	This->device->ds3dl.vOrientTop.y = yTop;
936 	This->device->ds3dl.vOrientTop.z = zTop;
937 	if (dwApply == DS3D_IMMEDIATE)
938 	{
939 		This->device->ds3dl_need_recalc = FALSE;
940 		DSOUND_ChangeListener(This);
941 	}
942 	This->device->ds3dl_need_recalc = TRUE;
943 	return DS_OK;
944 }
945 
IDirectSound3DListenerImpl_SetPosition(LPDIRECTSOUND3DLISTENER iface,D3DVALUE x,D3DVALUE y,D3DVALUE z,DWORD dwApply)946 static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
947 	LPDIRECTSOUND3DLISTENER iface,
948 	D3DVALUE x, D3DVALUE y, D3DVALUE z,
949 	DWORD dwApply)
950 {
951 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
952 	TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
953 	This->device->ds3dl.vPosition.x = x;
954 	This->device->ds3dl.vPosition.y = y;
955 	This->device->ds3dl.vPosition.z = z;
956 	if (dwApply == DS3D_IMMEDIATE)
957 	{
958 		This->device->ds3dl_need_recalc = FALSE;
959 		DSOUND_ChangeListener(This);
960 	}
961 	This->device->ds3dl_need_recalc = TRUE;
962 	return DS_OK;
963 }
964 
IDirectSound3DListenerImpl_SetRolloffFactor(LPDIRECTSOUND3DLISTENER iface,D3DVALUE fRolloffFactor,DWORD dwApply)965 static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
966 	LPDIRECTSOUND3DLISTENER iface,
967 	D3DVALUE fRolloffFactor,
968 	DWORD dwApply)
969 {
970 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
971 	TRACE("setting: Rolloff Factor = %f; dwApply = %d\n", fRolloffFactor, dwApply);
972 	This->device->ds3dl.flRolloffFactor = fRolloffFactor;
973 	if (dwApply == DS3D_IMMEDIATE)
974 	{
975 		This->device->ds3dl_need_recalc = FALSE;
976 		DSOUND_ChangeListener(This);
977 	}
978 	This->device->ds3dl_need_recalc = TRUE;
979 	return DS_OK;
980 }
981 
IDirectSound3DListenerImpl_SetVelocity(LPDIRECTSOUND3DLISTENER iface,D3DVALUE x,D3DVALUE y,D3DVALUE z,DWORD dwApply)982 static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
983 	LPDIRECTSOUND3DLISTENER iface,
984 	D3DVALUE x, D3DVALUE y, D3DVALUE z,
985 	DWORD dwApply)
986 {
987 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
988 	TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply);
989 	This->device->ds3dl.vVelocity.x = x;
990 	This->device->ds3dl.vVelocity.y = y;
991 	This->device->ds3dl.vVelocity.z = z;
992 	if (dwApply == DS3D_IMMEDIATE)
993 	{
994 		This->device->ds3dl_need_recalc = FALSE;
995 		DSOUND_ChangeListener(This);
996 	}
997 	This->device->ds3dl_need_recalc = TRUE;
998 	return DS_OK;
999 }
1000 
IDirectSound3DListenerImpl_CommitDeferredSettings(LPDIRECTSOUND3DLISTENER iface)1001 static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
1002 	LPDIRECTSOUND3DLISTENER iface)
1003 {
1004 	IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface;
1005 	TRACE("\n");
1006 	DSOUND_ChangeListener(This);
1007 	return DS_OK;
1008 }
1009 
1010 static const IDirectSound3DListenerVtbl ds3dlvt =
1011 {
1012 	/* IUnknown methods */
1013 	IDirectSound3DListenerImpl_QueryInterface,
1014 	IDirectSound3DListenerImpl_AddRef,
1015 	IDirectSound3DListenerImpl_Release,
1016 	/* IDirectSound3DListener methods */
1017 	IDirectSound3DListenerImpl_GetAllParameter,
1018 	IDirectSound3DListenerImpl_GetDistanceFactor,
1019 	IDirectSound3DListenerImpl_GetDopplerFactor,
1020 	IDirectSound3DListenerImpl_GetOrientation,
1021 	IDirectSound3DListenerImpl_GetPosition,
1022 	IDirectSound3DListenerImpl_GetRolloffFactor,
1023 	IDirectSound3DListenerImpl_GetVelocity,
1024 	IDirectSound3DListenerImpl_SetAllParameters,
1025 	IDirectSound3DListenerImpl_SetDistanceFactor,
1026 	IDirectSound3DListenerImpl_SetDopplerFactor,
1027 	IDirectSound3DListenerImpl_SetOrientation,
1028 	IDirectSound3DListenerImpl_SetPosition,
1029 	IDirectSound3DListenerImpl_SetRolloffFactor,
1030 	IDirectSound3DListenerImpl_SetVelocity,
1031 	IDirectSound3DListenerImpl_CommitDeferredSettings,
1032 };
1033 
IDirectSound3DListenerImpl_Create(DirectSoundDevice * device,IDirectSound3DListenerImpl ** ppdsl)1034 HRESULT IDirectSound3DListenerImpl_Create(
1035 	DirectSoundDevice * device,
1036 	IDirectSound3DListenerImpl ** ppdsl)
1037 {
1038 	IDirectSound3DListenerImpl *pdsl;
1039 	TRACE("(%p,%p)\n",device,ppdsl);
1040 
1041 	pdsl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*pdsl));
1042 
1043 	if (pdsl == NULL) {
1044 		WARN("out of memory\n");
1045 		*ppdsl = 0;
1046 		return DSERR_OUTOFMEMORY;
1047 	}
1048 
1049 	pdsl->ref = 0;
1050 	pdsl->lpVtbl = &ds3dlvt;
1051 
1052 	pdsl->device = device;
1053 
1054 	pdsl->device->ds3dl.dwSize = sizeof(DS3DLISTENER);
1055 	pdsl->device->ds3dl.vPosition.x = 0.0;
1056 	pdsl->device->ds3dl.vPosition.y = 0.0;
1057 	pdsl->device->ds3dl.vPosition.z = 0.0;
1058 	pdsl->device->ds3dl.vVelocity.x = 0.0;
1059 	pdsl->device->ds3dl.vVelocity.y = 0.0;
1060 	pdsl->device->ds3dl.vVelocity.z = 0.0;
1061 	pdsl->device->ds3dl.vOrientFront.x = 0.0;
1062 	pdsl->device->ds3dl.vOrientFront.y = 0.0;
1063 	pdsl->device->ds3dl.vOrientFront.z = 1.0;
1064 	pdsl->device->ds3dl.vOrientTop.x = 0.0;
1065 	pdsl->device->ds3dl.vOrientTop.y = 1.0;
1066 	pdsl->device->ds3dl.vOrientTop.z = 0.0;
1067 	pdsl->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
1068 	pdsl->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
1069 	pdsl->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
1070 
1071 	pdsl->device->ds3dl_need_recalc = TRUE;
1072 
1073 	*ppdsl = pdsl;
1074 	return S_OK;
1075 }
1076