2 * Tests the panning and 3D functions of DirectSound
4 * Part of this test involves playing test tones. But this only makes
5 * sense if someone is going to carefully listen to it, and would only
6 * bother everyone else.
7 * So this is only done if the test is being run in interactive mode.
9 * Copyright (c) 2002-2004 Francois Gouget
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
35 #include "dsound_test.h"
37 #define PI 3.14159265358979323846
39 char* wave_generate_la(WAVEFORMATEX
* wfx
, double duration
, DWORD
* size
, BOOL ieee
)
46 nb_samples
=(int)(duration
*wfx
->nSamplesPerSec
);
47 *size
=nb_samples
*wfx
->nBlockAlign
;
48 b
=buf
=HeapAlloc(GetProcessHeap(), 0, *size
);
49 for (i
=0;i
<nb_samples
;i
++) {
50 double y
=sin(440.0*2*PI
*i
/wfx
->nSamplesPerSec
);
51 if (wfx
->wBitsPerSample
==8) {
52 unsigned char sample
=127.5*(y
+1.0);
54 if (wfx
->nChannels
==2)
56 } else if (wfx
->wBitsPerSample
== 16) {
57 signed short sample
=32767.5*y
-0.5;
61 if (wfx
->nChannels
==2) {
66 } else if (wfx
->wBitsPerSample
== 24) {
67 signed int sample
=8388607.5*y
-0.5;
69 b
[1]=(sample
>> 8)&0xff;
72 if (wfx
->nChannels
==2) {
74 b
[1]=(sample
>> 8)&0xff;
78 } else if (wfx
->wBitsPerSample
== 32) {
80 float *ptr
= (float *) b
;
86 if (wfx
->nChannels
==2) {
91 signed int sample
=2147483647.5*y
-0.5;
93 b
[1]=(sample
>> 8)&0xff;
94 b
[2]=(sample
>> 16)&0xff;
97 if (wfx
->nChannels
==2) {
99 b
[1]=(sample
>> 8)&0xff;
100 b
[2]=(sample
>> 16)&0xff;
110 const char * getDSBCAPS(DWORD xmask
) {
115 #define FE(x) { x, #x },
116 FE(DSBCAPS_PRIMARYBUFFER
)
118 FE(DSBCAPS_LOCHARDWARE
)
119 FE(DSBCAPS_LOCSOFTWARE
)
121 FE(DSBCAPS_CTRLFREQUENCY
)
123 FE(DSBCAPS_CTRLVOLUME
)
124 FE(DSBCAPS_CTRLPOSITIONNOTIFY
)
125 FE(DSBCAPS_STICKYFOCUS
)
126 FE(DSBCAPS_GLOBALFOCUS
)
127 FE(DSBCAPS_GETCURRENTPOSITION2
)
128 FE(DSBCAPS_MUTE3DATMAXDISTANCE
)
131 static char buffer
[512];
137 for (i
= 0; i
< ARRAY_SIZE(flags
); i
++) {
138 if ((flags
[i
].mask
& xmask
) == flags
[i
].mask
) {
143 strcat(buffer
, flags
[i
].name
);
152 HWND hwnd
=GetForegroundWindow();
154 hwnd
=GetDesktopWindow();
158 void init_format(WAVEFORMATEX
* wfx
, int format
, int rate
, int depth
,
161 wfx
->wFormatTag
=format
;
162 wfx
->nChannels
=channels
;
163 wfx
->wBitsPerSample
=depth
;
164 wfx
->nSamplesPerSec
=rate
;
165 wfx
->nBlockAlign
=wfx
->nChannels
*wfx
->wBitsPerSample
/8;
166 /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */
167 if (wfx
->nBlockAlign
==0)
169 /* align compressed formats to byte boundary */
172 wfx
->nAvgBytesPerSec
=wfx
->nSamplesPerSec
*wfx
->nBlockAlign
;
180 LPDIRECTSOUNDBUFFER dsbo
;
188 static int buffer_refill(play_state_t
* state
, DWORD size
)
194 if (size
>state
->wave_len
-state
->written
)
195 size
=state
->wave_len
-state
->written
;
197 /* some broken apps like Navyfield mistakenly pass NULL for a ppValue */
198 rc
=IDirectSoundBuffer_Lock(state
->dsbo
,state
->offset
,size
,
199 &ptr1
,NULL
,&ptr2
,&len2
,0);
200 ok(rc
==DSERR_INVALIDPARAM
,"expected %08lx got %08lx\n",DSERR_INVALIDPARAM
, rc
);
201 rc
=IDirectSoundBuffer_Lock(state
->dsbo
,state
->offset
,size
,
202 &ptr1
,&len1
,&ptr2
,&len2
,0);
203 ok(rc
==DS_OK
,"IDirectSoundBuffer_Lock() failed: %08lx\n", rc
);
207 memcpy(ptr1
,state
->wave
+state
->written
,len1
);
208 state
->written
+=len1
;
210 memcpy(ptr2
,state
->wave
+state
->written
,len2
);
211 state
->written
+=len2
;
213 state
->offset
=state
->written
% state
->buffer_size
;
214 /* some apps blindly pass &ptr1 instead of ptr1 */
215 rc
=IDirectSoundBuffer_Unlock(state
->dsbo
,&ptr1
,len1
,ptr2
,len2
);
216 ok(rc
==DSERR_INVALIDPARAM
, "IDDirectSoundBuffer_Unlock(): expected %08lx got %08lx, %p %p\n",DSERR_INVALIDPARAM
, rc
, &ptr1
, ptr1
);
217 rc
=IDirectSoundBuffer_Unlock(state
->dsbo
,ptr1
,len1
,ptr2
,len2
);
218 ok(rc
==DS_OK
,"IDirectSoundBuffer_Unlock() failed: %08lx\n", rc
);
224 static int buffer_silence(play_state_t
* state
, DWORD size
)
231 rc
=IDirectSoundBuffer_Lock(state
->dsbo
,state
->offset
,size
,
232 &ptr1
,&len1
,&ptr2
,&len2
,0);
233 ok(rc
==DS_OK
,"IDirectSoundBuffer_Lock() failed: %08lx\n", rc
);
237 s
=(state
->wfx
->wBitsPerSample
==8?0x80:0);
242 state
->offset
=(state
->offset
+size
) % state
->buffer_size
;
243 rc
=IDirectSoundBuffer_Unlock(state
->dsbo
,ptr1
,len1
,ptr2
,len2
);
244 ok(rc
==DS_OK
,"IDirectSoundBuffer_Unlock() failed: %08lx\n", rc
);
250 static BOOL
buffer_service(play_state_t
* state
)
252 DWORD last_play_pos
,play_pos
,buf_free
;
255 rc
=IDirectSoundBuffer_GetCurrentPosition(state
->dsbo
,&play_pos
,NULL
);
256 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetCurrentPosition() failed: %08lx\n", rc
);
261 /* Update the amount played */
262 last_play_pos
=state
->played
% state
->buffer_size
;
263 if (play_pos
<last_play_pos
)
264 state
->played
+=state
->buffer_size
-last_play_pos
+play_pos
;
266 state
->played
+=play_pos
-last_play_pos
;
268 if (winetest_debug
> 1)
269 trace("buf size=%ld last_play_pos=%ld play_pos=%ld played=%ld / %ld\n",
270 state
->buffer_size
,last_play_pos
,play_pos
,state
->played
,
273 if (state
->played
>state
->wave_len
)
275 /* Everything has been played */
279 /* Refill the buffer */
280 if (state
->offset
<=play_pos
)
281 buf_free
=play_pos
-state
->offset
;
283 buf_free
=state
->buffer_size
-state
->offset
+play_pos
;
285 if (winetest_debug
> 1)
286 trace("offset=%ld free=%ld written=%ld / %ld\n",
287 state
->offset
,buf_free
,state
->written
,state
->wave_len
);
291 if (state
->written
<state
->wave_len
)
293 int w
=buffer_refill(state
,buf_free
);
297 if (state
->written
==state
->wave_len
&& winetest_debug
> 1)
298 trace("last sound byte at %ld\n",
299 (state
->written
% state
->buffer_size
));
303 /* Fill with silence */
304 if (winetest_debug
> 1)
305 trace("writing %ld bytes of silence\n",buf_free
);
306 if (buffer_silence(state
,buf_free
)==-1)
312 if (winetest_debug
> 1)
313 trace("stopping playback\n");
314 rc
=IDirectSoundBuffer_Stop(state
->dsbo
);
315 ok(rc
==DS_OK
,"IDirectSoundBuffer_Stop() failed: %08lx\n", rc
);
319 void test_buffer(LPDIRECTSOUND dso
, LPDIRECTSOUNDBUFFER
*dsbo
,
320 BOOL is_primary
, BOOL set_volume
, LONG volume
,
321 BOOL set_pan
, LONG pan
, BOOL play
, double duration
,
322 BOOL buffer3d
, LPDIRECTSOUND3DLISTENER listener
,
323 BOOL move_listener
, BOOL move_sound
,
324 BOOL set_frequency
, DWORD frequency
)
328 WAVEFORMATEX wfx
,wfx2
;
329 DWORD size
,status
,freq
;
334 rc
=IDirectSoundBuffer_SetFrequency(*dsbo
,frequency
);
335 ok(rc
==DS_OK
||rc
==DSERR_CONTROLUNAVAIL
,
336 "IDirectSoundBuffer_SetFrequency() failed to set frequency %08lx\n",rc
);
341 /* DSOUND: Error: Invalid caps pointer */
342 rc
=IDirectSoundBuffer_GetCaps(*dsbo
,0);
343 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundBuffer_GetCaps() should have "
344 "returned DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
346 ZeroMemory(&dsbcaps
, sizeof(dsbcaps
));
348 /* DSOUND: Error: Invalid caps pointer */
349 rc
=IDirectSoundBuffer_GetCaps(*dsbo
,&dsbcaps
);
350 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundBuffer_GetCaps() should have "
351 "returned DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
353 dsbcaps
.dwSize
=sizeof(dsbcaps
);
354 rc
=IDirectSoundBuffer_GetCaps(*dsbo
,&dsbcaps
);
355 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetCaps() failed: %08lx\n", rc
);
356 if (rc
==DS_OK
&& winetest_debug
> 1) {
357 trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps
.dwFlags
,
358 dsbcaps
.dwBufferBytes
);
361 /* Query the format size. */
363 rc
=IDirectSoundBuffer_GetFormat(*dsbo
,NULL
,0,&size
);
364 ok(rc
==DS_OK
&& size
!=0,"IDirectSoundBuffer_GetFormat() should have "
365 "returned the needed size: rc=%08lx size=%ld\n",rc
,size
);
367 ok(size
== sizeof(WAVEFORMATEX
) || size
== sizeof(WAVEFORMATEXTENSIBLE
),
368 "Expected a correct structure size, got %ld\n", size
);
370 if (size
== sizeof(WAVEFORMATEX
)) {
371 rc
=IDirectSoundBuffer_GetFormat(*dsbo
,&wfx
,size
,NULL
);
372 ieee
= (wfx
.wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
);
374 else if (size
== sizeof(WAVEFORMATEXTENSIBLE
)) {
375 WAVEFORMATEXTENSIBLE wfxe
;
376 rc
=IDirectSoundBuffer_GetFormat(*dsbo
,(WAVEFORMATEX
*)&wfxe
,size
,NULL
);
378 ieee
= IsEqualGUID(&wfxe
.SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
);
383 "IDirectSoundBuffer_GetFormat() failed: %08lx\n", rc
);
384 if (rc
==DS_OK
&& winetest_debug
> 1) {
385 trace(" Format: %s tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
386 is_primary
? "Primary" : "Secondary",
387 wfx
.wFormatTag
,wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,
388 wfx
.nChannels
,wfx
.nAvgBytesPerSec
,wfx
.nBlockAlign
);
391 /* DSOUND: Error: Invalid frequency buffer */
392 rc
=IDirectSoundBuffer_GetFrequency(*dsbo
,0);
393 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundBuffer_GetFrequency() should have "
394 "returned DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
396 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
397 rc
=IDirectSoundBuffer_GetFrequency(*dsbo
,&freq
);
398 ok((rc
==DS_OK
&& !is_primary
) || (rc
==DSERR_CONTROLUNAVAIL
&&is_primary
) ||
399 (rc
==DSERR_CONTROLUNAVAIL
&&!(dsbcaps
.dwFlags
&DSBCAPS_CTRLFREQUENCY
)),
400 "IDirectSoundBuffer_GetFrequency() failed: %08lx\n",rc
);
402 DWORD f
= set_frequency
?frequency
:wfx
.nSamplesPerSec
;
403 ok(freq
==f
,"The frequency returned by GetFrequency "
404 "%ld does not match the format %ld\n",freq
,f
);
407 /* DSOUND: Error: Invalid status pointer */
408 rc
=IDirectSoundBuffer_GetStatus(*dsbo
,0);
409 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundBuffer_GetStatus() should have "
410 "returned DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
412 rc
=IDirectSoundBuffer_GetStatus(*dsbo
,&status
);
413 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetStatus() failed: %08lx\n", rc
);
414 ok(status
==0,"status=0x%lx instead of 0\n",status
);
418 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
419 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
420 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
421 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08lx\n",rc
);
425 /* DSOUND: Error: Invalid format pointer */
426 rc
=IDirectSoundBuffer_SetFormat(*dsbo
,0);
427 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSoundBuffer_SetFormat() should have "
428 "returned DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
430 init_format(&wfx2
,WAVE_FORMAT_PCM
,11025,16,2);
431 rc
=IDirectSoundBuffer_SetFormat(*dsbo
,&wfx2
);
432 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetFormat(%s) failed: %08lx\n",
433 format_string(&wfx2
), rc
);
435 /* There is no guarantee that SetFormat will actually change the
436 * format to what we asked for. It depends on what the soundcard
437 * supports. So we must re-query the format.
439 rc
=IDirectSoundBuffer_GetFormat(*dsbo
,&wfx
,sizeof(wfx
),NULL
);
440 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetFormat() failed: %08lx\n", rc
);
442 (wfx
.wFormatTag
!=wfx2
.wFormatTag
||
443 wfx
.nSamplesPerSec
!=wfx2
.nSamplesPerSec
||
444 wfx
.wBitsPerSample
!=wfx2
.wBitsPerSample
||
445 wfx
.nChannels
!=wfx2
.nChannels
)) {
446 trace("Requested format tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
447 wfx2
.wFormatTag
,wfx2
.nSamplesPerSec
,wfx2
.wBitsPerSample
,
448 wfx2
.nChannels
,wfx2
.nAvgBytesPerSec
,wfx2
.nBlockAlign
);
449 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
450 wfx
.wFormatTag
,wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,
451 wfx
.nChannels
,wfx
.nAvgBytesPerSec
,wfx
.nBlockAlign
);
454 ZeroMemory(&new_dsbcaps
, sizeof(new_dsbcaps
));
455 new_dsbcaps
.dwSize
= sizeof(new_dsbcaps
);
456 rc
=IDirectSoundBuffer_GetCaps(*dsbo
,&new_dsbcaps
);
457 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetCaps() failed: %08lx\n", rc
);
458 if (rc
==DS_OK
&& winetest_debug
> 1) {
459 trace(" new Caps: flags=0x%08lx size=%ld\n",new_dsbcaps
.dwFlags
,
460 new_dsbcaps
.dwBufferBytes
);
463 /* Check for primary buffer size change */
464 ok(new_dsbcaps
.dwBufferBytes
== dsbcaps
.dwBufferBytes
,
465 " buffer size changed after SetFormat() - "
466 "previous size was %lu, current size is %lu\n",
467 dsbcaps
.dwBufferBytes
, new_dsbcaps
.dwBufferBytes
);
468 dsbcaps
.dwBufferBytes
= new_dsbcaps
.dwBufferBytes
;
470 /* Check for primary buffer flags change */
471 ok(new_dsbcaps
.dwFlags
== dsbcaps
.dwFlags
,
472 " flags changed after SetFormat() - "
473 "previous flags were %08lx, current flags are %08lx\n",
474 dsbcaps
.dwFlags
, new_dsbcaps
.dwFlags
);
476 /* Set the CooperativeLevel back to normal */
477 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
478 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
479 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08lx\n",rc
);
484 DS3DLISTENER listener_param
;
485 LPDIRECTSOUND3DBUFFER buffer
=NULL
;
486 DS3DBUFFER buffer_param
;
487 DWORD start_time
,now
;
491 if (winetest_interactive
) {
493 trace(" Playing %g second 440Hz tone at %ldx%dx%d with a "
494 "frequency of %ld (%ldHz)\n", duration
,
495 wfx
.nSamplesPerSec
, wfx
.wBitsPerSample
, wfx
.nChannels
,
496 frequency
, (440 * frequency
) / wfx
.nSamplesPerSec
);
498 trace(" Playing %g second 440Hz tone at %ldx%dx%d\n", duration
,
499 wfx
.nSamplesPerSec
, wfx
.wBitsPerSample
, wfx
.nChannels
);
503 /* We must call SetCooperativeLevel to be allowed to call Lock */
504 /* DSOUND: Setting DirectSound cooperative level to
505 * DSSCL_WRITEPRIMARY */
506 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),
508 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_WRITEPRIMARY) "
509 "failed: %08lx\n",rc
);
514 LPDIRECTSOUNDBUFFER temp_buffer
;
516 rc
=IDirectSoundBuffer_QueryInterface(*dsbo
,&IID_IDirectSound3DBuffer
,
518 ok(rc
==DS_OK
,"IDirectSoundBuffer_QueryInterface() failed: %08lx\n", rc
);
522 /* check the COM interface */
523 rc
=IDirectSoundBuffer_QueryInterface(*dsbo
, &IID_IDirectSoundBuffer
,
524 (LPVOID
*)&temp_buffer
);
525 ok(rc
==DS_OK
&& temp_buffer
!=NULL
,
526 "IDirectSoundBuffer_QueryInterface() failed: %08lx\n", rc
);
527 ok(temp_buffer
==*dsbo
,"COM interface broken: %p != %p\n",
529 ref
=IDirectSoundBuffer_Release(temp_buffer
);
530 ok(ref
==1,"IDirectSoundBuffer_Release() has %d references, "
531 "should have 1\n",ref
);
533 ref
=IDirectSoundBuffer_Release(*dsbo
);
534 ok(ref
==0,"IDirectSoundBuffer_Release() has %d references, "
535 "should have 0\n",ref
);
537 rc
=IDirectSound3DBuffer_QueryInterface(buffer
,
538 &IID_IDirectSoundBuffer
,
540 ok(rc
==DS_OK
&& *dsbo
!=NULL
,"IDirectSound3DBuffer_QueryInterface() "
541 "failed: %08lx\n",rc
);
543 /* DSOUND: Error: Invalid buffer */
544 rc
=IDirectSound3DBuffer_GetAllParameters(buffer
,0);
545 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound3DBuffer_GetAllParameters() "
546 "failed: %08lx\n",rc
);
548 ZeroMemory(&buffer_param
, sizeof(buffer_param
));
550 /* DSOUND: Error: Invalid buffer */
551 rc
=IDirectSound3DBuffer_GetAllParameters(buffer
,&buffer_param
);
552 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound3DBuffer_GetAllParameters() "
553 "failed: %08lx\n",rc
);
555 buffer_param
.dwSize
=sizeof(buffer_param
);
556 rc
=IDirectSound3DBuffer_GetAllParameters(buffer
,&buffer_param
);
557 ok(rc
==DS_OK
,"IDirectSound3DBuffer_GetAllParameters() failed: %08lx\n", rc
);
560 if (dsbcaps
.dwFlags
& DSBCAPS_CTRLVOLUME
) {
562 rc
=IDirectSoundBuffer_GetVolume(*dsbo
,&val
);
563 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetVolume() failed: %08lx\n", rc
);
565 rc
=IDirectSoundBuffer_SetVolume(*dsbo
,volume
);
566 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetVolume() failed: %08lx\n", rc
);
568 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
569 rc
=IDirectSoundBuffer_GetVolume(*dsbo
,&volume
);
570 ok(rc
==DSERR_CONTROLUNAVAIL
,"IDirectSoundBuffer_GetVolume() "
571 "should have returned DSERR_CONTROLUNAVAIL, returned: %08lx\n", rc
);
576 if (dsbcaps
.dwFlags
& DSBCAPS_CTRLPAN
) {
578 rc
=IDirectSoundBuffer_GetPan(*dsbo
,&val
);
579 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetPan() failed: %08lx\n", rc
);
581 rc
=IDirectSoundBuffer_SetPan(*dsbo
,pan
);
582 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetPan() failed: %08lx\n", rc
);
584 /* DSOUND: Error: Buffer does not have CTRLPAN */
585 rc
=IDirectSoundBuffer_GetPan(*dsbo
,&pan
);
586 ok(rc
==DSERR_CONTROLUNAVAIL
,"IDirectSoundBuffer_GetPan() "
587 "should have returned DSERR_CONTROLUNAVAIL, returned: %08lx\n", rc
);
591 /* try an offset past the end of the buffer */
592 rc
= IDirectSoundBuffer_Lock(*dsbo
, dsbcaps
.dwBufferBytes
, 0, &buffer1
,
593 &length1
, NULL
, NULL
,
594 DSBLOCK_ENTIREBUFFER
);
595 ok(rc
==DSERR_INVALIDPARAM
, "IDirectSoundBuffer_Lock() should have "
596 "returned DSERR_INVALIDPARAM, returned %08lx\n", rc
);
598 /* try a size larger than the buffer */
599 rc
= IDirectSoundBuffer_Lock(*dsbo
, 0, dsbcaps
.dwBufferBytes
+ 1,
600 &buffer1
, &length1
, NULL
, NULL
,
601 DSBLOCK_FROMWRITECURSOR
);
602 ok(rc
==DSERR_INVALIDPARAM
, "IDirectSoundBuffer_Lock() should have "
603 "returned DSERR_INVALIDPARAM, returned %08lx\n", rc
);
606 state
.wave
=wave_generate_la(&wfx
,(duration
*frequency
)/wfx
.nSamplesPerSec
,&state
.wave_len
,ieee
);
608 state
.wave
=wave_generate_la(&wfx
,duration
,&state
.wave_len
,ieee
);
612 state
.buffer_size
=dsbcaps
.dwBufferBytes
;
613 state
.played
=state
.written
=state
.offset
=0;
614 buffer_refill(&state
,state
.buffer_size
);
616 rc
=IDirectSoundBuffer_Play(*dsbo
,0,0,DSBPLAY_LOOPING
);
617 ok(rc
==DS_OK
,"IDirectSoundBuffer_Play() failed: %08lx\n", rc
);
619 rc
=IDirectSoundBuffer_GetStatus(*dsbo
,&status
);
620 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetStatus() failed: %08lx\n", rc
);
621 ok(status
==(DSBSTATUS_PLAYING
|DSBSTATUS_LOOPING
),
622 "GetStatus: bad status: %lx\n",status
);
625 ZeroMemory(&listener_param
,sizeof(listener_param
));
626 listener_param
.dwSize
=sizeof(listener_param
);
627 rc
=IDirectSound3DListener_GetAllParameters(listener
,
629 ok(rc
==DS_OK
,"IDirectSound3dListener_GetAllParameters() "
630 "failed: %08lx\n",rc
);
632 listener_param
.vPosition
.x
= -5.0f
;
633 listener_param
.vVelocity
.x
= (float)(10.0/duration
);
635 rc
=IDirectSound3DListener_SetAllParameters(listener
,
638 ok(rc
==DS_OK
,"IDirectSound3dListener_SetPosition() failed: %08lx\n", rc
);
642 buffer_param
.vPosition
.x
= 100.0f
;
643 buffer_param
.vVelocity
.x
= (float)(-200.0/duration
);
645 buffer_param
.flMinDistance
= 10;
646 rc
=IDirectSound3DBuffer_SetAllParameters(buffer
,&buffer_param
,
648 ok(rc
==DS_OK
,"IDirectSound3dBuffer_SetPosition() failed: %08lx\n", rc
);
651 start_time
=GetTickCount();
652 while (buffer_service(&state
)) {
653 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE
);
655 if (listener
&& move_listener
) {
656 listener_param
.vPosition
.x
= (float)(-5.0+10.0*(now
-start_time
)/1000/duration
);
657 if (winetest_debug
>2)
658 trace("listener position=%g\n",listener_param
.vPosition
.x
);
659 rc
=IDirectSound3DListener_SetPosition(listener
,
660 listener_param
.vPosition
.x
,listener_param
.vPosition
.y
,
661 listener_param
.vPosition
.z
,DS3D_IMMEDIATE
);
662 ok(rc
==DS_OK
,"IDirectSound3dListener_SetPosition() failed: %08lx\n",rc
);
664 if (buffer3d
&& move_sound
) {
665 buffer_param
.vPosition
.x
= (float)(100-200.0*(now
-start_time
)/1000/duration
);
666 if (winetest_debug
>2)
667 trace("sound position=%g\n",buffer_param
.vPosition
.x
);
668 rc
=IDirectSound3DBuffer_SetPosition(buffer
,
669 buffer_param
.vPosition
.x
,buffer_param
.vPosition
.y
,
670 buffer_param
.vPosition
.z
,DS3D_IMMEDIATE
);
671 ok(rc
==DS_OK
,"IDirectSound3dBuffer_SetPosition() failed: %08lx\n", rc
);
674 /* Check the sound duration was within 10% of the expected value */
676 ok(fabs(1000*duration
-now
+start_time
)<=100*duration
,
677 "The sound played for %ld ms instead of %g ms\n",
678 now
-start_time
,1000*duration
);
680 HeapFree(GetProcessHeap(), 0, state
.wave
);
682 /* Set the CooperativeLevel back to normal */
683 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
684 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
685 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) "
686 "failed: %08lx\n",rc
);
689 ref
=IDirectSound3DBuffer_Release(buffer
);
690 ok(ref
==0,"IDirectSound3DBuffer_Release() has %d references, "
691 "should have 0\n",ref
);
696 static HRESULT
test_secondary(LPGUID lpGuid
, int play
,
697 int has_3d
, int has_3dbuffer
,
698 int has_listener
, int has_duplicate
,
699 int move_listener
, int move_sound
)
702 LPDIRECTSOUND dso
=NULL
;
703 LPDIRECTSOUNDBUFFER primary
=NULL
,secondary
=NULL
;
704 LPDIRECTSOUND3DLISTENER listener
=NULL
;
705 DSBUFFERDESC bufdesc
;
706 WAVEFORMATEX wfx
, wfx1
;
709 /* Create the DirectSound object */
710 rc
= DirectSoundCreate(lpGuid
, &dso
, NULL
);
711 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
,"DirectSoundCreate() failed: %08lx\n", rc
);
715 /* We must call SetCooperativeLevel before creating primary buffer */
716 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
717 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
718 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08lx\n",rc
);
722 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
723 bufdesc
.dwSize
=sizeof(bufdesc
);
724 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
;
726 bufdesc
.dwFlags
|=DSBCAPS_CTRL3D
;
728 bufdesc
.dwFlags
|=(DSBCAPS_CTRLVOLUME
|DSBCAPS_CTRLPAN
);
729 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
730 ok((rc
==DS_OK
&& primary
!=NULL
) || (rc
==DSERR_CONTROLUNAVAIL
),
731 "IDirectSound_CreateSoundBuffer() failed to create a %sprimary buffer: %08lx\n",has_3d
?"3D ":"", rc
);
732 if (rc
==DSERR_CONTROLUNAVAIL
)
733 trace(" No Primary\n");
734 else if (rc
==DS_OK
&& primary
!=NULL
) {
735 rc
=IDirectSoundBuffer_GetFormat(primary
,&wfx1
,sizeof(wfx1
),NULL
);
736 ok(rc
==DS_OK
,"IDirectSoundBuffer8_Getformat() failed: %08lx\n", rc
);
741 rc
=IDirectSoundBuffer_QueryInterface(primary
,
742 &IID_IDirectSound3DListener
,
744 ok(rc
==DS_OK
&& listener
!=NULL
,
745 "IDirectSoundBuffer_QueryInterface() failed to get a 3D listener: %08lx\n",rc
);
746 ref
=IDirectSoundBuffer_Release(primary
);
747 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
748 "should have 0\n",ref
);
749 if (rc
==DS_OK
&& listener
!=NULL
) {
750 DS3DLISTENER listener_param
;
751 ZeroMemory(&listener_param
,sizeof(listener_param
));
752 /* DSOUND: Error: Invalid buffer */
753 rc
=IDirectSound3DListener_GetAllParameters(listener
,0);
754 ok(rc
==DSERR_INVALIDPARAM
,
755 "IDirectSound3dListener_GetAllParameters() should have "
756 "returned DSERR_INVALIDPARAM, returned: %08lx\n", rc
);
758 /* DSOUND: Error: Invalid buffer */
759 rc
=IDirectSound3DListener_GetAllParameters(listener
,
761 ok(rc
==DSERR_INVALIDPARAM
,
762 "IDirectSound3dListener_GetAllParameters() should have "
763 "returned DSERR_INVALIDPARAM, returned: %08lx\n", rc
);
765 listener_param
.dwSize
=sizeof(listener_param
);
766 rc
=IDirectSound3DListener_GetAllParameters(listener
,
768 ok(rc
==DS_OK
,"IDirectSound3dListener_GetAllParameters() "
769 "failed: %08lx\n",rc
);
771 ok(listener
==NULL
, "IDirectSoundBuffer_QueryInterface() "
772 "failed but returned a listener anyway\n");
773 ok(rc
!=DS_OK
, "IDirectSoundBuffer_QueryInterface() succeeded "
774 "but returned a NULL listener\n");
776 ref
=IDirectSound3DListener_Release(listener
);
777 ok(ref
==0,"IDirectSound3dListener_Release() listener has "
778 "%d references, should have 0\n",ref
);
784 init_format(&wfx
,WAVE_FORMAT_PCM
,22050,16,2);
786 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
787 bufdesc
.dwSize
=sizeof(bufdesc
);
788 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
;
790 bufdesc
.dwFlags
|=DSBCAPS_CTRL3D
;
791 bufdesc
.dwFlags
|= DSBCAPS_CTRLFREQUENCY
|DSBCAPS_CTRLVOLUME
|DSBCAPS_CTRLPAN
;
792 bufdesc
.dwBufferBytes
=align(wfx
.nAvgBytesPerSec
*BUFFER_LEN
/1000,
794 bufdesc
.lpwfxFormat
=&wfx
;
795 if (winetest_interactive
) {
796 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d "
797 "with a primary buffer at %ldx%dx%d\n",
798 has_3dbuffer
?"3D ":"",
799 has_duplicate
?"duplicated ":"",
800 listener
!=NULL
||move_sound
?"with ":"",
801 move_listener
?"moving ":"",
802 listener
!=NULL
?"listener ":"",
803 listener
&&move_sound
?"and moving sound ":move_sound
?
805 wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,wfx
.nChannels
,
806 wfx1
.nSamplesPerSec
,wfx1
.wBitsPerSample
,wfx1
.nChannels
);
808 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
809 ok((rc
==DS_OK
&& secondary
!=NULL
) || broken(rc
== DSERR_CONTROLUNAVAIL
), /* vmware drivers on w2k */
810 "IDirectSound_CreateSoundBuffer() failed to create a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d (%s): %08lx\n",
811 has_3dbuffer
?"3D ":"", has_duplicate
?"duplicated ":"",
812 listener
!=NULL
||move_sound
?"with ":"", move_listener
?"moving ":"",
813 listener
!=NULL
?"listener ":"",
814 listener
&&move_sound
?"and moving sound ":move_sound
?
816 wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,wfx
.nChannels
,
817 getDSBCAPS(bufdesc
.dwFlags
),rc
);
818 if (rc
==DS_OK
&& secondary
!=NULL
) {
819 IDirectSound3DBuffer
*ds3d
;
821 rc
=IDirectSoundBuffer_QueryInterface(secondary
, &IID_IDirectSound3DBuffer
, (void**)&ds3d
);
822 ok((has_3dbuffer
&& rc
==DS_OK
) || (!has_3dbuffer
&& rc
==E_NOINTERFACE
),
823 "Wrong return trying to get 3D buffer on %s3D secondary interface: %08lx\n", has_3dbuffer
? "" : "non-", rc
);
825 IDirectSound3DBuffer_Release(ds3d
);
828 LONG refvol
,vol
,refpan
,pan
;
830 /* Check the initial secondary buffer's volume and pan */
831 rc
=IDirectSoundBuffer_GetVolume(secondary
,&vol
);
832 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetVolume(secondary) failed: %08lx\n",rc
);
833 ok(vol
==0,"wrong volume for a new secondary buffer: %ld\n",vol
);
834 rc
=IDirectSoundBuffer_GetPan(secondary
,&pan
);
835 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetPan(secondary) failed: %08lx\n",rc
);
836 ok(pan
==0,"wrong pan for a new secondary buffer: %ld\n",pan
);
838 /* Check that changing the secondary buffer's volume and pan
839 * does not impact the primary buffer's volume and pan
841 rc
=IDirectSoundBuffer_GetVolume(primary
,&refvol
);
842 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetVolume(primary) failed: %08lx\n",rc
);
843 rc
=IDirectSoundBuffer_GetPan(primary
,&refpan
);
844 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetPan(primary) failed: %08lx\n", rc
);
846 rc
=IDirectSoundBuffer_SetVolume(secondary
,-1000);
847 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetVolume(secondary) failed: %08lx\n",rc
);
848 rc
=IDirectSoundBuffer_GetVolume(secondary
,&vol
);
849 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetVolume(secondary) failed: %08lx\n",rc
);
850 ok(vol
==-1000,"secondary: wrong volume %ld instead of -1000\n",
852 rc
=IDirectSoundBuffer_SetPan(secondary
,-1000);
853 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetPan(secondary) failed: %08lx\n",rc
);
854 rc
=IDirectSoundBuffer_GetPan(secondary
,&pan
);
855 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetPan(secondary) failed: %08lx\n",rc
);
856 ok(pan
==-1000,"secondary: wrong pan %ld instead of -1000\n",
859 rc
=IDirectSoundBuffer_GetVolume(primary
,&vol
);
860 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetVolume(primary) failed: %08lx\n",rc
);
861 ok(vol
==refvol
,"The primary volume changed from %ld to %ld\n",
863 rc
=IDirectSoundBuffer_GetPan(primary
,&pan
);
864 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetPan(primary) failed: %08lx\n", rc
);
865 ok(pan
==refpan
,"The primary pan changed from %ld to %ld\n",
868 rc
=IDirectSoundBuffer_SetVolume(secondary
,0);
869 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetVolume(secondary) failed: %08lx\n",rc
);
870 rc
=IDirectSoundBuffer_SetPan(secondary
,0);
871 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetPan(secondary) failed: %08lx\n",rc
);
872 } else if (has_3dbuffer
) {
875 rc
=IDirectSoundBuffer_GetPan(secondary
,&pan
);
876 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetPan() failed, returned: %08lx\n", rc
);
877 rc
=IDirectSoundBuffer_SetPan(secondary
,0);
878 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetPan() failed, returned: %08lx\n", rc
);
882 LPDIRECTSOUNDBUFFER duplicated
=NULL
;
884 /* DSOUND: Error: Invalid source buffer */
885 rc
=IDirectSound_DuplicateSoundBuffer(dso
,0,0);
886 ok(rc
==DSERR_INVALIDPARAM
,
887 "IDirectSound_DuplicateSoundBuffer() should have returned "
888 "DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
890 /* DSOUND: Error: Invalid dest buffer */
891 rc
=IDirectSound_DuplicateSoundBuffer(dso
,secondary
,0);
892 ok(rc
==DSERR_INVALIDPARAM
,
893 "IDirectSound_DuplicateSoundBuffer() should have returned "
894 "DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
896 /* DSOUND: Error: Invalid source buffer */
897 rc
=IDirectSound_DuplicateSoundBuffer(dso
,0,&duplicated
);
898 ok(rc
==DSERR_INVALIDPARAM
,
899 "IDirectSound_DuplicateSoundBuffer() should have returned "
900 "DSERR_INVALIDPARAM, returned: %08lx\n",rc
);
903 rc
=IDirectSound_DuplicateSoundBuffer(dso
,secondary
,
905 ok(rc
==DS_OK
&& duplicated
!=NULL
,
906 "IDirectSound_DuplicateSoundBuffer() failed to duplicate "
907 "a secondary buffer: %08lx\n",rc
);
909 if (rc
==DS_OK
&& duplicated
!=NULL
) {
910 ref
=IDirectSoundBuffer_Release(secondary
);
911 ok(ref
==0,"IDirectSoundBuffer_Release() secondary has %d "
912 "references, should have 0\n",ref
);
913 secondary
=duplicated
;
917 if (rc
==DS_OK
&& secondary
!=NULL
) {
919 duration
=(move_listener
|| move_sound
?4.0:1.0);
920 test_buffer(dso
,&secondary
,0,FALSE
,0,FALSE
,0,
921 winetest_interactive
,duration
,has_3dbuffer
,
922 listener
,move_listener
,move_sound
,FALSE
,0);
923 ref
=IDirectSoundBuffer_Release(secondary
);
924 ok(ref
==0,"IDirectSoundBuffer_Release() %s has %d references, "
925 "should have 0\n",has_duplicate
?"duplicated":"secondary",
931 ref
=IDirectSound3DListener_Release(listener
);
932 ok(ref
==0,"IDirectSound3dListener_Release() listener has %d "
933 "references, should have 0\n",ref
);
935 ref
=IDirectSoundBuffer_Release(primary
);
936 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
937 "should have 0\n",ref
);
940 ok(primary
==NULL
,"IDirectSound_CreateSoundBuffer(primary) failed "
941 "but primary created anyway\n");
942 ok(rc
!=DS_OK
,"IDirectSound_CreateSoundBuffer(primary) succeeded "
943 "but primary not created\n");
945 ref
=IDirectSoundBuffer_Release(primary
);
946 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
947 "should have 0\n",ref
);
951 /* Set the CooperativeLevel back to normal */
952 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
953 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
954 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08lx\n", rc
);
957 ref
=IDirectSound_Release(dso
);
958 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
960 return DSERR_GENERIC
;
965 static HRESULT
test_for_driver(LPGUID lpGuid
)
968 LPDIRECTSOUND dso
=NULL
;
971 /* Create the DirectSound object */
972 rc
= DirectSoundCreate(lpGuid
, &dso
, NULL
);
973 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
974 "DirectSoundCreate() failed: %08lx\n",rc
);
978 ref
=IDirectSound_Release(dso
);
979 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
981 return DSERR_GENERIC
;
986 static HRESULT
test_primary(LPGUID lpGuid
)
989 LPDIRECTSOUND dso
=NULL
;
990 LPDIRECTSOUNDBUFFER primary
=NULL
;
991 DSBUFFERDESC bufdesc
;
995 /* Create the DirectSound object */
996 rc
= DirectSoundCreate(lpGuid
, &dso
, NULL
);
997 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
,"DirectSoundCreate() failed: %08lx\n", rc
);
1001 /* Get the device capabilities */
1002 ZeroMemory(&dscaps
, sizeof(dscaps
));
1003 dscaps
.dwSize
=sizeof(dscaps
);
1004 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
1005 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %08lx\n",rc
);
1009 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1010 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1011 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
1012 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08lx\n",rc
);
1016 /* Testing the primary buffer */
1018 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
1019 bufdesc
.dwSize
=sizeof(bufdesc
);
1020 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
|DSBCAPS_CTRLVOLUME
|DSBCAPS_CTRLPAN
;
1021 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
1022 ok((rc
==DS_OK
&& primary
!=NULL
) || (rc
==DSERR_CONTROLUNAVAIL
),
1023 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: %08lx\n",rc
);
1024 if (rc
==DSERR_CONTROLUNAVAIL
)
1025 trace(" No Primary\n");
1026 else if (rc
==DS_OK
&& primary
!=NULL
) {
1027 test_buffer(dso
,&primary
,1,TRUE
,0,TRUE
,0,winetest_interactive
&&
1028 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),1.0,0,NULL
,0,0,
1030 if (winetest_interactive
) {
1033 volume
= DSBVOLUME_MAX
;
1034 for (i
= 0; i
< 6; i
++) {
1035 test_buffer(dso
,&primary
,1,TRUE
,volume
,TRUE
,0,
1036 winetest_interactive
&&
1037 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),
1038 1.0,0,NULL
,0,0,FALSE
,0);
1039 volume
-= ((DSBVOLUME_MAX
-DSBVOLUME_MIN
) / 40);
1043 for (i
= 0; i
< 7; i
++) {
1044 test_buffer(dso
,&primary
,1,TRUE
,0,TRUE
,pan
,
1045 winetest_interactive
&&
1046 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),1.0,0,0,0,0,FALSE
,0);
1047 pan
+= ((DSBPAN_RIGHT
-DSBPAN_LEFT
) / 6);
1050 ref
=IDirectSoundBuffer_Release(primary
);
1051 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
1052 "should have 0\n",ref
);
1055 /* Set the CooperativeLevel back to normal */
1056 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1057 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
1058 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08lx\n", rc
);
1061 ref
=IDirectSound_Release(dso
);
1062 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
1064 return DSERR_GENERIC
;
1069 static HRESULT
test_primary_3d(LPGUID lpGuid
)
1072 LPDIRECTSOUND dso
=NULL
;
1073 LPDIRECTSOUNDBUFFER primary
=NULL
;
1074 DSBUFFERDESC bufdesc
;
1078 /* Create the DirectSound object */
1079 rc
= DirectSoundCreate(lpGuid
, &dso
, NULL
);
1080 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
,"DirectSoundCreate() failed: %08lx\n", rc
);
1084 /* Get the device capabilities */
1085 ZeroMemory(&dscaps
, sizeof(dscaps
));
1086 dscaps
.dwSize
=sizeof(dscaps
);
1087 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
1088 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %08lx\n",rc
);
1092 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1093 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1094 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
1095 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08lx\n",rc
);
1100 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
1101 bufdesc
.dwSize
=sizeof(bufdesc
);
1102 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
;
1103 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
1104 ok(rc
==DS_OK
&& primary
!=NULL
,"IDirectSound_CreateSoundBuffer() failed "
1105 "to create a primary buffer: %08lx\n",rc
);
1106 if (rc
==DS_OK
&& primary
!=NULL
) {
1107 ref
=IDirectSoundBuffer_Release(primary
);
1108 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
1109 "should have 0\n",ref
);
1111 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
1112 bufdesc
.dwSize
=sizeof(bufdesc
);
1113 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
|DSBCAPS_CTRL3D
;
1114 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
1115 ok(rc
==DS_OK
&& primary
!=NULL
,"IDirectSound_CreateSoundBuffer() "
1116 "failed to create a 3D primary buffer: %08lx\n",rc
);
1117 if (rc
==DS_OK
&& primary
!=NULL
) {
1118 test_buffer(dso
,&primary
,1,FALSE
,0,FALSE
,0,winetest_interactive
&&
1119 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),1.0,0,0,0,0,
1121 ref
=IDirectSoundBuffer_Release(primary
);
1122 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
1123 "should have 0\n",ref
);
1126 /* Set the CooperativeLevel back to normal */
1127 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
1128 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
1129 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_NORMAL) failed: %08lx\n", rc
);
1132 ref
=IDirectSound_Release(dso
);
1133 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
1135 return DSERR_GENERIC
;
1140 static HRESULT
test_primary_3d_with_listener(LPGUID lpGuid
)
1143 LPDIRECTSOUND dso
=NULL
;
1144 LPDIRECTSOUNDBUFFER primary
=NULL
;
1145 DSBUFFERDESC bufdesc
;
1149 /* Create the DirectSound object */
1150 rc
= DirectSoundCreate(lpGuid
, &dso
, NULL
);
1151 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
,"DirectSoundCreate() failed: %08lx\n", rc
);
1155 /* Get the device capabilities */
1156 ZeroMemory(&dscaps
, sizeof(dscaps
));
1157 dscaps
.dwSize
=sizeof(dscaps
);
1158 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
1159 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %08lx\n",rc
);
1163 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
1164 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
1165 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
1166 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08lx\n",rc
);
1170 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
1171 bufdesc
.dwSize
=sizeof(bufdesc
);
1172 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
|DSBCAPS_CTRL3D
;
1173 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
1174 ok(rc
==DS_OK
&& primary
!=NULL
,"IDirectSound_CreateSoundBuffer() failed "
1175 "to create a 3D primary buffer: %08lx\n",rc
);
1176 if (rc
==DS_OK
&& primary
!=NULL
) {
1177 LPDIRECTSOUND3DLISTENER listener
=NULL
;
1178 LPDIRECTSOUNDBUFFER temp_buffer
=NULL
;
1179 IKsPropertySet
*propset
;
1181 rc
=IDirectSoundBuffer_QueryInterface(primary
,
1182 &IID_IDirectSound3DListener
,(void **)&listener
);
1183 ok(rc
==DS_OK
&& listener
!=NULL
,"IDirectSoundBuffer_QueryInterface() "
1184 "failed to get a 3D listener: %08lx\n",rc
);
1185 if (rc
==DS_OK
&& listener
!=NULL
) {
1186 /* Checking the COM interface */
1187 rc
=IDirectSoundBuffer_QueryInterface(primary
,
1188 &IID_IDirectSoundBuffer
,(LPVOID
*)&temp_buffer
);
1189 ok(rc
==DS_OK
&& temp_buffer
!=NULL
,
1190 "IDirectSoundBuffer_QueryInterface() failed: %08lx\n", rc
);
1191 ok(temp_buffer
==primary
,
1192 "COM interface broken: %p != %p\n",
1193 temp_buffer
,primary
);
1194 if (rc
==DS_OK
&& temp_buffer
!=NULL
) {
1195 ref
=IDirectSoundBuffer_Release(temp_buffer
);
1196 ok(ref
==1,"IDirectSoundBuffer_Release() has %d references, "
1197 "should have 1\n",ref
);
1200 rc
=IDirectSound3DListener_QueryInterface(listener
,
1201 &IID_IDirectSoundBuffer
,(LPVOID
*)&temp_buffer
);
1202 ok(rc
==DS_OK
&& temp_buffer
!=NULL
,
1203 "IDirectSoundBuffer_QueryInterface() failed: %08lx\n", rc
);
1204 ok(temp_buffer
==primary
,
1205 "COM interface broken: %p != %p\n",
1206 temp_buffer
,primary
);
1207 ref
=IDirectSoundBuffer_Release(temp_buffer
);
1208 ok(ref
==1,"IDirectSoundBuffer_Release() has %d references, "
1209 "should have 1\n",ref
);
1211 /* Testing the buffer */
1212 test_buffer(dso
,&primary
,1,FALSE
,0,FALSE
,0,
1213 winetest_interactive
&&
1214 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),1.0,0,
1215 listener
,0,0,FALSE
,0);
1218 rc
= IDirectSound3DListener_QueryInterface(listener
, &IID_IKsPropertySet
,
1220 ok(rc
== DS_OK
&& propset
!= NULL
,
1221 "IDirectSound3DListener_QueryInterface didn't handle IKsPropertySet: ret = %08lx\n", rc
);
1222 IKsPropertySet_Release(propset
);
1225 /* Testing the reference counting */
1226 ref
=IDirectSound3DListener_Release(listener
);
1227 ok(ref
==0,"IDirectSound3DListener_Release() listener has %d "
1228 "references, should have 0\n",ref
);
1232 rc
= IDirectSoundBuffer_QueryInterface(primary
, &IID_IKsPropertySet
, (void **)&propset
);
1233 ok(rc
== DS_OK
&& propset
!= NULL
,
1234 "IDirectSoundBuffer_QueryInterface didn't handle IKsPropertySet on primary buffer: ret = %08lx\n", rc
);
1235 IKsPropertySet_Release(propset
);
1237 /* Testing the reference counting */
1238 ref
=IDirectSoundBuffer_Release(primary
);
1239 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
1240 "should have 0\n",ref
);
1244 ref
=IDirectSound_Release(dso
);
1245 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
1247 return DSERR_GENERIC
;
1252 static void check_doppler(IDirectSound
*dsound
, IDirectSound3DListener
*listener
,
1253 BOOL play
, DWORD mode
, float listener_pos
, float listener_velocity
,
1254 float buffer_pos
, float buffer_velocity
, DWORD set_freq
, DWORD expected_freq
)
1256 IDirectSound3DBuffer
*buffer_3d
;
1257 IDirectSoundBuffer
*ref_buffer
;
1258 IDirectSoundBuffer
*buffer
;
1259 WAVEFORMATEX format
;
1271 const char *mode_str
= "";
1272 if (mode
== DS3DMODE_HEADRELATIVE
)
1273 mode_str
= "in head-relative mode ";
1274 else if (mode
== DS3DMODE_DISABLE
)
1275 mode_str
= "with 3D processing disabled ";
1276 trace(" Testing Doppler shift %swith listener at %g, velocity %g"
1277 " with sound at %g, velocity %g, frequency %luHz\n",
1278 mode_str
, listener_pos
, listener_velocity
, buffer_pos
, buffer_velocity
, set_freq
);
1281 memset(&format
, 0, sizeof(format
));
1282 format
.wFormatTag
= WAVE_FORMAT_PCM
;
1283 format
.nChannels
= 1;
1284 format
.nSamplesPerSec
= 22050;
1285 format
.wBitsPerSample
= 16;
1286 format
.nAvgBytesPerSec
= 2 * 22050;
1287 format
.nBlockAlign
= 2;
1289 data
= wave_generate_la(&format
, 0.6, &size
, FALSE
);
1291 memset(&desc
, 0, sizeof(desc
));
1292 desc
.dwSize
= sizeof(desc
);
1294 desc
.lpwfxFormat
= &format
;
1295 desc
.dwBufferBytes
= size
;
1297 hr
= IDirectSound_CreateSoundBuffer(dsound
, &desc
, &ref_buffer
, NULL
);
1298 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1300 hr
= IDirectSoundBuffer_Lock(ref_buffer
, 0, 0, &locked_data
, &locked_size
, NULL
, NULL
, DSBLOCK_ENTIREBUFFER
);
1301 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1302 memcpy(locked_data
, data
, size
);
1303 hr
= IDirectSoundBuffer_Unlock(ref_buffer
, locked_data
, locked_size
, NULL
, 0);
1304 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1306 HeapFree(GetProcessHeap(), 0, data
);
1308 memset(&format
, 0, sizeof(format
));
1309 format
.wFormatTag
= WAVE_FORMAT_PCM
;
1310 format
.nChannels
= 1;
1311 /* Set the sampling frequency of the generated waveform to the frequency
1312 * that the buffer is expected to be played at. This way a successful
1313 * test will produce a 440Hz tone. */
1314 format
.nSamplesPerSec
= expected_freq
;
1315 format
.wBitsPerSample
= 16;
1316 format
.nAvgBytesPerSec
= 2 * expected_freq
;
1317 format
.nBlockAlign
= 2;
1319 data
= wave_generate_la(&format
, 0.6, &size
, FALSE
);
1321 memset(&format
, 0, sizeof(format
));
1322 format
.wFormatTag
= WAVE_FORMAT_PCM
;
1323 format
.nChannels
= 1;
1324 format
.nSamplesPerSec
= 22050;
1325 format
.wBitsPerSample
= 16;
1326 format
.nAvgBytesPerSec
= 2 * 22050;
1327 format
.nBlockAlign
= 2;
1329 memset(&desc
, 0, sizeof(desc
));
1330 desc
.dwSize
= sizeof(desc
);
1331 desc
.dwFlags
= DSBCAPS_CTRLFREQUENCY
| DSBCAPS_CTRL3D
;
1332 desc
.lpwfxFormat
= &format
;
1333 desc
.dwBufferBytes
= size
;
1335 hr
= IDirectSound_CreateSoundBuffer(dsound
, &desc
, &buffer
, NULL
);
1336 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1337 hr
= IDirectSoundBuffer_QueryInterface(buffer
, &IID_IDirectSound3DBuffer
, (void *)&buffer_3d
);
1338 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1340 hr
= IDirectSoundBuffer_Lock(buffer
, 0, 0, &locked_data
, &locked_size
, NULL
, NULL
, DSBLOCK_ENTIREBUFFER
);
1341 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1342 memcpy(locked_data
, data
, size
);
1343 hr
= IDirectSoundBuffer_Unlock(buffer
, locked_data
, locked_size
, NULL
, 0);
1344 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1346 HeapFree(GetProcessHeap(), 0, data
);
1348 /* Set to different values first to test that the frequency is updated. */
1349 hr
= IDirectSound3DListener_SetPosition(listener
, 0, 0, 0, DS3D_DEFERRED
);
1350 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1351 hr
= IDirectSound3DListener_SetVelocity(listener
, 0, 0, 0, DS3D_DEFERRED
);
1352 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1353 hr
= IDirectSound3DBuffer_SetPosition(buffer_3d
, 0, 1, 0, DS3D_DEFERRED
);
1354 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1355 hr
= IDirectSound3DBuffer_SetVelocity(buffer_3d
, 0, -60, 0, DS3D_DEFERRED
);
1356 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1357 hr
= IDirectSound3DListener_CommitDeferredSettings(listener
);
1358 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1360 hr
= IDirectSound3DListener_SetPosition(listener
, 0, listener_pos
, 0, DS3D_DEFERRED
);
1361 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1362 hr
= IDirectSound3DListener_SetVelocity(listener
, 0, listener_velocity
, 0, DS3D_DEFERRED
);
1363 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1365 hr
= IDirectSoundBuffer_SetFrequency(buffer
, set_freq
);
1366 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1368 hr
= IDirectSound3DBuffer_SetMode(buffer_3d
, mode
, DS3D_DEFERRED
);
1369 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1370 hr
= IDirectSound3DBuffer_SetPosition(buffer_3d
, 0, buffer_pos
, 0, DS3D_DEFERRED
);
1371 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1372 hr
= IDirectSound3DBuffer_SetVelocity(buffer_3d
, 0, buffer_velocity
, 0, DS3D_DEFERRED
);
1373 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1375 hr
= IDirectSound3DListener_CommitDeferredSettings(listener
);
1376 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1379 hr
= IDirectSoundBuffer_GetFrequency(buffer
, &freq
);
1380 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1381 ok(freq
== set_freq
, "Got frequency %lu\n", freq
);
1385 trace(" Playing a reference 440Hz tone\n");
1386 hr
= IDirectSoundBuffer_Play(ref_buffer
, 0, 0, DSBPLAY_LOOPING
);
1387 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1389 hr
= IDirectSoundBuffer_Stop(ref_buffer
);
1390 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1392 trace(" Playing a test tone (should be 440Hz)\n");
1393 hr
= IDirectSoundBuffer_Play(buffer
, 0, 0, DSBPLAY_LOOPING
);
1394 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1396 hr
= IDirectSoundBuffer_Stop(buffer
);
1397 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1400 IDirectSound3DBuffer_Release(buffer_3d
);
1401 ref
= IDirectSoundBuffer_Release(buffer
);
1402 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1403 ref
= IDirectSoundBuffer_Release(ref_buffer
);
1404 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1407 static void test_doppler(GUID
*guid
, BOOL play
)
1409 IDirectSound3DListener
*listener
;
1410 IDirectSoundBuffer
*primary
;
1411 IDirectSound
*dsound
;
1419 hr
= DirectSoundCreate(guid
, &dsound
, NULL
);
1420 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1422 hr
= IDirectSound_SetCooperativeLevel(dsound
, hwnd
, DSSCL_PRIORITY
);
1423 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1425 memset(&desc
, 0, sizeof(desc
));
1426 desc
.dwSize
= sizeof(desc
);
1427 desc
.dwFlags
= DSBCAPS_PRIMARYBUFFER
| DSBCAPS_CTRL3D
;
1428 hr
= IDirectSound_CreateSoundBuffer(dsound
, &desc
, &primary
, NULL
);
1429 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1430 hr
= IDirectSoundBuffer_QueryInterface(primary
, &IID_IDirectSound3DListener
, (void *)&listener
);
1431 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1433 /* When run in interactive mode, the following tests should produce a series
1434 * of 440Hz tones. Any deviation from 440Hz indicates a test failure. */
1436 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, 0, 1, 0, 22050, 22050);
1437 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, -90, 1, -90, 22050, 22050);
1439 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, 0, 1, -90, 22050, 29400);
1440 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, 0, 1, 90, 22050, 17640);
1442 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, 0, 0, -90, 22050, 22050);
1444 /* The Doppler shift does not depend on the frame of reference. */
1445 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, 90, 1, 0, 22050, 29400);
1446 check_doppler(dsound
, listener
, play
, DS3DMODE_NORMAL
, 0, -90, 1, 0, 22050, 17640);
1448 IDirectSound3DListener_Release(listener
);
1449 ref
= IDirectSoundBuffer_Release(primary
);
1450 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1451 ref
= IDirectSound_Release(dsound
);
1452 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1455 static unsigned driver_count
= 0;
1457 static BOOL WINAPI
dsenum_callback(LPGUID lpGuid
, LPCSTR lpcstrDescription
,
1458 LPCSTR lpcstrModule
, LPVOID lpContext
)
1461 trace("*** Testing %s - %s ***\n",lpcstrDescription
,lpcstrModule
);
1464 rc
= test_for_driver(lpGuid
);
1465 if (rc
== DSERR_NODRIVER
) {
1466 trace(" No Driver\n");
1468 } else if (rc
== DSERR_ALLOCATED
) {
1469 trace(" Already In Use\n");
1471 } else if (rc
== E_FAIL
) {
1472 trace(" No Device\n");
1476 trace(" Testing the primary buffer\n");
1477 test_primary(lpGuid
);
1479 trace(" Testing 3D primary buffer\n");
1480 test_primary_3d(lpGuid
);
1482 trace(" Testing 3D primary buffer with listener\n");
1483 test_primary_3d_with_listener(lpGuid
);
1485 /* Testing secondary buffers */
1486 test_secondary(lpGuid
,winetest_interactive
,0,0,0,0,0,0);
1487 test_secondary(lpGuid
,winetest_interactive
,0,0,0,1,0,0);
1489 /* Testing 3D secondary buffers */
1490 test_secondary(lpGuid
,winetest_interactive
,1,0,0,0,0,0);
1491 test_secondary(lpGuid
,winetest_interactive
,1,1,0,0,0,0);
1492 test_secondary(lpGuid
,winetest_interactive
,1,1,0,1,0,0);
1493 test_secondary(lpGuid
,winetest_interactive
,1,0,1,0,0,0);
1494 test_secondary(lpGuid
,winetest_interactive
,1,0,1,1,0,0);
1495 test_secondary(lpGuid
,winetest_interactive
,1,1,1,0,0,0);
1496 test_secondary(lpGuid
,winetest_interactive
,1,1,1,1,0,0);
1497 test_secondary(lpGuid
,winetest_interactive
,1,1,1,0,1,0);
1498 test_secondary(lpGuid
,winetest_interactive
,1,1,1,0,0,1);
1499 test_secondary(lpGuid
,winetest_interactive
,1,1,1,0,1,1);
1501 test_doppler(lpGuid
,winetest_interactive
);
1506 static void ds3d_tests(void)
1509 rc
= DirectSoundEnumerateA(dsenum_callback
, NULL
);
1510 ok(rc
==DS_OK
,"DirectSoundEnumerateA() failed: %08lx\n",rc
);
1511 trace("tested %u DirectSound drivers\n", driver_count
);