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) */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 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 285 static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb) 286 { 287 TRACE("(%p)\n",dsb); 288 289 DSOUND_Calc3DBuffer(dsb); 290 } 291 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 */ 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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