1 /* DirectSound COM interface
3 * Copyright 2009 Maarten Lankhorst
5 * Some code taken from the original dsound-openal implementation
6 * Copyright 2007-2009 Chris Robinson
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.
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.
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
32 #include <devpropdef.h>
34 #include "dsound_private.h"
37 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName
, 0xa45c254e,0xdf1c,0x4efd,0x80,0x20,0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
39 DEFINE_GUID(CLSID_DirectSoundPrivate
,0x11ab3ec0,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
41 DEFINE_GUID(DSPROPSETID_DirectSoundDevice
,0x84624f82,0x25ec,0x11d1,0xa4,0xd8,0x00,0xc0,0x4f,0xc2,0x8a,0xca);
43 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
44 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
47 #define DS_INCOMPLETE ((HRESULT)0x08780020)
50 #ifndef WAVE_FORMAT_IEEE_FLOAT
51 #define WAVE_FORMAT_IEEE_FLOAT 3
55 /* TODO: when bufferlost is set, return from all calls except initialize with
58 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
;
59 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
;
60 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
;
61 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
;
64 static inline DS8Buffer
*impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8
*iface
)
66 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
69 static inline DS8Buffer
*impl_from_IDirectSoundBuffer(IDirectSoundBuffer
*iface
)
71 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundBuffer8_iface
);
74 static inline DS8Buffer
*impl_from_IDirectSound3DBuffer(IDirectSound3DBuffer
*iface
)
76 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSound3DBuffer_iface
);
79 static inline DS8Buffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
81 return CONTAINING_RECORD(iface
, DS8Buffer
, IDirectSoundNotify_iface
);
84 static inline DS8Buffer
*impl_from_IKsPropertySet(IKsPropertySet
*iface
)
86 return CONTAINING_RECORD(iface
, DS8Buffer
, IKsPropertySet_iface
);
90 /* Should be called with critsect held and context set.. */
91 static void DS8Buffer_addnotify(DS8Buffer
*buf
)
93 DS8Primary
*prim
= buf
->primary
;
97 list
= prim
->notifies
;
98 for(i
= 0; i
< prim
->nnotifies
; ++i
)
102 ERR("Buffer %p already in notification list\n", buf
);
106 if(prim
->nnotifies
== prim
->sizenotifies
)
108 list
= HeapReAlloc(GetProcessHeap(), 0, list
, (prim
->nnotifies
+ 1) * sizeof(*list
));
110 prim
->sizenotifies
++;
112 list
[prim
->nnotifies
++] = buf
;
113 prim
->notifies
= list
;
117 static const char *get_fmtstr_PCM(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
119 out
->Format
= *format
;
120 out
->Format
.cbSize
= 0;
122 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
123 !BITFIELD_TEST(prim
->Exts
, EXT_MCFORMATS
))
125 WARN("Multi-channel not available\n");
129 if(format
->wBitsPerSample
== 8)
131 switch(format
->nChannels
)
133 case 1: return "AL_FORMAT_MONO8";
134 case 2: return "AL_FORMAT_STEREO8";
135 case 4: return "AL_FORMAT_QUAD8";
136 case 6: return "AL_FORMAT_51CHN8";
137 case 7: return "AL_FORMAT_61CHN8";
138 case 8: return "AL_FORMAT_71CHN8";
141 else if(format
->wBitsPerSample
== 16)
143 switch(format
->nChannels
)
145 case 1: return "AL_FORMAT_MONO16";
146 case 2: return "AL_FORMAT_STEREO16";
147 case 4: return "AL_FORMAT_QUAD16";
148 case 6: return "AL_FORMAT_51CHN16";
149 case 7: return "AL_FORMAT_61CHN16";
150 case 8: return "AL_FORMAT_71CHN16";
154 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
155 format
->wBitsPerSample
, format
->nChannels
);
159 static const char *get_fmtstr_FLOAT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
161 out
->Format
= *format
;
162 out
->Format
.cbSize
= 0;
164 if(out
->Format
.nChannels
!= 1 && out
->Format
.nChannels
!= 2 &&
165 !BITFIELD_TEST(prim
->Exts
, EXT_MCFORMATS
))
167 WARN("Multi-channel not available\n");
171 if(format
->wBitsPerSample
== 32 && BITFIELD_TEST(prim
->Exts
, EXT_FLOAT32
))
173 switch(format
->nChannels
)
175 case 1: return "AL_FORMAT_MONO_FLOAT32";
176 case 2: return "AL_FORMAT_STEREO_FLOAT32";
177 case 4: return "AL_FORMAT_QUAD32";
178 case 6: return "AL_FORMAT_51CHN32";
179 case 7: return "AL_FORMAT_61CHN32";
180 case 8: return "AL_FORMAT_71CHN32";
184 FIXME("Could not get OpenAL format (%d-bit, %d channels)\n",
185 format
->wBitsPerSample
, format
->nChannels
);
189 /* Speaker configs */
190 #define MONO SPEAKER_FRONT_CENTER
191 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
192 #define REAR (SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
193 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
194 #define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
195 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
196 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
198 static const char *get_fmtstr_EXT(const DS8Primary
*prim
, const WAVEFORMATEX
*format
, WAVEFORMATEXTENSIBLE
*out
)
200 *out
= *CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
201 out
->Format
.cbSize
= sizeof(*out
) - sizeof(out
->Format
);
203 if(!out
->Samples
.wValidBitsPerSample
)
204 out
->Samples
.wValidBitsPerSample
= out
->Format
.wBitsPerSample
;
205 else if(out
->Samples
.wValidBitsPerSample
> out
->Format
.wBitsPerSample
)
207 WARN("Invalid ValidBitsPerSample (%u > %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
210 else if(out
->Samples
.wValidBitsPerSample
< out
->Format
.wBitsPerSample
)
212 FIXME("Padded samples not supported (%u of %u)\n", out
->Samples
.wValidBitsPerSample
, out
->Format
.wBitsPerSample
);
216 if(out
->dwChannelMask
!= MONO
&& out
->dwChannelMask
!= STEREO
&&
217 !BITFIELD_TEST(prim
->Exts
, EXT_MCFORMATS
))
219 WARN("Multi-channel not available\n");
223 if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
225 if(out
->Samples
.wValidBitsPerSample
== 8)
227 switch(out
->dwChannelMask
)
229 case MONO
: return "AL_FORMAT_MONO8";
230 case STEREO
: return "AL_FORMAT_STEREO8";
231 case REAR
: return "AL_FORMAT_REAR8";
232 case QUAD
: return "AL_FORMAT_QUAD8";
233 case X5DOT1
: return "AL_FORMAT_51CHN8";
234 case X6DOT1
: return "AL_FORMAT_61CHN8";
235 case X7DOT1
: return "AL_FORMAT_71CHN8";
238 else if(out
->Samples
.wValidBitsPerSample
== 16)
240 switch(out
->dwChannelMask
)
242 case MONO
: return "AL_FORMAT_MONO16";
243 case STEREO
: return "AL_FORMAT_STEREO16";
244 case REAR
: return "AL_FORMAT_REAR16";
245 case QUAD
: return "AL_FORMAT_QUAD16";
246 case X5DOT1
: return "AL_FORMAT_51CHN16";
247 case X6DOT1
: return "AL_FORMAT_61CHN16";
248 case X7DOT1
: return "AL_FORMAT_71CHN16";
252 FIXME("Could not get OpenAL PCM format (%d-bit, channelmask %#lx)\n",
253 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
256 else if(IsEqualGUID(&out
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
) &&
257 BITFIELD_TEST(prim
->Exts
, EXT_FLOAT32
))
259 if(out
->Samples
.wValidBitsPerSample
== 32)
261 switch(out
->dwChannelMask
)
263 case MONO
: return "AL_FORMAT_MONO_FLOAT32";
264 case STEREO
: return "AL_FORMAT_STEREO_FLOAT32";
265 case REAR
: return "AL_FORMAT_REAR32";
266 case QUAD
: return "AL_FORMAT_QUAD32";
267 case X5DOT1
: return "AL_FORMAT_51CHN32";
268 case X6DOT1
: return "AL_FORMAT_61CHN32";
269 case X7DOT1
: return "AL_FORMAT_71CHN32";
274 WARN("Invalid float bits: %u\n", out
->Samples
.wValidBitsPerSample
);
278 FIXME("Could not get OpenAL float format (%d-bit, channelmask %#lx)\n",
279 out
->Samples
.wValidBitsPerSample
, out
->dwChannelMask
);
282 else if(!IsEqualGUID(&out
->SubFormat
, &GUID_NULL
))
283 ERR("Unhandled extensible format: %s\n", debugstr_guid(&out
->SubFormat
));
287 static void DS8Data_Release(DS8Data
*This
);
288 static HRESULT
DS8Data_Create(DS8Data
**ppv
, const DSBUFFERDESC
*desc
, DS8Primary
*prim
)
290 HRESULT hr
= DSERR_INVALIDPARAM
;
291 const WAVEFORMATEX
*format
;
292 const char *fmt_str
= NULL
;
296 format
= desc
->lpwfxFormat
;
297 TRACE("Requested buffer format:\n"
298 " FormatTag = 0x%04x\n"
300 " SamplesPerSec = %lu\n"
301 " AvgBytesPerSec = %lu\n"
303 " BitsPerSample = %d\n",
304 format
->wFormatTag
, format
->nChannels
,
305 format
->nSamplesPerSec
, format
->nAvgBytesPerSec
,
306 format
->nBlockAlign
, format
->wBitsPerSample
);
308 if(format
->nChannels
<= 0)
310 WARN("Invalid Channels %d\n", format
->nChannels
);
311 return DSERR_INVALIDPARAM
;
313 if(format
->nSamplesPerSec
< DSBFREQUENCY_MIN
|| format
->nSamplesPerSec
> DSBFREQUENCY_MAX
)
315 WARN("Invalid SamplesPerSec %lu\n", format
->nSamplesPerSec
);
316 return DSERR_INVALIDPARAM
;
318 if(format
->nBlockAlign
<= 0)
320 WARN("Invalid BlockAlign %d\n", format
->nBlockAlign
);
321 return DSERR_INVALIDPARAM
;
323 if(format
->wBitsPerSample
== 0 || (format
->wBitsPerSample
%8) != 0)
325 WARN("Invalid BitsPerSample %d\n", format
->wBitsPerSample
);
326 return DSERR_INVALIDPARAM
;
328 if(format
->nBlockAlign
!= format
->nChannels
*format
->wBitsPerSample
/8)
330 WARN("Invalid BlockAlign %d (expected %u = %u*%u/8)\n",
331 format
->nBlockAlign
, format
->nChannels
*format
->wBitsPerSample
/8,
332 format
->nChannels
, format
->wBitsPerSample
);
333 return DSERR_INVALIDPARAM
;
335 if(format
->nAvgBytesPerSec
!= format
->nBlockAlign
*format
->nSamplesPerSec
)
337 WARN("Invalid AvgBytesPerSec %lu (expected %lu = %lu*%u)\n",
338 format
->nAvgBytesPerSec
, format
->nSamplesPerSec
*format
->nBlockAlign
,
339 format
->nSamplesPerSec
, format
->nBlockAlign
);
340 return DSERR_INVALIDPARAM
;
343 if((desc
->dwFlags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
)) == (DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
))
345 WARN("Hardware and software location requested\n");
346 return DSERR_INVALIDPARAM
;
349 buf_size
= desc
->dwBufferBytes
+ format
->nBlockAlign
- 1;
350 buf_size
-= buf_size
%format
->nBlockAlign
;
351 if(buf_size
< DSBSIZE_MIN
) return DSERR_BUFFERTOOSMALL
;
352 if(buf_size
> DSBSIZE_MAX
) return DSERR_INVALIDPARAM
;
354 /* Generate a new buffer. Supporting the DSBCAPS_LOC* flags properly
355 * will need the EAX-RAM extension. Currently, we just tell the app it
356 * gets what it wanted. */
357 if(!BITFIELD_TEST(prim
->Exts
, SOFTX_MAP_BUFFER
))
358 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
)+buf_size
);
360 pBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pBuffer
));
361 if(!pBuffer
) return E_OUTOFMEMORY
;
363 pBuffer
->primary
= prim
;
365 pBuffer
->dsbflags
= desc
->dwFlags
;
366 if(!(pBuffer
->dsbflags
&(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCDEFER
)))
367 pBuffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
368 pBuffer
->buf_size
= buf_size
;
370 if(format
->wFormatTag
== WAVE_FORMAT_PCM
)
371 fmt_str
= get_fmtstr_PCM(prim
, format
, &pBuffer
->format
);
372 else if(format
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
373 fmt_str
= get_fmtstr_FLOAT(prim
, format
, &pBuffer
->format
);
374 else if(format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
376 const WAVEFORMATEXTENSIBLE
*wfe
;
378 if(format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
) &&
379 format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
382 wfe
= CONTAINING_RECORD(format
, const WAVEFORMATEXTENSIBLE
, Format
);
383 TRACE("Extensible values:\n"
385 " ChannelMask = 0x%lx\n"
387 wfe
->Samples
.wReserved
, wfe
->dwChannelMask
,
388 debugstr_guid(&wfe
->SubFormat
));
390 fmt_str
= get_fmtstr_EXT(prim
, format
, &pBuffer
->format
);
393 ERR("Unhandled formattag 0x%04x\n", format
->wFormatTag
);
394 if(!fmt_str
) goto fail
;
397 pBuffer
->buf_format
= alGetEnumValue(fmt_str
);
398 if(alGetError() != AL_NO_ERROR
|| pBuffer
->buf_format
== 0 ||
399 pBuffer
->buf_format
== -1)
401 WARN("Could not get OpenAL format from %s\n", fmt_str
);
406 if(!BITFIELD_TEST(prim
->Exts
, SOFTX_MAP_BUFFER
))
408 pBuffer
->data
= (BYTE
*)(pBuffer
+1);
410 alGenBuffers(1, &pBuffer
->bid
);
415 const ALbitfieldSOFT map_bits
= AL_MAP_READ_BIT_SOFT
| AL_MAP_WRITE_BIT_SOFT
|
416 AL_MAP_PERSISTENT_BIT_SOFT
;
417 alGenBuffers(1, &pBuffer
->bid
);
418 alBufferStorageSOFT(pBuffer
->bid
, pBuffer
->buf_format
, NULL
, pBuffer
->buf_size
,
419 pBuffer
->format
.Format
.nSamplesPerSec
, map_bits
);
420 pBuffer
->data
= alMapBufferSOFT(pBuffer
->bid
, 0, pBuffer
->buf_size
, map_bits
);
423 if(!pBuffer
->data
) goto fail
;
430 DS8Data_Release(pBuffer
);
434 static void DS8Data_AddRef(DS8Data
*data
)
436 InterlockedIncrement(&data
->ref
);
439 /* This function is always called with the device lock held */
440 static void DS8Data_Release(DS8Data
*This
)
442 if(InterlockedDecrement(&This
->ref
)) return;
444 TRACE("Deleting %p\n", This
);
447 DS8Primary
*prim
= This
->primary
;
448 if(BITFIELD_TEST(prim
->Exts
, SOFTX_MAP_BUFFER
))
449 alUnmapBufferSOFT(This
->bid
);
450 alDeleteBuffers(1, &This
->bid
);
453 HeapFree(GetProcessHeap(), 0, This
);
457 HRESULT
DS8Buffer_Create(DS8Buffer
**ppv
, DS8Primary
*prim
, IDirectSoundBuffer
*orig
, BOOL prim_emu
)
459 DS8Buffer
*This
= NULL
;
464 EnterCriticalSection(prim
->crst
);
467 This
= &prim
->writable_buf
;
468 memset(This
, 0, sizeof(*This
));
470 else for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
472 if(prim
->BufferGroups
[i
].FreeBuffers
)
474 int idx
= CTZ64(prim
->BufferGroups
[i
].FreeBuffers
);
475 This
= prim
->BufferGroups
[i
].Buffers
+ idx
;
476 memset(This
, 0, sizeof(*This
));
477 prim
->BufferGroups
[i
].FreeBuffers
&= ~(U64(1) << idx
);
481 LeaveCriticalSection(prim
->crst
);
484 WARN("Out of buffers\n");
485 return DSERR_ALLOCATED
;
488 This
->IDirectSoundBuffer8_iface
.lpVtbl
= &DS8Buffer_Vtbl
;
489 This
->IDirectSound3DBuffer_iface
.lpVtbl
= &DS8Buffer3d_Vtbl
;
490 This
->IDirectSoundNotify_iface
.lpVtbl
= &DS8BufferNot_Vtbl
;
491 This
->IKsPropertySet_iface
.lpVtbl
= &DS8BufferProp_Vtbl
;
493 This
->primary
= prim
;
494 This
->ctx
= prim
->ctx
;
495 This
->crst
= prim
->crst
;
496 This
->ref
= This
->all_ref
= 1;
500 DS8Buffer
*org
= impl_from_IDirectSoundBuffer(orig
);
501 hr
= DSERR_BUFFERLOST
;
504 DS8Data_AddRef(org
->buffer
);
505 This
->buffer
= org
->buffer
;
508 /* Disable until initialized.. */
509 This
->ds3dmode
= DS3DMODE_DISABLE
;
515 DS8Buffer_Destroy(This
);
519 void DS8Buffer_Destroy(DS8Buffer
*This
)
521 DS8Primary
*prim
= This
->primary
;
525 TRACE("Destroying %p\n", This
);
527 EnterCriticalSection(prim
->crst
);
528 /* Remove from list, if in list */
529 for(i
= 0;i
< prim
->nnotifies
;++i
)
531 if(This
== prim
->notifies
[i
])
533 prim
->notifies
[i
] = prim
->notifies
[--prim
->nnotifies
];
538 setALContext(This
->ctx
);
541 alSourceStop(This
->source
);
542 alSourcei(This
->source
, AL_BUFFER
, 0);
545 prim
->sources
->ids
[prim
->sources
->avail_num
++] = This
->source
;
548 if(This
->stream_bids
[0])
549 alDeleteBuffers(QBUFFERS
, This
->stream_bids
);
551 alDeleteFilters(2, This
->filter
);
554 DS8Data_Release(This
->buffer
);
558 HeapFree(GetProcessHeap(), 0, This
->notify
);
560 for(i
= 0;i
< prim
->NumBufferGroups
;++i
)
562 DWORD_PTR idx
= This
- prim
->BufferGroups
[i
].Buffers
;
565 prim
->BufferGroups
[i
].FreeBuffers
|= U64(1) << idx
;
570 LeaveCriticalSection(prim
->crst
);
574 static HRESULT WINAPI
DS8Buffer_QueryInterface(IDirectSoundBuffer8
*iface
, REFIID riid
, void **ppv
)
576 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
578 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
581 if(IsEqualIID(riid
, &IID_IUnknown
))
582 *ppv
= &This
->IDirectSoundBuffer8_iface
;
583 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer
))
584 *ppv
= &This
->IDirectSoundBuffer8_iface
;
585 else if(IsEqualIID(riid
, &IID_IDirectSoundBuffer8
))
587 if(This
->primary
->parent
->is_8
)
588 *ppv
= &This
->IDirectSoundBuffer8_iface
;
590 else if(IsEqualIID(riid
, &IID_IDirectSound3DBuffer
))
592 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
593 *ppv
= &This
->IDirectSound3DBuffer_iface
;
595 else if(IsEqualIID(riid
, &IID_IDirectSoundNotify
))
597 if((This
->buffer
->dsbflags
&DSBCAPS_CTRLPOSITIONNOTIFY
))
598 *ppv
= &This
->IDirectSoundNotify_iface
;
600 else if(IsEqualIID(riid
, &IID_IKsPropertySet
))
601 *ppv
= &This
->IKsPropertySet_iface
;
603 FIXME("Unhandled GUID: %s\n", debugstr_guid(riid
));
607 IUnknown_AddRef((IUnknown
*)*ppv
);
611 return E_NOINTERFACE
;
614 static ULONG WINAPI
DS8Buffer_AddRef(IDirectSoundBuffer8
*iface
)
616 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
619 InterlockedIncrement(&This
->all_ref
);
620 ret
= InterlockedIncrement(&This
->ref
);
621 TRACE("new refcount %ld\n", ret
);
626 static ULONG WINAPI
DS8Buffer_Release(IDirectSoundBuffer8
*iface
)
628 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
631 ret
= InterlockedDecrement(&This
->ref
);
632 TRACE("new refcount %ld\n", ret
);
633 if(InterlockedDecrement(&This
->all_ref
) == 0)
634 DS8Buffer_Destroy(This
);
639 static HRESULT WINAPI
DS8Buffer_GetCaps(IDirectSoundBuffer8
*iface
, DSBCAPS
*caps
)
641 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
643 TRACE("(%p)->(%p)\n", iface
, caps
);
645 if(!caps
|| caps
->dwSize
< sizeof(*caps
))
647 WARN("Invalid DSBCAPS (%p, %lu)\n", caps
, (caps
? caps
->dwSize
: 0));
648 return DSERR_INVALIDPARAM
;
651 caps
->dwFlags
= This
->buffer
->dsbflags
;
652 caps
->dwBufferBytes
= This
->buffer
->buf_size
;
653 caps
->dwUnlockTransferRate
= 4096;
654 caps
->dwPlayCpuOverhead
= 0;
658 HRESULT WINAPI
DS8Buffer_GetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD
*playpos
, DWORD
*curpos
)
660 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
661 ALsizei writecursor
, pos
;
664 TRACE("(%p)->(%p, %p)\n", iface
, playpos
, curpos
);
667 if(This
->segsize
!= 0)
669 ALint queued
= QBUFFERS
;
673 EnterCriticalSection(This
->crst
);
675 setALContext(This
->ctx
);
676 alGetSourcei(This
->source
, AL_BUFFERS_QUEUED
, &queued
);
677 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
678 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
682 if(status
== AL_STOPPED
)
683 pos
= This
->segsize
*queued
+ This
->queue_base
;
685 pos
= ofs
+ This
->queue_base
;
686 if(pos
>= data
->buf_size
)
689 pos
%= data
->buf_size
;
690 else if(This
->isplaying
)
692 pos
= data
->buf_size
;
693 alSourceStop(This
->source
);
694 alSourcei(This
->source
, AL_BUFFER
, 0);
696 This
->isplaying
= FALSE
;
700 writecursor
= (This
->segsize
*QBUFFERS
+ pos
) % data
->buf_size
;
702 writecursor
= pos
% data
->buf_size
;
704 LeaveCriticalSection(This
->crst
);
708 const WAVEFORMATEX
*format
= &data
->format
.Format
;
712 setALContext(This
->ctx
);
713 alGetSourcei(This
->source
, AL_BYTE_OFFSET
, &ofs
);
714 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &status
);
718 /* AL_STOPPED means the source naturally reached its end, where
719 * DirectSound's position should be at the end (OpenAL reports a 0
720 * position). The Stop method correlates to pausing, which would put
721 * the source into an AL_PAUSED state and hold its current position.
723 pos
= (status
== AL_STOPPED
) ? data
->buf_size
: ofs
;
724 if(status
== AL_PLAYING
)
726 writecursor
= format
->nSamplesPerSec
/ This
->primary
->refresh
;
727 writecursor
*= format
->nBlockAlign
;
731 writecursor
= (writecursor
+ pos
) % data
->buf_size
;
733 TRACE("%p Play pos = %u, write pos = %u\n", This
, pos
, writecursor
);
735 if(pos
> data
->buf_size
)
737 ERR("playpos > buf_size\n");
738 pos
%= data
->buf_size
;
740 if(writecursor
>= data
->buf_size
)
742 ERR("writepos >= buf_size\n");
743 writecursor
%= data
->buf_size
;
746 if(playpos
) *playpos
= pos
;
747 if(curpos
) *curpos
= writecursor
;
752 static HRESULT WINAPI
DS8Buffer_GetFormat(IDirectSoundBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD allocated
, DWORD
*written
)
754 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
758 TRACE("(%p)->(%p, %lu, %p)\n", iface
, wfx
, allocated
, written
);
762 WARN("Cannot report format or format size\n");
763 return DSERR_INVALIDPARAM
;
766 size
= sizeof(This
->buffer
->format
.Format
) + This
->buffer
->format
.Format
.cbSize
;
770 hr
= DSERR_INVALIDPARAM
;
772 memcpy(wfx
, &This
->buffer
->format
.Format
, size
);
780 static HRESULT WINAPI
DS8Buffer_GetVolume(IDirectSoundBuffer8
*iface
, LONG
*vol
)
782 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
785 TRACE("(%p)->(%p)\n", iface
, vol
);
789 WARN("Invalid pointer\n");
790 return DSERR_INVALIDPARAM
;
793 hr
= DSERR_CONTROLUNAVAIL
;
794 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
795 WARN("Volume control not set\n");
800 setALContext(This
->ctx
);
801 alGetSourcef(This
->source
, AL_GAIN
, &gain
);
805 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
812 static HRESULT WINAPI
DS8Buffer_GetPan(IDirectSoundBuffer8
*iface
, LONG
*pan
)
814 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
817 TRACE("(%p)->(%p)\n", iface
, pan
);
821 WARN("Invalid pointer\n");
822 return DSERR_INVALIDPARAM
;
825 hr
= DSERR_CONTROLUNAVAIL
;
826 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
827 WARN("Panning control not set\n");
830 if((This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
836 setALContext(This
->ctx
);
837 alGetSourcefv(This
->source
, AL_POSITION
, pos
);
841 *pan
= clampI((LONG
)((pos
[0]+0.5f
)*(DSBPAN_RIGHT
-DSBPAN_LEFT
) + 0.5f
) + DSBPAN_LEFT
,
842 DSBPAN_LEFT
, DSBPAN_RIGHT
);
850 static HRESULT WINAPI
DS8Buffer_GetFrequency(IDirectSoundBuffer8
*iface
, DWORD
*freq
)
852 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
855 TRACE("(%p)->(%p)\n", iface
, freq
);
859 WARN("Invalid pointer\n");
860 return DSERR_INVALIDPARAM
;
863 hr
= DSERR_CONTROLUNAVAIL
;
864 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
865 WARN("Frequency control not set\n");
868 ALfloat pitch
= 1.0f
;
870 setALContext(This
->ctx
);
871 alGetSourcefv(This
->source
, AL_PITCH
, &pitch
);
875 *freq
= (DWORD
)(This
->buffer
->format
.Format
.nSamplesPerSec
* pitch
);
882 HRESULT WINAPI
DS8Buffer_GetStatus(IDirectSoundBuffer8
*iface
, DWORD
*status
)
884 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
885 ALint state
, looping
;
887 TRACE("(%p)->(%p)\n", iface
, status
);
891 WARN("Invalid pointer\n");
892 return DSERR_INVALIDPARAM
;
896 if(This
->segsize
== 0)
898 setALContext(This
->ctx
);
899 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
900 alGetSourcei(This
->source
, AL_LOOPING
, &looping
);
906 EnterCriticalSection(This
->crst
);
907 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
908 looping
= This
->islooping
;
909 LeaveCriticalSection(This
->crst
);
912 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
914 if((This
->buffer
->dsbflags
&DSBCAPS_LOCSOFTWARE
))
915 *status
|= DSBSTATUS_LOCSOFTWARE
;
916 else if((This
->buffer
->dsbflags
&DSBCAPS_LOCHARDWARE
))
917 *status
|= DSBSTATUS_LOCHARDWARE
;
919 if(state
== AL_PLAYING
)
920 *status
|= DSBSTATUS_PLAYING
| (looping
? DSBSTATUS_LOOPING
: 0);
922 TRACE("%p status = 0x%08lx\n", This
, *status
);
926 HRESULT WINAPI
DS8Buffer_Initialize(IDirectSoundBuffer8
*iface
, IDirectSound
*ds
, const DSBUFFERDESC
*desc
)
928 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
929 EAX20BUFFERPROPERTIES
*eaxbuffer
;
930 DS3DBUFFER
*ds3dbuffer
;
935 TRACE("(%p)->(%p, %p)\n", iface
, ds
, desc
);
937 EnterCriticalSection(This
->crst
);
938 setALContext(This
->ctx
);
940 hr
= DSERR_ALREADYINITIALIZED
;
941 if(This
->source
) goto out
;
943 prim
= This
->primary
;
946 hr
= DSERR_INVALIDPARAM
;
949 WARN("Missing DSound buffer description\n");
952 if(!desc
->lpwfxFormat
)
954 WARN("Missing buffer format (%p)\n", This
);
957 if((desc
->dwFlags
&DSBCAPS_CTRL3D
) && desc
->lpwfxFormat
->nChannels
!= 1)
959 if(prim
->parent
->is_8
)
961 /* DirectSoundBuffer8 objects aren't allowed non-mono 3D
963 WARN("Can't create multi-channel 3D buffers\n");
970 ERR("Multi-channel 3D sounds are not spatialized\n");
973 if((desc
->dwFlags
&DSBCAPS_CTRLPAN
) && desc
->lpwfxFormat
->nChannels
!= 1)
977 ERR("Panning for multi-channel buffers is not supported\n");
980 hr
= DS8Data_Create(&This
->buffer
, desc
, prim
);
981 if(FAILED(hr
)) goto out
;
984 if(data
->format
.Format
.wBitsPerSample
== 8)
985 memset(data
->data
, 0x80, data
->buf_size
);
987 memset(data
->data
, 0x00, data
->buf_size
);
991 if(!(data
->dsbflags
&DSBCAPS_STATIC
) && !BITFIELD_TEST(prim
->Exts
, SOFTX_MAP_BUFFER
))
993 This
->segsize
= (data
->format
.Format
.nAvgBytesPerSec
+prim
->refresh
-1) / prim
->refresh
;
994 This
->segsize
= clampI(This
->segsize
, data
->format
.Format
.nBlockAlign
, 2048);
995 This
->segsize
+= data
->format
.Format
.nBlockAlign
- 1;
996 This
->segsize
-= This
->segsize
%data
->format
.Format
.nBlockAlign
;
998 alGenBuffers(QBUFFERS
, This
->stream_bids
);
1002 hr
= DSERR_ALLOCATED
;
1003 if(!prim
->sources
->avail_num
)
1006 This
->source
= prim
->sources
->ids
[--(prim
->sources
->avail_num
)];
1007 alSourceRewind(This
->source
);
1008 alSourcef(This
->source
, AL_GAIN
, 1.0f
);
1009 alSourcef(This
->source
, AL_PITCH
, 1.0f
);
1012 ds3dbuffer
= &This
->params
;
1013 ds3dbuffer
->dwSize
= sizeof(This
->params
);
1014 ds3dbuffer
->vPosition
.x
= 0.0f
;
1015 ds3dbuffer
->vPosition
.y
= 0.0f
;
1016 ds3dbuffer
->vPosition
.z
= 0.0f
;
1017 ds3dbuffer
->vVelocity
.x
= 0.0f
;
1018 ds3dbuffer
->vVelocity
.y
= 0.0f
;
1019 ds3dbuffer
->vVelocity
.z
= 0.0f
;
1020 ds3dbuffer
->dwInsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1021 ds3dbuffer
->dwOutsideConeAngle
= DS3D_DEFAULTCONEANGLE
;
1022 ds3dbuffer
->vConeOrientation
.x
= 0.0f
;
1023 ds3dbuffer
->vConeOrientation
.y
= 0.0f
;
1024 ds3dbuffer
->vConeOrientation
.z
= 1.0f
;
1025 ds3dbuffer
->lConeOutsideVolume
= DS3D_DEFAULTCONEOUTSIDEVOLUME
;
1026 ds3dbuffer
->flMinDistance
= DS3D_DEFAULTMINDISTANCE
;
1027 ds3dbuffer
->flMaxDistance
= DS3D_DEFAULTMAXDISTANCE
;
1028 ds3dbuffer
->dwMode
= DS3DMODE_NORMAL
;
1029 eaxbuffer
= &This
->eax_prop
;
1030 eaxbuffer
->lDirect
= 0;
1031 eaxbuffer
->lDirectHF
= 0;
1032 eaxbuffer
->lRoom
= 0;
1033 eaxbuffer
->lRoomHF
= 0;
1034 eaxbuffer
->flRoomRolloffFactor
= 0.0f
;
1035 eaxbuffer
->lObstruction
= 0;
1036 eaxbuffer
->flObstructionLFRatio
= 0.25f
;
1037 eaxbuffer
->lOcclusion
= 0;
1038 eaxbuffer
->flOcclusionLFRatio
= 0.25f
;
1039 eaxbuffer
->flOcclusionRoomRatio
= 0.5f
;
1040 eaxbuffer
->lOutsideVolumeHF
= 0;
1041 eaxbuffer
->flAirAbsorptionFactor
= 0.0f
;
1042 eaxbuffer
->dwFlags
= EAXBUFFERFLAGS_DIRECTHFAUTO
| EAXBUFFERFLAGS_ROOMAUTO
|
1043 EAXBUFFERFLAGS_ROOMHFAUTO
;
1045 if((data
->dsbflags
&DSBCAPS_CTRL3D
))
1047 union BufferParamFlags dirty
= { 0 };
1049 if(BITFIELD_TEST(prim
->Exts
, EXT_EFX
))
1051 alGenFilters(2, This
->filter
);
1052 alFilteri(This
->filter
[0], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1053 alFilteri(This
->filter
[1], AL_FILTER_TYPE
, AL_FILTER_LOWPASS
);
1058 dirty
.bit
.cone_angles
= 1;
1059 dirty
.bit
.cone_orient
= 1;
1060 dirty
.bit
.cone_outsidevolume
= 1;
1061 dirty
.bit
.min_distance
= 1;
1062 dirty
.bit
.max_distance
= 1;
1064 if(BITFIELD_TEST(prim
->Exts
, EXT_EFX
))
1066 dirty
.bit
.dry_filter
= 1;
1067 dirty
.bit
.wet_filter
= 1;
1068 dirty
.bit
.room_rolloff
= 1;
1069 dirty
.bit
.cone_outsidevolumehf
= 1;
1070 dirty
.bit
.air_absorb
= 1;
1071 dirty
.bit
.flags
= 1;
1073 DS8Buffer_SetParams(This
, ds3dbuffer
, eaxbuffer
, dirty
.flags
);
1078 ALuint source
= This
->source
;
1080 /* Non-3D sources aren't distance attenuated */
1081 This
->ds3dmode
= DS3DMODE_DISABLE
;
1082 alSource3f(source
, AL_POSITION
, 0.0f
, 0.0f
, -1.0f
);
1083 alSource3f(source
, AL_VELOCITY
, 0.0f
, 0.0f
, 0.0f
);
1084 alSource3f(source
, AL_DIRECTION
, 0.0f
, 0.0f
, 0.0f
);
1085 alSourcef(source
, AL_CONE_OUTER_GAIN
, 1.0f
);
1086 alSourcef(source
, AL_REFERENCE_DISTANCE
, 1.0f
);
1087 alSourcef(source
, AL_MAX_DISTANCE
, 1000.0f
);
1088 alSourcef(source
, AL_ROLLOFF_FACTOR
, 0.0f
);
1089 alSourcei(source
, AL_CONE_INNER_ANGLE
, 360);
1090 alSourcei(source
, AL_CONE_OUTER_ANGLE
, 360);
1091 alSourcei(source
, AL_SOURCE_RELATIVE
, AL_TRUE
);
1092 if(BITFIELD_TEST(prim
->Exts
, EXT_EFX
))
1094 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, 0.0f
);
1095 alSourcef(source
, AL_CONE_OUTER_GAINHF
, 1.0f
);
1096 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, 0.0f
);
1097 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
, AL_TRUE
);
1098 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
, AL_TRUE
);
1099 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
, AL_TRUE
);
1100 alSourcei(source
, AL_DIRECT_FILTER
, AL_FILTER_NULL
);
1101 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, 0, 0, AL_FILTER_NULL
);
1103 if(BITFIELD_TEST(prim
->Exts
, SOFT_SOURCE_SPATIALIZE
))
1105 /* Set to auto so panning works for mono, and multi-channel works
1108 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
, AL_AUTO_SOFT
);
1116 LeaveCriticalSection(This
->crst
);
1121 static HRESULT WINAPI
DS8Buffer_Lock(IDirectSoundBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
1123 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1126 TRACE("(%p)->(%lu, %lu, %p, %p, %p, %p, 0x%lx)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
1130 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
1131 return DSERR_INVALIDPARAM
;
1136 if(ptr2
) *ptr2
= NULL
;
1139 if((flags
&DSBLOCK_FROMWRITECURSOR
))
1140 DS8Buffer_GetCurrentPosition(iface
, NULL
, &ofs
);
1141 else if(ofs
>= (DWORD
)This
->buffer
->buf_size
)
1143 WARN("Invalid ofs %lu\n", ofs
);
1144 return DSERR_INVALIDPARAM
;
1146 if((flags
&DSBLOCK_ENTIREBUFFER
))
1147 bytes
= This
->buffer
->buf_size
;
1148 else if(bytes
> (DWORD
)This
->buffer
->buf_size
)
1150 WARN("Invalid size %lu\n", bytes
);
1151 return DSERR_INVALIDPARAM
;
1154 if(InterlockedExchange(&This
->buffer
->locked
, TRUE
) == TRUE
)
1156 WARN("Already locked\n");
1157 return DSERR_INVALIDPARAM
;
1160 *ptr1
= This
->buffer
->data
+ ofs
;
1161 if(bytes
>= (DWORD
)This
->buffer
->buf_size
-ofs
)
1163 *len1
= This
->buffer
->buf_size
- ofs
;
1164 remain
= bytes
- *len1
;
1172 if(ptr2
&& len2
&& remain
)
1174 *ptr2
= This
->buffer
->data
;
1181 static HRESULT WINAPI
DS8Buffer_Play(IDirectSoundBuffer8
*iface
, DWORD res1
, DWORD prio
, DWORD flags
)
1183 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1184 ALint state
= AL_STOPPED
;
1188 TRACE("(%p)->(%lu, %lu, %lu)\n", iface
, res1
, prio
, flags
);
1190 EnterCriticalSection(This
->crst
);
1191 setALContext(This
->ctx
);
1193 hr
= DSERR_BUFFERLOST
;
1194 if(This
->bufferlost
)
1196 WARN("Buffer %p lost\n", This
);
1200 data
= This
->buffer
;
1201 if((data
->dsbflags
&DSBCAPS_LOCDEFER
))
1203 if(!(data
->dsbflags
&(DSBCAPS_LOCHARDWARE
|DSBCAPS_LOCSOFTWARE
)))
1205 if(flags
& DSBPLAY_LOCSOFTWARE
)
1206 data
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1208 data
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1213 ERR("Invalid priority set for non-deferred buffer %p, %lu!\n", This
->buffer
, prio
);
1214 hr
= DSERR_INVALIDPARAM
;
1218 if(This
->segsize
!= 0)
1220 This
->islooping
= !!(flags
&DSBPLAY_LOOPING
);
1221 if(This
->isplaying
) state
= AL_PLAYING
;
1225 alSourcei(This
->source
, AL_LOOPING
, (flags
&DSBPLAY_LOOPING
) ? AL_TRUE
: AL_FALSE
);
1226 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1231 if(state
== AL_PLAYING
)
1234 if(This
->segsize
== 0)
1236 if(state
!= AL_PAUSED
)
1237 alSourcei(This
->source
, AL_BUFFER
, data
->bid
);
1238 alSourcePlay(This
->source
);
1242 alSourceRewind(This
->source
);
1243 alSourcei(This
->source
, AL_BUFFER
, 0);
1244 This
->queue_base
= This
->data_offset
% data
->buf_size
;
1247 if(alGetError() != AL_NO_ERROR
)
1249 ERR("Couldn't start source\n");
1250 alSourcei(This
->source
, AL_BUFFER
, 0);
1255 This
->isplaying
= TRUE
;
1256 This
->playflags
= flags
;
1259 DS8Buffer_addnotify(This
);
1263 LeaveCriticalSection(This
->crst
);
1267 static HRESULT WINAPI
DS8Buffer_SetCurrentPosition(IDirectSoundBuffer8
*iface
, DWORD pos
)
1269 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1272 TRACE("(%p)->(%lu)\n", iface
, pos
);
1274 data
= This
->buffer
;
1275 if(pos
>= (DWORD
)data
->buf_size
)
1276 return DSERR_INVALIDPARAM
;
1277 pos
-= pos
%data
->format
.Format
.nBlockAlign
;
1279 EnterCriticalSection(This
->crst
);
1281 if(This
->segsize
!= 0)
1285 setALContext(This
->ctx
);
1286 /* Perform a flush, so the next timer update will restart at the
1287 * proper position */
1288 alSourceRewind(This
->source
);
1289 alSourcei(This
->source
, AL_BUFFER
, 0);
1293 This
->queue_base
= This
->data_offset
= pos
;
1298 setALContext(This
->ctx
);
1299 alSourcei(This
->source
, AL_BYTE_OFFSET
, pos
);
1303 This
->lastpos
= pos
;
1305 LeaveCriticalSection(This
->crst
);
1309 static HRESULT WINAPI
DS8Buffer_SetFormat(IDirectSoundBuffer8
*iface
, const WAVEFORMATEX
*wfx
)
1311 /* This call only works on primary buffers */
1312 WARN("(%p)->(%p)\n", iface
, wfx
);
1313 return DSERR_INVALIDCALL
;
1316 static HRESULT WINAPI
DS8Buffer_SetVolume(IDirectSoundBuffer8
*iface
, LONG vol
)
1318 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1321 TRACE("(%p)->(%ld)\n", iface
, vol
);
1323 if(vol
> DSBVOLUME_MAX
|| vol
< DSBVOLUME_MIN
)
1325 WARN("Invalid volume (%ld)\n", vol
);
1326 return DSERR_INVALIDPARAM
;
1329 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLVOLUME
))
1330 hr
= DSERR_CONTROLUNAVAIL
;
1333 ALfloat fvol
= mB_to_gain(vol
);
1334 setALContext(This
->ctx
);
1335 alSourcef(This
->source
, AL_GAIN
, fvol
);
1342 static HRESULT WINAPI
DS8Buffer_SetPan(IDirectSoundBuffer8
*iface
, LONG pan
)
1344 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1347 TRACE("(%p)->(%ld)\n", iface
, pan
);
1349 if(pan
> DSBPAN_RIGHT
|| pan
< DSBPAN_LEFT
)
1351 WARN("invalid parameter: pan = %ld\n", pan
);
1352 return DSERR_INVALIDPARAM
;
1355 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLPAN
))
1356 hr
= DSERR_CONTROLUNAVAIL
;
1359 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRL3D
))
1362 pos
[0] = (ALfloat
)(pan
-DSBPAN_LEFT
)/(ALfloat
)(DSBPAN_RIGHT
-DSBPAN_LEFT
) - 0.5f
;
1364 /* NOTE: Strict movement along the X plane can cause the sound to
1365 * jump between left and right sharply. Using a curved path helps
1368 pos
[2] = -sqrtf(1.0f
- pos
[0]*pos
[0]);
1370 setALContext(This
->ctx
);
1371 alSourcefv(This
->source
, AL_POSITION
, pos
);
1380 static HRESULT WINAPI
DS8Buffer_SetFrequency(IDirectSoundBuffer8
*iface
, DWORD freq
)
1382 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1385 TRACE("(%p)->(%lu)\n", iface
, freq
);
1387 if(freq
< DSBFREQUENCY_MIN
|| freq
> DSBFREQUENCY_MAX
)
1389 WARN("invalid parameter: freq = %lu\n", freq
);
1390 return DSERR_INVALIDPARAM
;
1393 if(!(This
->buffer
->dsbflags
&DSBCAPS_CTRLFREQUENCY
))
1394 hr
= DSERR_CONTROLUNAVAIL
;
1397 ALfloat pitch
= 1.0f
;
1398 if(freq
!= DSBFREQUENCY_ORIGINAL
)
1399 pitch
= freq
/ (ALfloat
)This
->buffer
->format
.Format
.nSamplesPerSec
;
1401 setALContext(This
->ctx
);
1402 alSourcef(This
->source
, AL_PITCH
, pitch
);
1410 static HRESULT WINAPI
DS8Buffer_Stop(IDirectSoundBuffer8
*iface
)
1412 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1414 TRACE("(%p)->()\n", iface
);
1416 EnterCriticalSection(This
->crst
);
1417 setALContext(This
->ctx
);
1419 alSourcePause(This
->source
);
1422 This
->isplaying
= FALSE
;
1423 DS8Primary_triggernots(This
->primary
);
1426 LeaveCriticalSection(This
->crst
);
1431 static HRESULT WINAPI
DS8Buffer_Unlock(IDirectSoundBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
1433 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1434 DS8Data
*buf
= This
->buffer
;
1435 DWORD bufsize
= buf
->buf_size
;
1436 DWORD_PTR ofs1
, ofs2
;
1437 DWORD_PTR boundary
= (DWORD_PTR
)buf
->data
;
1440 TRACE("(%p)->(%p, %lu, %p, %lu)\n", iface
, ptr1
, len1
, ptr2
, len2
);
1442 if(InterlockedExchange(&This
->buffer
->locked
, FALSE
) == FALSE
)
1444 WARN("Not locked\n");
1445 return DSERR_INVALIDPARAM
;
1448 hr
= DSERR_INVALIDPARAM
;
1449 /* Make sure offset is between boundary and boundary + bufsize */
1450 ofs1
= (DWORD_PTR
)ptr1
;
1451 ofs2
= (DWORD_PTR
)ptr2
;
1452 if(ofs1
< boundary
|| (ofs2
&& ofs2
!= boundary
))
1456 if(bufsize
-ofs1
< len1
|| len2
> ofs1
)
1465 if(BITFIELD_TEST(This
->primary
->Exts
, SOFTX_MAP_BUFFER
))
1467 setALContext(This
->ctx
);
1468 alFlushMappedBufferSOFT(buf
->bid
, 0, buf
->buf_size
);
1472 else if(This
->segsize
== 0)
1474 setALContext(This
->ctx
);
1475 alBufferData(buf
->bid
, buf
->buf_format
, buf
->data
, buf
->buf_size
,
1476 buf
->format
.Format
.nSamplesPerSec
);
1483 WARN("Invalid parameters (0x%lx,%lu) (%p,%lu,%p,%lu)\n", boundary
, bufsize
, ptr1
, len1
, ptr2
, len2
);
1487 static HRESULT WINAPI
DS8Buffer_Restore(IDirectSoundBuffer8
*iface
)
1489 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1492 TRACE("(%p)->()\n", iface
);
1494 EnterCriticalSection(This
->crst
);
1495 if(This
->primary
->parent
->prio_level
< DSSCL_WRITEPRIMARY
||
1496 iface
== This
->primary
->write_emu
)
1498 This
->bufferlost
= 0;
1502 hr
= DSERR_BUFFERLOST
;
1503 LeaveCriticalSection(This
->crst
);
1508 static HRESULT WINAPI
DS8Buffer_SetFX(IDirectSoundBuffer8
*iface
, DWORD fxcount
, DSEFFECTDESC
*desc
, DWORD
*rescodes
)
1510 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1511 ALenum state
= AL_INITIAL
;
1516 TRACE("(%p)->(%lu, %p, %p)\n", This
, fxcount
, desc
, rescodes
);
1518 data
= This
->buffer
;
1519 if(!(data
->dsbflags
&DSBCAPS_CTRLFX
))
1521 WARN("FX control not set\n");
1522 return DSERR_CONTROLUNAVAIL
;
1527 WARN("Buffer is locked\n");
1528 return DSERR_INVALIDCALL
;
1531 EnterCriticalSection(This
->crst
);
1532 setALContext(This
->ctx
);
1534 alGetSourcei(This
->source
, AL_SOURCE_STATE
, &state
);
1536 if(This
->segsize
!= 0 && state
!= AL_PLAYING
)
1537 state
= This
->isplaying
? AL_PLAYING
: AL_PAUSED
;
1538 if(state
== AL_PLAYING
)
1540 WARN("Buffer is playing\n");
1541 hr
= DSERR_INVALIDCALL
;
1545 hr
= DSERR_INVALIDPARAM
;
1548 if(desc
|| rescodes
)
1550 WARN("Non-NULL desc and/or result pointer specified with no effects.\n");
1554 /* No effects; we can handle that */
1559 if(!desc
|| !rescodes
)
1561 WARN("NULL desc and/or result pointer specified.\n");
1565 /* We don't (currently) handle DSound effects */
1566 for(i
= 0;i
< fxcount
;++i
)
1568 FIXME("Cannot handle effect: %s\n", debugstr_guid(&desc
[i
].guidDSFXClass
));
1569 rescodes
[i
] = DSFXR_FAILED
;
1575 LeaveCriticalSection(This
->crst
);
1580 static HRESULT WINAPI
DS8Buffer_AcquireResources(IDirectSoundBuffer8
*iface
, DWORD flags
, DWORD fxcount
, DWORD
*rescodes
)
1582 DS8Buffer
*This
= impl_from_IDirectSoundBuffer8(iface
);
1584 TRACE("(%p)->(%lu, %lu, %p)\n", This
, flags
, fxcount
, rescodes
);
1586 /* effects aren't supported at the moment.. */
1587 if(fxcount
!= 0 || rescodes
)
1589 WARN("Non-zero effect count and/or result pointer specified with no effects.\n");
1590 return DSERR_INVALIDPARAM
;
1593 EnterCriticalSection(This
->crst
);
1594 if((This
->buffer
->dsbflags
&DSBCAPS_LOCDEFER
))
1596 This
->buffer
->dsbflags
&= ~(DSBCAPS_LOCSOFTWARE
|DSBCAPS_LOCHARDWARE
);
1597 if((flags
&DSBPLAY_LOCSOFTWARE
))
1598 This
->buffer
->dsbflags
|= DSBCAPS_LOCSOFTWARE
;
1600 This
->buffer
->dsbflags
|= DSBCAPS_LOCHARDWARE
;
1602 LeaveCriticalSection(This
->crst
);
1607 static HRESULT WINAPI
DS8Buffer_GetObjectInPath(IDirectSoundBuffer8
*iface
, REFGUID guid
, DWORD idx
, REFGUID rguidiface
, void **ppv
)
1609 FIXME("(%p)->(%s, %lu, %s, %p) : stub!\n", iface
, debugstr_guid(guid
), idx
, debugstr_guid(rguidiface
), ppv
);
1613 static const IDirectSoundBuffer8Vtbl DS8Buffer_Vtbl
= {
1614 DS8Buffer_QueryInterface
,
1618 DS8Buffer_GetCurrentPosition
,
1619 DS8Buffer_GetFormat
,
1620 DS8Buffer_GetVolume
,
1622 DS8Buffer_GetFrequency
,
1623 DS8Buffer_GetStatus
,
1624 DS8Buffer_Initialize
,
1627 DS8Buffer_SetCurrentPosition
,
1628 DS8Buffer_SetFormat
,
1629 DS8Buffer_SetVolume
,
1631 DS8Buffer_SetFrequency
,
1636 DS8Buffer_AcquireResources
,
1637 DS8Buffer_GetObjectInPath
1641 void DS8Buffer_SetParams(DS8Buffer
*This
, const DS3DBUFFER
*params
, const EAX20BUFFERPROPERTIES
*eax_params
, LONG flags
)
1643 const ALuint source
= This
->source
;
1644 union BufferParamFlags dirty
= { flags
};
1647 alSource3f(source
, AL_POSITION
, params
->vPosition
.x
, params
->vPosition
.y
,
1648 -params
->vPosition
.z
);
1650 alSource3f(source
, AL_VELOCITY
, params
->vVelocity
.x
, params
->vVelocity
.y
,
1651 -params
->vVelocity
.z
);
1652 if(dirty
.bit
.cone_angles
)
1654 alSourcei(source
, AL_CONE_INNER_ANGLE
, params
->dwInsideConeAngle
);
1655 alSourcei(source
, AL_CONE_OUTER_ANGLE
, params
->dwOutsideConeAngle
);
1657 if(dirty
.bit
.cone_orient
)
1658 alSource3f(source
, AL_DIRECTION
, params
->vConeOrientation
.x
,
1659 params
->vConeOrientation
.y
,
1660 -params
->vConeOrientation
.z
);
1661 if(dirty
.bit
.cone_outsidevolume
)
1662 alSourcef(source
, AL_CONE_OUTER_GAIN
, mB_to_gain(params
->lConeOutsideVolume
));
1663 if(dirty
.bit
.min_distance
)
1664 alSourcef(source
, AL_REFERENCE_DISTANCE
, params
->flMinDistance
);
1665 if(dirty
.bit
.max_distance
)
1666 alSourcef(source
, AL_MAX_DISTANCE
, params
->flMaxDistance
);
1669 This
->ds3dmode
= params
->dwMode
;
1670 if(BITFIELD_TEST(This
->primary
->Exts
, SOFT_SOURCE_SPATIALIZE
))
1671 alSourcei(source
, AL_SOURCE_SPATIALIZE_SOFT
,
1672 (params
->dwMode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
);
1673 alSourcei(source
, AL_SOURCE_RELATIVE
, (params
->dwMode
!=DS3DMODE_NORMAL
) ?
1674 AL_TRUE
: AL_FALSE
);
1675 alSourcef(source
, AL_ROLLOFF_FACTOR
, (params
->dwMode
==DS3DMODE_DISABLE
) ?
1676 0.0f
: This
->primary
->rollofffactor
);
1679 if(dirty
.bit
.dry_filter
)
1680 alSourcei(source
, AL_DIRECT_FILTER
, This
->filter
[0]);
1681 if(dirty
.bit
.wet_filter
)
1682 alSource3i(source
, AL_AUXILIARY_SEND_FILTER
, This
->primary
->auxslot
, 0, This
->filter
[1]);
1683 if(dirty
.bit
.room_rolloff
)
1684 alSourcef(source
, AL_ROOM_ROLLOFF_FACTOR
, eax_params
->flRoomRolloffFactor
);
1685 if(dirty
.bit
.cone_outsidevolumehf
)
1686 alSourcef(source
, AL_CONE_OUTER_GAINHF
, mB_to_gain(eax_params
->lOutsideVolumeHF
));
1687 if(dirty
.bit
.air_absorb
)
1688 alSourcef(source
, AL_AIR_ABSORPTION_FACTOR
, eax_params
->flAirAbsorptionFactor
);
1691 alSourcei(source
, AL_DIRECT_FILTER_GAINHF_AUTO
,
1692 (eax_params
->dwFlags
&EAXBUFFERFLAGS_DIRECTHFAUTO
) ? AL_TRUE
: AL_FALSE
);
1693 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAIN_AUTO
,
1694 (eax_params
->dwFlags
&EAXBUFFERFLAGS_ROOMAUTO
) ? AL_TRUE
: AL_FALSE
);
1695 alSourcei(source
, AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO
,
1696 (eax_params
->dwFlags
&EAXBUFFERFLAGS_ROOMHFAUTO
) ? AL_TRUE
: AL_FALSE
);
1700 static HRESULT WINAPI
DS8Buffer3D_QueryInterface(IDirectSound3DBuffer
*iface
, REFIID riid
, void **ppv
)
1702 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1703 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
1706 static ULONG WINAPI
DS8Buffer3D_AddRef(IDirectSound3DBuffer
*iface
)
1708 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1711 InterlockedIncrement(&This
->all_ref
);
1712 ret
= InterlockedIncrement(&This
->ds3d_ref
);
1713 TRACE("new refcount %ld\n", ret
);
1718 static ULONG WINAPI
DS8Buffer3D_Release(IDirectSound3DBuffer
*iface
)
1720 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1723 ret
= InterlockedDecrement(&This
->ds3d_ref
);
1724 TRACE("new refcount %ld\n", ret
);
1725 if(InterlockedDecrement(&This
->all_ref
) == 0)
1726 DS8Buffer_Destroy(This
);
1731 static HRESULT WINAPI
DS8Buffer3D_GetConeAngles(IDirectSound3DBuffer
*iface
, DWORD
*pdwInsideConeAngle
, DWORD
*pdwOutsideConeAngle
)
1733 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1734 ALint inangle
, outangle
;
1736 TRACE("(%p)->(%p, %p)\n", This
, pdwInsideConeAngle
, pdwOutsideConeAngle
);
1737 if(!pdwInsideConeAngle
|| !pdwOutsideConeAngle
)
1739 WARN("Invalid pointers (%p, %p)\n", pdwInsideConeAngle
, pdwOutsideConeAngle
);
1740 return DSERR_INVALIDPARAM
;
1743 EnterCriticalSection(This
->crst
);
1744 setALContext(This
->ctx
);
1746 alGetSourcei(This
->source
, AL_CONE_INNER_ANGLE
, &inangle
);
1747 alGetSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, &outangle
);
1751 LeaveCriticalSection(This
->crst
);
1753 *pdwInsideConeAngle
= inangle
;
1754 *pdwOutsideConeAngle
= outangle
;
1758 static HRESULT WINAPI
DS8Buffer3D_GetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVECTOR
*orient
)
1760 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1763 TRACE("(%p)->(%p)\n", This
, orient
);
1766 WARN("Invalid pointer\n");
1767 return DSERR_INVALIDPARAM
;
1770 setALContext(This
->ctx
);
1771 alGetSourcefv(This
->source
, AL_DIRECTION
, dir
);
1777 orient
->z
= -dir
[2];
1781 static HRESULT WINAPI
DS8Buffer3D_GetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG
*vol
)
1783 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1786 TRACE("(%p)->(%p)\n", This
, vol
);
1789 WARN("Invalid pointer\n");
1790 return DSERR_INVALIDPARAM
;
1793 setALContext(This
->ctx
);
1794 alGetSourcef(This
->source
, AL_CONE_OUTER_GAIN
, &gain
);
1798 *vol
= clampI(gain_to_mB(gain
), DSBVOLUME_MIN
, DSBVOLUME_MAX
);
1802 static HRESULT WINAPI
DS8Buffer3D_GetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*maxdist
)
1804 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1807 TRACE("(%p)->(%p)\n", This
, maxdist
);
1810 WARN("Invalid pointer\n");
1811 return DSERR_INVALIDPARAM
;
1814 setALContext(This
->ctx
);
1815 alGetSourcef(This
->source
, AL_MAX_DISTANCE
, &dist
);
1823 static HRESULT WINAPI
DS8Buffer3D_GetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE
*mindist
)
1825 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1828 TRACE("(%p)->(%p)\n", This
, mindist
);
1831 WARN("Invalid pointer\n");
1832 return DSERR_INVALIDPARAM
;
1835 setALContext(This
->ctx
);
1836 alGetSourcef(This
->source
, AL_REFERENCE_DISTANCE
, &dist
);
1844 static HRESULT WINAPI
DS8Buffer3D_GetMode(IDirectSound3DBuffer
*iface
, DWORD
*mode
)
1846 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1848 TRACE("(%p)->(%p)\n", This
, mode
);
1851 WARN("Invalid pointer\n");
1852 return DSERR_INVALIDPARAM
;
1855 EnterCriticalSection(This
->crst
);
1856 *mode
= This
->ds3dmode
;
1857 LeaveCriticalSection(This
->crst
);
1862 static HRESULT WINAPI
DS8Buffer3D_GetPosition(IDirectSound3DBuffer
*iface
, D3DVECTOR
*pos
)
1864 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1867 TRACE("(%p)->(%p)\n", This
, pos
);
1870 WARN("Invalid pointer\n");
1871 return DSERR_INVALIDPARAM
;
1874 setALContext(This
->ctx
);
1875 alGetSourcefv(This
->source
, AL_POSITION
, alpos
);
1885 static HRESULT WINAPI
DS8Buffer3D_GetVelocity(IDirectSound3DBuffer
*iface
, D3DVECTOR
*vel
)
1887 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1890 TRACE("(%p)->(%p)\n", This
, vel
);
1893 WARN("Invalid pointer\n");
1894 return DSERR_INVALIDPARAM
;
1897 setALContext(This
->ctx
);
1898 alGetSourcefv(This
->source
, AL_VELOCITY
, alvel
);
1908 static HRESULT WINAPI
DS8Buffer3D_GetAllParameters(IDirectSound3DBuffer
*iface
, DS3DBUFFER
*ds3dbuffer
)
1910 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1912 TRACE("(%p)->(%p)\n", iface
, ds3dbuffer
);
1914 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
1916 WARN("Invalid parameters %p %lu\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
1917 return DSERR_INVALIDPARAM
;
1920 EnterCriticalSection(This
->crst
);
1921 setALContext(This
->ctx
);
1923 DS8Buffer3D_GetPosition(iface
, &ds3dbuffer
->vPosition
);
1924 DS8Buffer3D_GetVelocity(iface
, &ds3dbuffer
->vVelocity
);
1925 DS8Buffer3D_GetConeAngles(iface
, &ds3dbuffer
->dwInsideConeAngle
, &ds3dbuffer
->dwOutsideConeAngle
);
1926 DS8Buffer3D_GetConeOrientation(iface
, &ds3dbuffer
->vConeOrientation
);
1927 DS8Buffer3D_GetConeOutsideVolume(iface
, &ds3dbuffer
->lConeOutsideVolume
);
1928 DS8Buffer3D_GetMinDistance(iface
, &ds3dbuffer
->flMinDistance
);
1929 DS8Buffer3D_GetMaxDistance(iface
, &ds3dbuffer
->flMaxDistance
);
1930 DS8Buffer3D_GetMode(iface
, &ds3dbuffer
->dwMode
);
1933 LeaveCriticalSection(This
->crst
);
1938 static HRESULT WINAPI
DS8Buffer3D_SetConeAngles(IDirectSound3DBuffer
*iface
, DWORD dwInsideConeAngle
, DWORD dwOutsideConeAngle
, DWORD apply
)
1940 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1942 TRACE("(%p)->(%lu, %lu, %lu)\n", This
, dwInsideConeAngle
, dwOutsideConeAngle
, apply
);
1943 if(dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
1944 dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
1946 WARN("Invalid cone angles (%lu, %lu)\n", dwInsideConeAngle
, dwOutsideConeAngle
);
1947 return DSERR_INVALIDPARAM
;
1950 EnterCriticalSection(This
->crst
);
1951 if(apply
== DS3D_DEFERRED
)
1953 This
->params
.dwInsideConeAngle
= dwInsideConeAngle
;
1954 This
->params
.dwOutsideConeAngle
= dwOutsideConeAngle
;
1955 This
->dirty
.bit
.cone_angles
= 1;
1959 setALContext(This
->ctx
);
1960 alSourcei(This
->source
, AL_CONE_INNER_ANGLE
, dwInsideConeAngle
);
1961 alSourcei(This
->source
, AL_CONE_OUTER_ANGLE
, dwOutsideConeAngle
);
1965 LeaveCriticalSection(This
->crst
);
1970 static HRESULT WINAPI
DS8Buffer3D_SetConeOrientation(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
1972 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
1974 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
1976 if(apply
== DS3D_DEFERRED
)
1978 EnterCriticalSection(This
->crst
);
1979 This
->params
.vConeOrientation
.x
= x
;
1980 This
->params
.vConeOrientation
.y
= y
;
1981 This
->params
.vConeOrientation
.z
= z
;
1982 This
->dirty
.bit
.cone_orient
= 1;
1983 LeaveCriticalSection(This
->crst
);
1987 setALContext(This
->ctx
);
1988 alSource3f(This
->source
, AL_DIRECTION
, x
, y
, -z
);
1996 static HRESULT WINAPI
DS8Buffer3D_SetConeOutsideVolume(IDirectSound3DBuffer
*iface
, LONG vol
, DWORD apply
)
1998 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2000 TRACE("(%p)->(%ld, %lu)\n", This
, vol
, apply
);
2001 if(vol
< DSBVOLUME_MIN
|| vol
> DSBVOLUME_MAX
)
2003 WARN("Invalid volume (%ld)\n", vol
);
2004 return DSERR_INVALIDPARAM
;
2007 if(apply
== DS3D_DEFERRED
)
2009 EnterCriticalSection(This
->crst
);
2010 This
->params
.lConeOutsideVolume
= vol
;
2011 This
->dirty
.bit
.cone_outsidevolume
= 1;
2012 LeaveCriticalSection(This
->crst
);
2016 setALContext(This
->ctx
);
2017 alSourcef(This
->source
, AL_CONE_OUTER_GAIN
, mB_to_gain(vol
));
2025 static HRESULT WINAPI
DS8Buffer3D_SetMaxDistance(IDirectSound3DBuffer
*iface
, D3DVALUE maxdist
, DWORD apply
)
2027 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2029 TRACE("(%p)->(%f, %lu)\n", This
, maxdist
, apply
);
2032 WARN("Invalid max distance (%f)\n", maxdist
);
2033 return DSERR_INVALIDPARAM
;
2036 if(apply
== DS3D_DEFERRED
)
2038 EnterCriticalSection(This
->crst
);
2039 This
->params
.flMaxDistance
= maxdist
;
2040 This
->dirty
.bit
.max_distance
= 1;
2041 LeaveCriticalSection(This
->crst
);
2045 setALContext(This
->ctx
);
2046 alSourcef(This
->source
, AL_MAX_DISTANCE
, maxdist
);
2054 static HRESULT WINAPI
DS8Buffer3D_SetMinDistance(IDirectSound3DBuffer
*iface
, D3DVALUE mindist
, DWORD apply
)
2056 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2058 TRACE("(%p)->(%f, %lu)\n", This
, mindist
, apply
);
2061 WARN("Invalid min distance (%f)\n", mindist
);
2062 return DSERR_INVALIDPARAM
;
2065 if(apply
== DS3D_DEFERRED
)
2067 EnterCriticalSection(This
->crst
);
2068 This
->params
.flMinDistance
= mindist
;
2069 This
->dirty
.bit
.min_distance
= 1;
2070 LeaveCriticalSection(This
->crst
);
2074 setALContext(This
->ctx
);
2075 alSourcef(This
->source
, AL_REFERENCE_DISTANCE
, mindist
);
2083 static HRESULT WINAPI
DS8Buffer3D_SetMode(IDirectSound3DBuffer
*iface
, DWORD mode
, DWORD apply
)
2085 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2087 TRACE("(%p)->(%lu, %lu)\n", This
, mode
, apply
);
2088 if(mode
!= DS3DMODE_NORMAL
&& mode
!= DS3DMODE_HEADRELATIVE
&&
2089 mode
!= DS3DMODE_DISABLE
)
2091 WARN("Invalid mode (%lu)\n", mode
);
2092 return DSERR_INVALIDPARAM
;
2095 EnterCriticalSection(This
->crst
);
2096 if(apply
== DS3D_DEFERRED
)
2098 This
->params
.dwMode
= mode
;
2099 This
->dirty
.bit
.mode
= 1;
2103 setALContext(This
->ctx
);
2104 This
->ds3dmode
= mode
;
2105 if(BITFIELD_TEST(This
->primary
->Exts
, SOFT_SOURCE_SPATIALIZE
))
2106 alSourcei(This
->source
, AL_SOURCE_SPATIALIZE_SOFT
,
2107 (mode
==DS3DMODE_DISABLE
) ? AL_FALSE
: AL_TRUE
);
2108 alSourcei(This
->source
, AL_SOURCE_RELATIVE
,
2109 (mode
!= DS3DMODE_NORMAL
) ? AL_TRUE
: AL_FALSE
);
2110 alSourcef(This
->source
, AL_ROLLOFF_FACTOR
,
2111 (mode
== DS3DMODE_DISABLE
) ? 0.0f
: This
->primary
->rollofffactor
);
2115 LeaveCriticalSection(This
->crst
);
2120 static HRESULT WINAPI
DS8Buffer3D_SetPosition(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2122 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2124 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2126 if(apply
== DS3D_DEFERRED
)
2128 EnterCriticalSection(This
->crst
);
2129 This
->params
.vPosition
.x
= x
;
2130 This
->params
.vPosition
.y
= y
;
2131 This
->params
.vPosition
.z
= z
;
2132 This
->dirty
.bit
.pos
= 1;
2133 LeaveCriticalSection(This
->crst
);
2137 setALContext(This
->ctx
);
2138 alSource3f(This
->source
, AL_POSITION
, x
, y
, -z
);
2146 static HRESULT WINAPI
DS8Buffer3D_SetVelocity(IDirectSound3DBuffer
*iface
, D3DVALUE x
, D3DVALUE y
, D3DVALUE z
, DWORD apply
)
2148 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2150 TRACE("(%p)->(%f, %f, %f, %lu)\n", This
, x
, y
, z
, apply
);
2152 if(apply
== DS3D_DEFERRED
)
2154 EnterCriticalSection(This
->crst
);
2155 This
->params
.vVelocity
.x
= x
;
2156 This
->params
.vVelocity
.y
= y
;
2157 This
->params
.vVelocity
.z
= z
;
2158 This
->dirty
.bit
.vel
= 1;
2159 LeaveCriticalSection(This
->crst
);
2163 setALContext(This
->ctx
);
2164 alSource3f(This
->source
, AL_VELOCITY
, x
, y
, -z
);
2172 static HRESULT WINAPI
DS8Buffer3D_SetAllParameters(IDirectSound3DBuffer
*iface
, const DS3DBUFFER
*ds3dbuffer
, DWORD apply
)
2174 DS8Buffer
*This
= impl_from_IDirectSound3DBuffer(iface
);
2175 TRACE("(%p)->(%p, %lu)\n", This
, ds3dbuffer
, apply
);
2177 if(!ds3dbuffer
|| ds3dbuffer
->dwSize
< sizeof(*ds3dbuffer
))
2179 WARN("Invalid DS3DBUFFER (%p, %lu)\n", ds3dbuffer
, ds3dbuffer
? ds3dbuffer
->dwSize
: 0);
2180 return DSERR_INVALIDPARAM
;
2183 if(ds3dbuffer
->dwInsideConeAngle
> DS3D_MAXCONEANGLE
||
2184 ds3dbuffer
->dwOutsideConeAngle
> DS3D_MAXCONEANGLE
)
2186 WARN("Invalid cone angles (%lu, %lu)\n",
2187 ds3dbuffer
->dwInsideConeAngle
, ds3dbuffer
->dwOutsideConeAngle
);
2188 return DSERR_INVALIDPARAM
;
2191 if(ds3dbuffer
->lConeOutsideVolume
> DSBVOLUME_MAX
||
2192 ds3dbuffer
->lConeOutsideVolume
< DSBVOLUME_MIN
)
2194 WARN("Invalid cone outside volume (%ld)\n", ds3dbuffer
->lConeOutsideVolume
);
2195 return DSERR_INVALIDPARAM
;
2198 if(ds3dbuffer
->flMaxDistance
< 0.0f
)
2200 WARN("Invalid max distance (%f)\n", ds3dbuffer
->flMaxDistance
);
2201 return DSERR_INVALIDPARAM
;
2204 if(ds3dbuffer
->flMinDistance
< 0.0f
)
2206 WARN("Invalid min distance (%f)\n", ds3dbuffer
->flMinDistance
);
2207 return DSERR_INVALIDPARAM
;
2210 if(ds3dbuffer
->dwMode
!= DS3DMODE_NORMAL
&&
2211 ds3dbuffer
->dwMode
!= DS3DMODE_HEADRELATIVE
&&
2212 ds3dbuffer
->dwMode
!= DS3DMODE_DISABLE
)
2214 WARN("Invalid mode (%lu)\n", ds3dbuffer
->dwMode
);
2215 return DSERR_INVALIDPARAM
;
2218 if(apply
== DS3D_DEFERRED
)
2220 EnterCriticalSection(This
->crst
);
2221 This
->params
= *ds3dbuffer
;
2222 This
->params
.dwSize
= sizeof(This
->params
);
2223 This
->dirty
.bit
.pos
= 1;
2224 This
->dirty
.bit
.vel
= 1;
2225 This
->dirty
.bit
.cone_angles
= 1;
2226 This
->dirty
.bit
.cone_orient
= 1;
2227 This
->dirty
.bit
.cone_outsidevolume
= 1;
2228 This
->dirty
.bit
.min_distance
= 1;
2229 This
->dirty
.bit
.max_distance
= 1;
2230 This
->dirty
.bit
.mode
= 1;
2231 LeaveCriticalSection(This
->crst
);
2235 union BufferParamFlags dirty
= { 0 };
2238 dirty
.bit
.cone_angles
= 1;
2239 dirty
.bit
.cone_orient
= 1;
2240 dirty
.bit
.cone_outsidevolume
= 1;
2241 dirty
.bit
.min_distance
= 1;
2242 dirty
.bit
.max_distance
= 1;
2245 EnterCriticalSection(This
->crst
);
2246 setALContext(This
->ctx
);
2247 DS8Buffer_SetParams(This
, ds3dbuffer
, NULL
, dirty
.flags
);
2250 LeaveCriticalSection(This
->crst
);
2256 static const IDirectSound3DBufferVtbl DS8Buffer3d_Vtbl
=
2258 DS8Buffer3D_QueryInterface
,
2260 DS8Buffer3D_Release
,
2261 DS8Buffer3D_GetAllParameters
,
2262 DS8Buffer3D_GetConeAngles
,
2263 DS8Buffer3D_GetConeOrientation
,
2264 DS8Buffer3D_GetConeOutsideVolume
,
2265 DS8Buffer3D_GetMaxDistance
,
2266 DS8Buffer3D_GetMinDistance
,
2267 DS8Buffer3D_GetMode
,
2268 DS8Buffer3D_GetPosition
,
2269 DS8Buffer3D_GetVelocity
,
2270 DS8Buffer3D_SetAllParameters
,
2271 DS8Buffer3D_SetConeAngles
,
2272 DS8Buffer3D_SetConeOrientation
,
2273 DS8Buffer3D_SetConeOutsideVolume
,
2274 DS8Buffer3D_SetMaxDistance
,
2275 DS8Buffer3D_SetMinDistance
,
2276 DS8Buffer3D_SetMode
,
2277 DS8Buffer3D_SetPosition
,
2278 DS8Buffer3D_SetVelocity
2282 static HRESULT WINAPI
DS8BufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
2284 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2285 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2288 static ULONG WINAPI
DS8BufferNot_AddRef(IDirectSoundNotify
*iface
)
2290 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2293 InterlockedIncrement(&This
->all_ref
);
2294 ret
= InterlockedIncrement(&This
->not_ref
);
2295 TRACE("new refcount %ld\n", ret
);
2300 static ULONG WINAPI
DS8BufferNot_Release(IDirectSoundNotify
*iface
)
2302 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2305 ret
= InterlockedDecrement(&This
->not_ref
);
2306 TRACE("new refcount %ld\n", ret
);
2307 if(InterlockedDecrement(&This
->all_ref
) == 0)
2308 DS8Buffer_Destroy(This
);
2313 static HRESULT WINAPI
DS8BufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
2315 DS8Buffer
*This
= impl_from_IDirectSoundNotify(iface
);
2316 DSBPOSITIONNOTIFY
*nots
;
2320 TRACE("(%p)->(%lu, %p))\n", iface
, count
, notifications
);
2322 EnterCriticalSection(This
->crst
);
2323 hr
= DSERR_INVALIDPARAM
;
2324 if(count
&& !notifications
)
2327 hr
= DS8Buffer_GetStatus(&This
->IDirectSoundBuffer8_iface
, &state
);
2328 if(FAILED(hr
)) goto out
;
2330 hr
= DSERR_INVALIDCALL
;
2331 if((state
&DSBSTATUS_PLAYING
))
2336 HeapFree(GetProcessHeap(), 0, This
->notify
);
2345 hr
= DSERR_INVALIDPARAM
;
2346 for(i
= 0;i
< count
;++i
)
2348 if(notifications
[i
].dwOffset
>= (DWORD
)This
->buffer
->buf_size
&&
2349 notifications
[i
].dwOffset
!= (DWORD
)DSBPN_OFFSETSTOP
)
2354 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
2356 memcpy(nots
, notifications
, count
*sizeof(*nots
));
2358 HeapFree(GetProcessHeap(), 0, This
->notify
);
2359 This
->notify
= nots
;
2360 This
->nnotify
= count
;
2366 LeaveCriticalSection(This
->crst
);
2370 static const IDirectSoundNotifyVtbl DS8BufferNot_Vtbl
=
2372 DS8BufferNot_QueryInterface
,
2373 DS8BufferNot_AddRef
,
2374 DS8BufferNot_Release
,
2375 DS8BufferNot_SetNotificationPositions
2379 static void ApplyReverbParams(DS8Primary
*prim
, const EAXLISTENERPROPERTIES
*props
)
2381 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
2382 prim
->eax_prop
= *props
;
2383 alEffectf(prim
->effect
, AL_REVERB_DENSITY
,
2384 clampF(powf(props
->flEnvironmentSize
, 3.0f
) / 16.0f
, 0.0f
, 1.0f
)
2386 alEffectf(prim
->effect
, AL_REVERB_DIFFUSION
, props
->flEnvironmentDiffusion
);
2388 alEffectf(prim
->effect
, AL_REVERB_GAIN
, mB_to_gain(props
->lRoom
));
2389 alEffectf(prim
->effect
, AL_REVERB_GAINHF
, mB_to_gain(props
->lRoomHF
));
2391 alEffectf(prim
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
, props
->flRoomRolloffFactor
);
2393 alEffectf(prim
->effect
, AL_REVERB_DECAY_TIME
, props
->flDecayTime
);
2394 alEffectf(prim
->effect
, AL_REVERB_DECAY_HFRATIO
, props
->flDecayHFRatio
);
2396 alEffectf(prim
->effect
, AL_REVERB_REFLECTIONS_GAIN
, mB_to_gain(props
->lReflections
));
2397 alEffectf(prim
->effect
, AL_REVERB_REFLECTIONS_DELAY
, props
->flReflectionsDelay
);
2399 alEffectf(prim
->effect
, AL_REVERB_LATE_REVERB_GAIN
, mB_to_gain(props
->lReverb
));
2400 alEffectf(prim
->effect
, AL_REVERB_LATE_REVERB_DELAY
, props
->flReverbDelay
);
2402 alEffectf(prim
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
2403 mB_to_gain(props
->flAirAbsorptionHF
));
2405 alEffecti(prim
->effect
, AL_REVERB_DECAY_HFLIMIT
,
2406 (props
->dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
2407 AL_TRUE
: AL_FALSE
);
2411 prim
->dirty
.bit
.effect
= 1;
2414 #define APPLY_DRY_PARAMS 1
2415 #define APPLY_WET_PARAMS 2
2416 static void ApplyFilterParams(DS8Buffer
*buf
, const EAX20BUFFERPROPERTIES
*props
, int apply
)
2418 /* The LFRatio properties determine how much the given level applies to low
2419 * frequencies as well as high frequencies. Given that the high frequency
2420 * levels are specified relative to the low, they should increase as the
2421 * low frequency levels reduce.
2423 FLOAT occl
= props
->lOcclusion
* props
->flOcclusionLFRatio
;
2424 FLOAT occlhf
= props
->lOcclusion
* (1.0f
-props
->flOcclusionLFRatio
);
2426 if((apply
&APPLY_DRY_PARAMS
))
2428 FLOAT obstr
= props
->lObstruction
* props
->flObstructionLFRatio
;
2429 FLOAT obstrhf
= props
->lObstruction
* (1.0f
-props
->flObstructionLFRatio
);
2430 FLOAT mb
= props
->lDirect
+ obstr
+ occl
;
2431 FLOAT mbhf
= props
->lDirectHF
+ obstrhf
+ occlhf
;
2433 alFilterf(buf
->filter
[0], AL_LOWPASS_GAIN
, mB_to_gain(mb
));
2434 alFilterf(buf
->filter
[0], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
2436 if((apply
&APPLY_WET_PARAMS
))
2438 FLOAT occlroom
= props
->flOcclusionRoomRatio
;
2439 FLOAT mb
= props
->lRoom
+ occlroom
*occl
;
2440 FLOAT mbhf
= props
->lRoomHF
+ occlroom
*occlhf
;
2442 alFilterf(buf
->filter
[1], AL_LOWPASS_GAIN
, mB_to_gain(mb
));
2443 alFilterf(buf
->filter
[1], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
2448 static HRESULT WINAPI
DS8BufferProp_QueryInterface(IKsPropertySet
*iface
, REFIID riid
, void **ppv
)
2450 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2451 return DS8Buffer_QueryInterface(&This
->IDirectSoundBuffer8_iface
, riid
, ppv
);
2454 static ULONG WINAPI
DS8BufferProp_AddRef(IKsPropertySet
*iface
)
2456 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2459 InterlockedIncrement(&This
->all_ref
);
2460 ret
= InterlockedIncrement(&This
->prop_ref
);
2461 TRACE("new refcount %ld\n", ret
);
2466 static ULONG WINAPI
DS8BufferProp_Release(IKsPropertySet
*iface
)
2468 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2471 ret
= InterlockedDecrement(&This
->prop_ref
);
2472 TRACE("new refcount %ld\n", ret
);
2473 if(InterlockedDecrement(&This
->all_ref
) == 0)
2474 DS8Buffer_Destroy(This
);
2479 /* NOTE: Due to some apparent quirks in DSound, the listener properties are
2480 handled through secondary buffers. */
2481 static HRESULT WINAPI
DS8BufferProp_Get(IKsPropertySet
*iface
,
2482 REFGUID guidPropSet
, ULONG dwPropID
,
2483 LPVOID pInstanceData
, ULONG cbInstanceData
,
2484 LPVOID pPropData
, ULONG cbPropData
,
2487 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2488 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2490 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
),
2491 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
, pcbReturned
);
2497 if(cbPropData
> 0 && !pPropData
)
2499 WARN("pPropData is NULL with cbPropData > 0\n");
2503 #define GET_PROP(hr, retsize, dst, dstsize, src, Type) do { \
2504 if(cbPropData >= sizeof(Type)) \
2511 *data.props = src; \
2512 *(retsize) = sizeof(Type); \
2516 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2518 EnterCriticalSection(This
->crst
);
2520 hr
= DSERR_INVALIDPARAM
;
2521 if(This
->filter
[0] == 0)
2522 hr
= E_PROP_ID_UNSUPPORTED
;
2523 else switch(dwPropID
)
2525 case DSPROPERTY_EAXBUFFER_ALLPARAMETERS
:
2526 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
,
2527 EAX20BUFFERPROPERTIES
);
2530 case DSPROPERTY_EAXBUFFER_DIRECT
:
2531 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lDirect
,
2534 case DSPROPERTY_EAXBUFFER_DIRECTHF
:
2535 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lDirectHF
,
2539 case DSPROPERTY_EAXBUFFER_ROOM
:
2540 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lRoom
,
2543 case DSPROPERTY_EAXBUFFER_ROOMHF
:
2544 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lRoomHF
,
2548 case DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR
:
2549 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.flRoomRolloffFactor
,
2553 case DSPROPERTY_EAXBUFFER_OBSTRUCTION
:
2554 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lObstruction
,
2557 case DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO
:
2558 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.flObstructionLFRatio
,
2562 case DSPROPERTY_EAXBUFFER_OCCLUSION
:
2563 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lOcclusion
,
2566 case DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO
:
2567 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.flOcclusionLFRatio
,
2570 case DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO
:
2571 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.flOcclusionRoomRatio
,
2575 case DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF
:
2576 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.lOutsideVolumeHF
,
2580 case DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR
:
2581 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.flAirAbsorptionFactor
,
2585 case DSPROPERTY_EAXBUFFER_FLAGS
:
2586 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, This
->eax_prop
.dwFlags
,
2591 hr
= E_PROP_ID_UNSUPPORTED
;
2592 FIXME("Unhandled buffer propid: 0x%08lx\n", dwPropID
);
2596 LeaveCriticalSection(This
->crst
);
2598 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
2600 DS8Primary
*prim
= This
->primary
;
2602 EnterCriticalSection(This
->crst
);
2604 hr
= DSERR_INVALIDPARAM
;
2605 if(prim
->effect
== 0)
2606 hr
= E_PROP_ID_UNSUPPORTED
;
2607 else switch(dwPropID
)
2609 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
2610 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
, prim
->eax_prop
,
2611 EAXLISTENERPROPERTIES
);
2614 case DSPROPERTY_EAXLISTENER_ROOM
:
2615 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2616 prim
->eax_prop
.lRoom
, LONG
);
2618 case DSPROPERTY_EAXLISTENER_ROOMHF
:
2619 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2620 prim
->eax_prop
.lRoomHF
, LONG
);
2623 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
2624 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2625 prim
->eax_prop
.flRoomRolloffFactor
, FLOAT
);
2628 case DSPROPERTY_EAXLISTENER_DECAYTIME
:
2629 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2630 prim
->eax_prop
.flDecayTime
, FLOAT
);
2632 case DSPROPERTY_EAXLISTENER_DECAYHFRATIO
:
2633 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2634 prim
->eax_prop
.flDecayHFRatio
, FLOAT
);
2637 case DSPROPERTY_EAXLISTENER_REFLECTIONS
:
2638 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2639 prim
->eax_prop
.lReflections
, LONG
);
2641 case DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY
:
2642 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2643 prim
->eax_prop
.flReflectionsDelay
, FLOAT
);
2646 case DSPROPERTY_EAXLISTENER_REVERB
:
2647 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2648 prim
->eax_prop
.lReverb
, LONG
);
2650 case DSPROPERTY_EAXLISTENER_REVERBDELAY
:
2651 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2652 prim
->eax_prop
.flReverbDelay
, FLOAT
);
2655 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
2656 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2657 prim
->eax_prop
.dwEnvironment
, DWORD
);
2660 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
2661 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2662 prim
->eax_prop
.flEnvironmentSize
, FLOAT
);
2664 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
2665 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2666 prim
->eax_prop
.flEnvironmentDiffusion
, FLOAT
);
2669 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
2670 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2671 prim
->eax_prop
.flAirAbsorptionHF
, FLOAT
);
2674 case DSPROPERTY_EAXLISTENER_FLAGS
:
2675 GET_PROP(&hr
, pcbReturned
, pPropData
, cbPropData
,
2676 prim
->eax_prop
.dwFlags
, DWORD
);
2680 hr
= E_PROP_ID_UNSUPPORTED
;
2681 FIXME("Unhandled listener propid: 0x%08lx\n", dwPropID
);
2685 LeaveCriticalSection(This
->crst
);
2687 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX_ReverbProperties
))
2689 DS8Primary
*prim
= This
->primary
;
2691 EnterCriticalSection(This
->crst
);
2693 hr
= DSERR_INVALIDPARAM
;
2694 if(prim
->effect
== 0)
2695 hr
= E_PROP_ID_UNSUPPORTED
;
2696 else switch(dwPropID
)
2698 case DSPROPERTY_EAX1_ALL
:
2699 if(cbPropData
>= sizeof(EAX1_REVERBPROPERTIES
))
2703 EAX1_REVERBPROPERTIES
*props
;
2704 } data
= { pPropData
};
2706 data
.props
->dwEnvironment
= prim
->eax_prop
.dwEnvironment
;
2707 data
.props
->fVolume
= mB_to_gain(prim
->eax_prop
.lRoom
);
2708 data
.props
->fDecayTime
= prim
->eax_prop
.flDecayTime
;
2709 data
.props
->fDamping
= prim
->eax1_dampening
;
2711 *pcbReturned
= sizeof(EAX1_REVERBPROPERTIES
);
2716 case DSPROPERTY_EAX1_ENVIRONMENT
:
2717 if(cbPropData
>= sizeof(DWORD
))
2722 } data
= { pPropData
};
2724 *data
.props
= prim
->eax_prop
.dwEnvironment
;
2726 *pcbReturned
= sizeof(DWORD
);
2731 case DSPROPERTY_EAX1_VOLUME
:
2732 if(cbPropData
>= sizeof(float))
2737 } data
= { pPropData
};
2739 *data
.props
= mB_to_gain(prim
->eax_prop
.lRoom
);
2741 *pcbReturned
= sizeof(float);
2746 case DSPROPERTY_EAX1_DECAYTIME
:
2747 if(cbPropData
>= sizeof(float))
2752 } data
= { pPropData
};
2754 *data
.props
= prim
->eax_prop
.flDecayTime
;
2756 *pcbReturned
= sizeof(float);
2761 case DSPROPERTY_EAX1_DAMPING
:
2762 if(cbPropData
>= sizeof(float))
2767 } data
= { pPropData
};
2769 *data
.props
= prim
->eax1_dampening
;
2771 *pcbReturned
= sizeof(float);
2777 hr
= E_PROP_ID_UNSUPPORTED
;
2778 FIXME("Unhandled EAX1 listener propid: 0x%08lx\n", dwPropID
);
2782 LeaveCriticalSection(This
->crst
);
2784 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAXBUFFER_ReverbProperties
))
2786 EnterCriticalSection(This
->crst
);
2788 hr
= DSERR_INVALIDPARAM
;
2789 if(This
->filter
[0] == 0)
2790 hr
= E_PROP_ID_UNSUPPORTED
;
2791 else switch(dwPropID
)
2793 /* NOTE: DSPROPERTY_EAX1BUFFER_ALL is for EAX1BUFFER_REVERBPROPERTIES,
2794 * however that struct just contains the single ReverbMix float
2797 case DSPROPERTY_EAX1BUFFER_ALL
:
2798 case DSPROPERTY_EAX1BUFFER_REVERBMIX
:
2799 if(cbPropData
>= sizeof(float))
2804 } data
= { pPropData
};
2806 *data
.props
= mB_to_gain(This
->eax_prop
.lRoom
);
2807 *pcbReturned
= sizeof(float);
2813 hr
= E_PROP_ID_UNSUPPORTED
;
2814 FIXME("Unhandled EAX1 buffer propid: 0x%08lx\n", dwPropID
);
2818 LeaveCriticalSection(This
->crst
);
2821 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
2827 static HRESULT WINAPI
DS8BufferProp_Set(IKsPropertySet
*iface
,
2828 REFGUID guidPropSet
, ULONG dwPropID
,
2829 LPVOID pInstanceData
, ULONG cbInstanceData
,
2830 LPVOID pPropData
, ULONG cbPropData
)
2832 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
2833 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
2835 TRACE("(%p)->(%s, %lu, %p, %lu, %p, %lu)\n", iface
, debugstr_guid(guidPropSet
),
2836 dwPropID
, pInstanceData
, cbInstanceData
, pPropData
, cbPropData
);
2838 if(cbPropData
> 0 && !pPropData
)
2840 WARN("pPropData is NULL with cbPropData > 0\n");
2844 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
2846 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXBUFFER_DEFERRED
;
2847 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXBUFFER_DEFERRED
);
2849 EnterCriticalSection(This
->crst
);
2850 setALContext(This
->ctx
);
2852 hr
= DSERR_INVALIDPARAM
;
2853 if(This
->filter
[0] == 0)
2854 hr
= E_PROP_ID_UNSUPPORTED
;
2857 case DSPROPERTY_EAXBUFFER_NONE
: /* not setting any property, just applying */
2861 case DSPROPERTY_EAXBUFFER_ALLPARAMETERS
:
2862 if(cbPropData
>= sizeof(EAX20BUFFERPROPERTIES
))
2866 const EAX20BUFFERPROPERTIES
*props
;
2867 } data
= { pPropData
};
2869 This
->eax_prop
= *data
.props
;
2870 ApplyFilterParams(This
, data
.props
, APPLY_DRY_PARAMS
|APPLY_WET_PARAMS
);
2872 This
->dirty
.bit
.dry_filter
= 1;
2873 This
->dirty
.bit
.wet_filter
= 1;
2874 This
->dirty
.bit
.room_rolloff
= 1;
2875 This
->dirty
.bit
.cone_outsidevolumehf
= 1;
2876 This
->dirty
.bit
.air_absorb
= 1;
2877 This
->dirty
.bit
.flags
= 1;
2882 case DSPROPERTY_EAXBUFFER_DIRECT
:
2883 if(cbPropData
>= sizeof(LONG
))
2888 } data
= { pPropData
};
2890 This
->eax_prop
.lDirect
= *data
.props
;
2891 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
);
2893 This
->dirty
.bit
.dry_filter
= 1;
2897 case DSPROPERTY_EAXBUFFER_DIRECTHF
:
2898 if(cbPropData
>= sizeof(LONG
))
2903 } data
= { pPropData
};
2905 This
->eax_prop
.lDirectHF
= *data
.props
;
2906 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
);
2908 This
->dirty
.bit
.dry_filter
= 1;
2913 case DSPROPERTY_EAXBUFFER_ROOM
:
2914 if(cbPropData
>= sizeof(LONG
))
2919 } data
= { pPropData
};
2921 This
->eax_prop
.lRoom
= *data
.props
;
2922 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_WET_PARAMS
);
2924 This
->dirty
.bit
.wet_filter
= 1;
2928 case DSPROPERTY_EAXBUFFER_ROOMHF
:
2929 if(cbPropData
>= sizeof(LONG
))
2934 } data
= { pPropData
};
2936 This
->eax_prop
.lRoomHF
= *data
.props
;
2937 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_WET_PARAMS
);
2939 This
->dirty
.bit
.wet_filter
= 1;
2944 case DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR
:
2945 if(cbPropData
>= sizeof(FLOAT
))
2950 } data
= { pPropData
};
2952 This
->eax_prop
.flRoomRolloffFactor
= *data
.props
;
2954 This
->dirty
.bit
.room_rolloff
= 1;
2959 case DSPROPERTY_EAXBUFFER_OBSTRUCTION
:
2960 if(cbPropData
>= sizeof(LONG
))
2965 } data
= { pPropData
};
2967 This
->eax_prop
.lObstruction
= *data
.props
;
2968 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
);
2970 This
->dirty
.bit
.dry_filter
= 1;
2974 case DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO
:
2975 if(cbPropData
>= sizeof(FLOAT
))
2980 } data
= { pPropData
};
2982 This
->eax_prop
.flObstructionLFRatio
= *data
.props
;
2983 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
);
2985 This
->dirty
.bit
.dry_filter
= 1;
2990 case DSPROPERTY_EAXBUFFER_OCCLUSION
:
2991 if(cbPropData
>= sizeof(LONG
))
2996 } data
= { pPropData
};
2998 This
->eax_prop
.lOcclusion
= *data
.props
;
2999 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
|APPLY_WET_PARAMS
);
3001 This
->dirty
.bit
.dry_filter
= 1;
3002 This
->dirty
.bit
.wet_filter
= 1;
3006 case DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO
:
3007 if(cbPropData
>= sizeof(FLOAT
))
3012 } data
= { pPropData
};
3014 This
->eax_prop
.flOcclusionLFRatio
= *data
.props
;
3015 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
|APPLY_WET_PARAMS
);
3017 This
->dirty
.bit
.dry_filter
= 1;
3018 This
->dirty
.bit
.wet_filter
= 1;
3022 case DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO
:
3023 if(cbPropData
>= sizeof(FLOAT
))
3028 } data
= { pPropData
};
3030 This
->eax_prop
.flOcclusionRoomRatio
= *data
.props
;
3031 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_DRY_PARAMS
|APPLY_WET_PARAMS
);
3033 This
->dirty
.bit
.dry_filter
= 1;
3034 This
->dirty
.bit
.wet_filter
= 1;
3039 case DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF
:
3040 if(cbPropData
>= sizeof(LONG
))
3045 } data
= { pPropData
};
3047 This
->eax_prop
.lOutsideVolumeHF
= *data
.props
;
3049 This
->dirty
.bit
.cone_outsidevolumehf
= 1;
3054 case DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR
:
3055 if(cbPropData
>= sizeof(FLOAT
))
3060 } data
= { pPropData
};
3062 This
->eax_prop
.flAirAbsorptionFactor
= *data
.props
;
3064 This
->dirty
.bit
.air_absorb
= 1;
3069 case DSPROPERTY_EAXBUFFER_FLAGS
:
3070 if(cbPropData
>= sizeof(DWORD
))
3075 } data
= { pPropData
};
3077 This
->eax_prop
.dwFlags
= *data
.props
;
3079 This
->dirty
.bit
.flags
= 1;
3085 hr
= E_PROP_ID_UNSUPPORTED
;
3086 FIXME("Unhandled buffer propid: 0x%08lx\n", propid
);
3090 if(hr
== DS_OK
&& immediate
)
3091 DS8Primary3D_CommitDeferredSettings(&This
->primary
->IDirectSound3DListener_iface
);
3094 LeaveCriticalSection(This
->crst
);
3096 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
3098 DS8Primary
*prim
= This
->primary
;
3099 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
3100 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
3102 EnterCriticalSection(prim
->crst
);
3103 setALContext(prim
->ctx
);
3105 hr
= DSERR_INVALIDPARAM
;
3106 if(prim
->effect
== 0)
3107 hr
= E_PROP_ID_UNSUPPORTED
;
3110 case DSPROPERTY_EAXLISTENER_NONE
: /* not setting any property, just applying */
3114 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
3115 if(cbPropData
>= sizeof(EAXLISTENERPROPERTIES
))
3119 const EAXLISTENERPROPERTIES
*props
;
3120 } data
= { pPropData
};
3122 ApplyReverbParams(prim
, data
.props
);
3127 case DSPROPERTY_EAXLISTENER_ROOM
:
3128 if(cbPropData
>= sizeof(LONG
))
3133 } data
= { pPropData
};
3135 prim
->eax_prop
.lRoom
= *data
.l
;
3136 alEffectf(prim
->effect
, AL_REVERB_GAIN
,
3137 mB_to_gain(prim
->eax_prop
.lRoom
));
3140 prim
->dirty
.bit
.effect
= 1;
3144 case DSPROPERTY_EAXLISTENER_ROOMHF
:
3145 if(cbPropData
>= sizeof(LONG
))
3150 } data
= { pPropData
};
3152 prim
->eax_prop
.lRoomHF
= *data
.l
;
3153 alEffectf(prim
->effect
, AL_REVERB_GAINHF
,
3154 mB_to_gain(prim
->eax_prop
.lRoomHF
));
3157 prim
->dirty
.bit
.effect
= 1;
3162 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
3163 if(cbPropData
>= sizeof(FLOAT
))
3168 } data
= { pPropData
};
3170 prim
->eax_prop
.flRoomRolloffFactor
= *data
.fl
;
3171 alEffectf(prim
->effect
, AL_REVERB_ROOM_ROLLOFF_FACTOR
,
3172 prim
->eax_prop
.flRoomRolloffFactor
);
3175 prim
->dirty
.bit
.effect
= 1;
3180 case DSPROPERTY_EAXLISTENER_DECAYTIME
:
3181 if(cbPropData
>= sizeof(FLOAT
))
3186 } data
= { pPropData
};
3188 prim
->eax_prop
.flDecayTime
= *data
.fl
;
3189 alEffectf(prim
->effect
, AL_REVERB_DECAY_TIME
,
3190 prim
->eax_prop
.flDecayTime
);
3193 prim
->dirty
.bit
.effect
= 1;
3197 case DSPROPERTY_EAXLISTENER_DECAYHFRATIO
:
3198 if(cbPropData
>= sizeof(FLOAT
))
3203 } data
= { pPropData
};
3205 prim
->eax_prop
.flDecayHFRatio
= *data
.fl
;
3206 alEffectf(prim
->effect
, AL_REVERB_DECAY_HFRATIO
,
3207 prim
->eax_prop
.flDecayHFRatio
);
3210 prim
->dirty
.bit
.effect
= 1;
3215 case DSPROPERTY_EAXLISTENER_REFLECTIONS
:
3216 if(cbPropData
>= sizeof(LONG
))
3221 } data
= { pPropData
};
3223 prim
->eax_prop
.lReflections
= *data
.l
;
3224 alEffectf(prim
->effect
, AL_REVERB_REFLECTIONS_GAIN
,
3225 mB_to_gain(prim
->eax_prop
.lReflections
));
3228 prim
->dirty
.bit
.effect
= 1;
3232 case DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY
:
3233 if(cbPropData
>= sizeof(FLOAT
))
3238 } data
= { pPropData
};
3240 prim
->eax_prop
.flReflectionsDelay
= *data
.fl
;
3241 alEffectf(prim
->effect
, AL_REVERB_REFLECTIONS_DELAY
,
3242 prim
->eax_prop
.flReflectionsDelay
);
3245 prim
->dirty
.bit
.effect
= 1;
3250 case DSPROPERTY_EAXLISTENER_REVERB
:
3251 if(cbPropData
>= sizeof(LONG
))
3256 } data
= { pPropData
};
3258 prim
->eax_prop
.lReverb
= *data
.l
;
3259 alEffectf(prim
->effect
, AL_REVERB_LATE_REVERB_GAIN
,
3260 mB_to_gain(prim
->eax_prop
.lReverb
));
3263 prim
->dirty
.bit
.effect
= 1;
3267 case DSPROPERTY_EAXLISTENER_REVERBDELAY
:
3268 if(cbPropData
>= sizeof(FLOAT
))
3273 } data
= { pPropData
};
3275 prim
->eax_prop
.flReverbDelay
= *data
.fl
;
3276 alEffectf(prim
->effect
, AL_REVERB_LATE_REVERB_DELAY
,
3277 prim
->eax_prop
.flReverbDelay
);
3280 prim
->dirty
.bit
.effect
= 1;
3285 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
3286 if(cbPropData
>= sizeof(DWORD
))
3291 } data
= { pPropData
};
3293 if(*data
.dw
<= EAX_MAX_ENVIRONMENT
)
3295 ApplyReverbParams(prim
, &EnvironmentDefaults
[*data
.dw
]);
3301 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
3302 if(cbPropData
>= sizeof(FLOAT
))
3307 } data
= { pPropData
};
3309 if(*data
.fl
>= 1.0f
&& *data
.fl
<= 100.0f
)
3311 float scale
= (*data
.fl
)/prim
->eax_prop
.flEnvironmentSize
;
3313 prim
->eax_prop
.flEnvironmentSize
= *data
.fl
;
3315 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYTIMESCALE
))
3317 prim
->eax_prop
.flDecayTime
*= scale
;
3318 prim
->eax_prop
.flDecayTime
= clampF(prim
->eax_prop
.flDecayTime
, 0.1f
, 20.0f
);
3320 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSSCALE
))
3322 prim
->eax_prop
.lReflections
-= gain_to_mB(scale
);
3323 prim
->eax_prop
.lReflections
= clampI(prim
->eax_prop
.lReflections
, -10000, 1000);
3325 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE
))
3327 prim
->eax_prop
.flReflectionsDelay
*= scale
;
3328 prim
->eax_prop
.flReflectionsDelay
= clampF(prim
->eax_prop
.flReflectionsDelay
, 0.0f
, 0.3f
);
3330 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBSCALE
))
3332 prim
->eax_prop
.lReverb
-= gain_to_mB(scale
);
3333 prim
->eax_prop
.lReverb
= clampI(prim
->eax_prop
.lReverb
, -10000, 2000);
3335 if((prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_REVERBDELAYSCALE
))
3337 prim
->eax_prop
.flReverbDelay
*= scale
;
3338 prim
->eax_prop
.flReverbDelay
= clampF(prim
->eax_prop
.flReverbDelay
, 0.0f
, 0.1f
);
3341 ApplyReverbParams(prim
, &prim
->eax_prop
);
3346 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
3347 if(cbPropData
>= sizeof(FLOAT
))
3352 } data
= { pPropData
};
3354 prim
->eax_prop
.flEnvironmentDiffusion
= *data
.fl
;
3355 alEffectf(prim
->effect
, AL_REVERB_DIFFUSION
,
3356 prim
->eax_prop
.flEnvironmentDiffusion
);
3359 prim
->dirty
.bit
.effect
= 1;
3364 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
3365 if(cbPropData
>= sizeof(FLOAT
))
3370 } data
= { pPropData
};
3372 prim
->eax_prop
.flAirAbsorptionHF
= *data
.fl
;
3373 alEffectf(prim
->effect
, AL_REVERB_AIR_ABSORPTION_GAINHF
,
3374 mB_to_gain(prim
->eax_prop
.flAirAbsorptionHF
));
3377 prim
->dirty
.bit
.effect
= 1;
3382 case DSPROPERTY_EAXLISTENER_FLAGS
:
3383 if(cbPropData
>= sizeof(DWORD
))
3388 } data
= { pPropData
};
3390 prim
->eax_prop
.dwFlags
= *data
.dw
;
3391 alEffecti(prim
->effect
, AL_REVERB_DECAY_HFLIMIT
,
3392 (prim
->eax_prop
.dwFlags
&EAXLISTENERFLAGS_DECAYHFLIMIT
) ?
3393 AL_TRUE
: AL_FALSE
);
3396 prim
->dirty
.bit
.effect
= 1;
3402 hr
= E_PROP_ID_UNSUPPORTED
;
3403 FIXME("Unhandled listener propid: 0x%08lx\n", propid
);
3407 if(hr
== DS_OK
&& immediate
)
3408 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
3411 LeaveCriticalSection(prim
->crst
);
3413 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX_ReverbProperties
))
3415 static const float eax1_env_dampening
[EAX_ENVIRONMENT_COUNT
] = {
3416 0.5f
, 0.0f
, 0.666f
, 0.166f
, 0.0f
, 0.888f
, 0.5f
, 0.5f
, 1.304f
,
3417 0.332f
, 0.3f
, 2.0f
, 0.0f
, 0.638f
, 0.776f
, 0.472f
, 0.224f
, 0.472f
,
3418 0.5f
, 0.224f
, 1.5f
, 0.25f
, 0.0f
, 1.388f
, 0.666f
, 0.806f
3420 DS8Primary
*prim
= This
->primary
;
3421 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXLISTENER_DEFERRED
;
3422 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXLISTENER_DEFERRED
);
3424 EnterCriticalSection(prim
->crst
);
3425 setALContext(prim
->ctx
);
3427 hr
= DSERR_INVALIDPARAM
;
3428 if(prim
->effect
== 0)
3429 hr
= E_PROP_ID_UNSUPPORTED
;
3432 case DSPROPERTY_EAX1_ALL
:
3433 if(cbPropData
>= sizeof(EAX1_REVERBPROPERTIES
))
3437 const EAX1_REVERBPROPERTIES
*props
;
3438 } data
= { pPropData
};
3440 if(data
.props
->dwEnvironment
< EAX_ENVIRONMENT_COUNT
)
3442 EAX20LISTENERPROPERTIES env
= EnvironmentDefaults
[data
.props
->dwEnvironment
];
3443 env
.lRoom
= gain_to_mB(data
.props
->fVolume
);
3444 env
.flDecayTime
= data
.props
->fDecayTime
;
3445 prim
->eax1_dampening
= data
.props
->fDamping
;
3446 ApplyReverbParams(prim
, &env
);
3452 case DSPROPERTY_EAX1_ENVIRONMENT
:
3453 if(cbPropData
>= sizeof(DWORD
))
3458 } data
= { pPropData
};
3460 if(*data
.dw
< EAX_ENVIRONMENT_COUNT
)
3462 prim
->eax1_dampening
= eax1_env_dampening
[*data
.dw
];
3463 ApplyReverbParams(prim
, &EnvironmentDefaults
[*data
.dw
]);
3469 case DSPROPERTY_EAX1_VOLUME
:
3470 if(cbPropData
>= sizeof(FLOAT
))
3475 } data
= { pPropData
};
3477 prim
->eax_prop
.lRoom
= gain_to_mB(*data
.l
);
3478 alEffectf(prim
->effect
, AL_REVERB_GAIN
,
3479 mB_to_gain(prim
->eax_prop
.lRoom
));
3482 prim
->dirty
.bit
.effect
= 1;
3486 case DSPROPERTY_EAX1_DECAYTIME
:
3487 if(cbPropData
>= sizeof(FLOAT
))
3492 } data
= { pPropData
};
3494 prim
->eax_prop
.flDecayTime
= *data
.fl
;
3495 alEffectf(prim
->effect
, AL_REVERB_DECAY_TIME
,
3496 prim
->eax_prop
.flDecayTime
);
3499 prim
->dirty
.bit
.effect
= 1;
3503 case DSPROPERTY_EAX1_DAMPING
:
3504 if(cbPropData
>= sizeof(FLOAT
))
3509 } data
= { pPropData
};
3511 prim
->eax1_dampening
= *data
.fl
;
3518 hr
= E_PROP_ID_UNSUPPORTED
;
3519 FIXME("Unhandled EAX1 listener propid: 0x%08lx\n", propid
);
3523 if(hr
== DS_OK
&& immediate
)
3524 DS8Primary3D_CommitDeferredSettings(&prim
->IDirectSound3DListener_iface
);
3527 LeaveCriticalSection(prim
->crst
);
3529 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAXBUFFER_ReverbProperties
))
3531 DWORD propid
= dwPropID
& ~DSPROPERTY_EAXBUFFER_DEFERRED
;
3532 BOOL immediate
= !(dwPropID
&DSPROPERTY_EAXBUFFER_DEFERRED
);
3534 EnterCriticalSection(This
->crst
);
3535 setALContext(This
->ctx
);
3537 hr
= DSERR_INVALIDPARAM
;
3538 if(This
->filter
[0] == 0)
3539 hr
= E_PROP_ID_UNSUPPORTED
;
3542 case DSPROPERTY_EAX1BUFFER_ALL
:
3543 case DSPROPERTY_EAX1BUFFER_REVERBMIX
:
3544 if(cbPropData
>= sizeof(FLOAT
))
3549 } data
= { pPropData
};
3551 This
->eax_prop
.lRoom
= gain_to_mB(*data
.props
);
3552 ApplyFilterParams(This
, &This
->eax_prop
, APPLY_WET_PARAMS
);
3554 This
->dirty
.bit
.wet_filter
= 1;
3560 hr
= E_PROP_ID_UNSUPPORTED
;
3561 FIXME("Unhandled EAX1 buffer propid: 0x%08lx\n", propid
);
3565 if(hr
== DS_OK
&& immediate
)
3566 DS8Primary3D_CommitDeferredSettings(&This
->primary
->IDirectSound3DListener_iface
);
3569 LeaveCriticalSection(This
->crst
);
3572 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
3577 static HRESULT WINAPI
DS8BufferProp_QuerySupport(IKsPropertySet
*iface
,
3578 REFGUID guidPropSet
, ULONG dwPropID
,
3579 ULONG
*pTypeSupport
)
3581 DS8Buffer
*This
= impl_from_IKsPropertySet(iface
);
3582 HRESULT hr
= E_PROP_ID_UNSUPPORTED
;
3584 TRACE("(%p)->(%s, %lu, %p)\n", iface
, debugstr_guid(guidPropSet
), dwPropID
, pTypeSupport
);
3590 if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_BufferProperties
))
3592 EnterCriticalSection(This
->crst
);
3594 if(This
->filter
[0] == 0)
3595 hr
= E_PROP_ID_UNSUPPORTED
;
3596 else switch(dwPropID
)
3598 case DSPROPERTY_EAXBUFFER_NONE
:
3599 *pTypeSupport
= KSPROPERTY_SUPPORT_SET
;
3602 case DSPROPERTY_EAXBUFFER_ALLPARAMETERS
:
3603 case DSPROPERTY_EAXBUFFER_DIRECT
:
3604 case DSPROPERTY_EAXBUFFER_DIRECTHF
:
3605 case DSPROPERTY_EAXBUFFER_ROOM
:
3606 case DSPROPERTY_EAXBUFFER_ROOMHF
:
3607 case DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR
:
3608 case DSPROPERTY_EAXBUFFER_OBSTRUCTION
:
3609 case DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO
:
3610 case DSPROPERTY_EAXBUFFER_OCCLUSION
:
3611 case DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO
:
3612 case DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO
:
3613 case DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF
:
3614 case DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR
:
3615 case DSPROPERTY_EAXBUFFER_FLAGS
:
3616 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
3620 hr
= E_PROP_ID_UNSUPPORTED
;
3621 FIXME("Unhandled EAX2 buffer propid: 0x%08lx\n", dwPropID
);
3625 LeaveCriticalSection(This
->crst
);
3627 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX20_ListenerProperties
))
3629 DS8Primary
*prim
= This
->primary
;
3631 EnterCriticalSection(This
->crst
);
3633 if(prim
->effect
== 0)
3634 hr
= E_PROP_ID_UNSUPPORTED
;
3635 else switch(dwPropID
)
3637 case DSPROPERTY_EAXLISTENER_NONE
:
3638 *pTypeSupport
= KSPROPERTY_SUPPORT_SET
;
3641 case DSPROPERTY_EAXLISTENER_ALLPARAMETERS
:
3642 case DSPROPERTY_EAXLISTENER_ROOM
:
3643 case DSPROPERTY_EAXLISTENER_ROOMHF
:
3644 case DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR
:
3645 case DSPROPERTY_EAXLISTENER_DECAYTIME
:
3646 case DSPROPERTY_EAXLISTENER_DECAYHFRATIO
:
3647 case DSPROPERTY_EAXLISTENER_REFLECTIONS
:
3648 case DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY
:
3649 case DSPROPERTY_EAXLISTENER_REVERB
:
3650 case DSPROPERTY_EAXLISTENER_REVERBDELAY
:
3651 case DSPROPERTY_EAXLISTENER_ENVIRONMENT
:
3652 case DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE
:
3653 case DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION
:
3654 case DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF
:
3655 case DSPROPERTY_EAXLISTENER_FLAGS
:
3656 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
3660 hr
= E_PROP_ID_UNSUPPORTED
;
3661 FIXME("Unhandled EAX2 listener propid: 0x%08lx\n", dwPropID
);
3665 LeaveCriticalSection(This
->crst
);
3667 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAX_ReverbProperties
))
3669 DS8Primary
*prim
= This
->primary
;
3671 EnterCriticalSection(This
->crst
);
3673 if(prim
->effect
== 0)
3674 hr
= E_PROP_ID_UNSUPPORTED
;
3675 else switch(dwPropID
)
3677 case DSPROPERTY_EAX1_ALL
:
3678 case DSPROPERTY_EAX1_ENVIRONMENT
:
3679 case DSPROPERTY_EAX1_VOLUME
:
3680 case DSPROPERTY_EAX1_DECAYTIME
:
3681 case DSPROPERTY_EAX1_DAMPING
:
3682 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
3686 hr
= E_PROP_ID_UNSUPPORTED
;
3687 FIXME("Unhandled EAX1 listener propid: 0x%08lx\n", dwPropID
);
3691 LeaveCriticalSection(This
->crst
);
3693 else if(IsEqualIID(guidPropSet
, &DSPROPSETID_EAXBUFFER_ReverbProperties
))
3695 EnterCriticalSection(This
->crst
);
3697 if(This
->filter
[0] == 0)
3698 hr
= E_PROP_ID_UNSUPPORTED
;
3699 else switch(dwPropID
)
3701 case DSPROPERTY_EAX1BUFFER_ALL
:
3702 case DSPROPERTY_EAX1BUFFER_REVERBMIX
:
3703 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
3707 hr
= E_PROP_ID_UNSUPPORTED
;
3708 FIXME("Unhandled EAX1 buffer propid: 0x%08lx\n", dwPropID
);
3712 LeaveCriticalSection(This
->crst
);
3715 FIXME("Unhandled propset: %s\n", debugstr_guid(guidPropSet
));
3720 static const IKsPropertySetVtbl DS8BufferProp_Vtbl
=
3722 DS8BufferProp_QueryInterface
,
3723 DS8BufferProp_AddRef
,
3724 DS8BufferProp_Release
,
3727 DS8BufferProp_QuerySupport