dsound: Use relative velocity to compute Doppler shift.
[wine.git] / dlls / dsound / tests / ds3d.c
blob5fa558f7c87635c5208ea24307eab3ec1ff3ecea
1 /*
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
26 #include <windows.h>
28 #include <math.h>
30 #include "wine/test.h"
31 #include "mmsystem.h"
32 #include "dsound.h"
33 #include "ks.h"
34 #include "ksmedia.h"
35 #include "dsound_test.h"
37 #define PI 3.14159265358979323846
39 char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size, BOOL ieee)
41 int i;
42 int nb_samples;
43 char* buf;
44 char* b;
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);
53 *b++=sample;
54 if (wfx->nChannels==2)
55 *b++=sample;
56 } else if (wfx->wBitsPerSample == 16) {
57 signed short sample=32767.5*y-0.5;
58 b[0]=sample & 0xff;
59 b[1]=sample >> 8;
60 b+=2;
61 if (wfx->nChannels==2) {
62 b[0]=sample & 0xff;
63 b[1]=sample >> 8;
64 b+=2;
66 } else if (wfx->wBitsPerSample == 24) {
67 signed int sample=8388607.5*y-0.5;
68 b[0]=sample & 0xff;
69 b[1]=(sample >> 8)&0xff;
70 b[2]=sample >> 16;
71 b+=3;
72 if (wfx->nChannels==2) {
73 b[0]=sample & 0xff;
74 b[1]=(sample >> 8)&0xff;
75 b[2]=sample >> 16;
76 b+=3;
78 } else if (wfx->wBitsPerSample == 32) {
79 if (ieee) {
80 float *ptr = (float *) b;
81 *ptr = y;
83 ptr++;
84 b+=4;
86 if (wfx->nChannels==2) {
87 *ptr = y;
88 b+=4;
90 } else {
91 signed int sample=2147483647.5*y-0.5;
92 b[0]=sample & 0xff;
93 b[1]=(sample >> 8)&0xff;
94 b[2]=(sample >> 16)&0xff;
95 b[3]=sample >> 24;
96 b+=4;
97 if (wfx->nChannels==2) {
98 b[0]=sample & 0xff;
99 b[1]=(sample >> 8)&0xff;
100 b[2]=(sample >> 16)&0xff;
101 b[3]=sample >> 24;
102 b+=4;
107 return buf;
110 const char * getDSBCAPS(DWORD xmask) {
111 static struct {
112 DWORD mask;
113 const char *name;
114 } flags[] = {
115 #define FE(x) { x, #x },
116 FE(DSBCAPS_PRIMARYBUFFER)
117 FE(DSBCAPS_STATIC)
118 FE(DSBCAPS_LOCHARDWARE)
119 FE(DSBCAPS_LOCSOFTWARE)
120 FE(DSBCAPS_CTRL3D)
121 FE(DSBCAPS_CTRLFREQUENCY)
122 FE(DSBCAPS_CTRLPAN)
123 FE(DSBCAPS_CTRLVOLUME)
124 FE(DSBCAPS_CTRLPOSITIONNOTIFY)
125 FE(DSBCAPS_STICKYFOCUS)
126 FE(DSBCAPS_GLOBALFOCUS)
127 FE(DSBCAPS_GETCURRENTPOSITION2)
128 FE(DSBCAPS_MUTE3DATMAXDISTANCE)
129 #undef FE
131 static char buffer[512];
132 unsigned int i;
133 BOOL first = TRUE;
135 buffer[0] = 0;
137 for (i = 0; i < ARRAY_SIZE(flags); i++) {
138 if ((flags[i].mask & xmask) == flags[i].mask) {
139 if (first)
140 first = FALSE;
141 else
142 strcat(buffer, "|");
143 strcat(buffer, flags[i].name);
147 return buffer;
150 HWND get_hwnd(void)
152 HWND hwnd=GetForegroundWindow();
153 if (!hwnd)
154 hwnd=GetDesktopWindow();
155 return hwnd;
158 void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth,
159 int channels)
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 */
170 wfx->nBlockAlign=1;
172 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
173 wfx->cbSize=0;
176 typedef struct {
177 char* wave;
178 DWORD wave_len;
180 LPDIRECTSOUNDBUFFER dsbo;
181 LPWAVEFORMATEX wfx;
182 DWORD buffer_size;
183 DWORD written;
184 DWORD played;
185 DWORD offset;
186 } play_state_t;
188 static int buffer_refill(play_state_t* state, DWORD size)
190 LPVOID ptr1,ptr2;
191 DWORD len1,len2;
192 HRESULT rc;
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);
204 if (rc!=DS_OK)
205 return -1;
207 memcpy(ptr1,state->wave+state->written,len1);
208 state->written+=len1;
209 if (ptr2!=NULL) {
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);
219 if (rc!=DS_OK)
220 return -1;
221 return size;
224 static int buffer_silence(play_state_t* state, DWORD size)
226 LPVOID ptr1,ptr2;
227 DWORD len1,len2;
228 HRESULT rc;
229 BYTE s;
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);
234 if (rc!=DS_OK)
235 return -1;
237 s=(state->wfx->wBitsPerSample==8?0x80:0);
238 memset(ptr1,s,len1);
239 if (ptr2!=NULL) {
240 memset(ptr2,s,len2);
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);
245 if (rc!=DS_OK)
246 return -1;
247 return size;
250 static BOOL buffer_service(play_state_t* state)
252 DWORD last_play_pos,play_pos,buf_free;
253 HRESULT rc;
255 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
256 ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08lx\n", rc);
257 if (rc!=DS_OK) {
258 goto STOP;
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;
265 else
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,
271 state->wave_len);
273 if (state->played>state->wave_len)
275 /* Everything has been played */
276 goto STOP;
279 /* Refill the buffer */
280 if (state->offset<=play_pos)
281 buf_free=play_pos-state->offset;
282 else
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);
288 if (buf_free==0)
289 return TRUE;
291 if (state->written<state->wave_len)
293 int w=buffer_refill(state,buf_free);
294 if (w==-1)
295 goto STOP;
296 buf_free-=w;
297 if (state->written==state->wave_len && winetest_debug > 1)
298 trace("last sound byte at %ld\n",
299 (state->written % state->buffer_size));
302 if (buf_free>0) {
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)
307 goto STOP;
309 return TRUE;
311 STOP:
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);
316 return FALSE;
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)
326 HRESULT rc;
327 DSBCAPS dsbcaps;
328 WAVEFORMATEX wfx,wfx2;
329 DWORD size,status,freq;
330 BOOL ieee = FALSE;
331 int ref;
333 if (set_frequency) {
334 rc=IDirectSoundBuffer_SetFrequency(*dsbo,frequency);
335 ok(rc==DS_OK||rc==DSERR_CONTROLUNAVAIL,
336 "IDirectSoundBuffer_SetFrequency() failed to set frequency %08lx\n",rc);
337 if (rc!=DS_OK)
338 return;
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. */
362 size=0;
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);
377 wfx = wfxe.Format;
378 ieee = IsEqualGUID(&wfxe.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
379 } else
380 return;
382 ok(rc==DS_OK,
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);
401 if (rc==DS_OK) {
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);
416 if (is_primary) {
417 DSBCAPS new_dsbcaps;
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);
422 if (rc!=DS_OK)
423 return;
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);
441 if (rc==DS_OK &&
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);
482 if (play) {
483 play_state_t state;
484 DS3DLISTENER listener_param;
485 LPDIRECTSOUND3DBUFFER buffer=NULL;
486 DS3DBUFFER buffer_param;
487 DWORD start_time,now;
488 LPVOID buffer1;
489 DWORD length1;
491 if (winetest_interactive) {
492 if (set_frequency)
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);
497 else
498 trace(" Playing %g second 440Hz tone at %ldx%dx%d\n", duration,
499 wfx.nSamplesPerSec, wfx.wBitsPerSample, wfx.nChannels);
502 if (is_primary) {
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(),
507 DSSCL_WRITEPRIMARY);
508 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(DSSCL_WRITEPRIMARY) "
509 "failed: %08lx\n",rc);
510 if (rc!=DS_OK)
511 return;
513 if (buffer3d) {
514 LPDIRECTSOUNDBUFFER temp_buffer;
516 rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
517 (LPVOID *)&buffer);
518 ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08lx\n", rc);
519 if (rc!=DS_OK)
520 return;
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",
528 temp_buffer,*dsbo);
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,
539 (LPVOID *)dsbo);
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);
559 if (set_volume) {
560 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
561 LONG val;
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);
567 } else {
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);
575 if (set_pan) {
576 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
577 LONG val;
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);
583 } else {
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);
605 if (set_frequency)
606 state.wave=wave_generate_la(&wfx,(duration*frequency)/wfx.nSamplesPerSec,&state.wave_len,ieee);
607 else
608 state.wave=wave_generate_la(&wfx,duration,&state.wave_len,ieee);
610 state.dsbo=*dsbo;
611 state.wfx=&wfx;
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);
624 if (listener) {
625 ZeroMemory(&listener_param,sizeof(listener_param));
626 listener_param.dwSize=sizeof(listener_param);
627 rc=IDirectSound3DListener_GetAllParameters(listener,
628 &listener_param);
629 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
630 "failed: %08lx\n",rc);
631 if (move_listener) {
632 listener_param.vPosition.x = -5.0f;
633 listener_param.vVelocity.x = (float)(10.0/duration);
635 rc=IDirectSound3DListener_SetAllParameters(listener,
636 &listener_param,
637 DS3D_IMMEDIATE);
638 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08lx\n", rc);
640 if (buffer3d) {
641 if (move_sound) {
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,
647 DS3D_IMMEDIATE);
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);
654 now=GetTickCount();
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 */
675 now=GetTickCount();
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);
681 if (is_primary) {
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);
688 if (buffer3d) {
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)
701 HRESULT rc;
702 LPDIRECTSOUND dso=NULL;
703 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
704 LPDIRECTSOUND3DLISTENER listener=NULL;
705 DSBUFFERDESC bufdesc;
706 WAVEFORMATEX wfx, wfx1;
707 int ref;
709 /* Create the DirectSound object */
710 rc = DirectSoundCreate(lpGuid, &dso, NULL);
711 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08lx\n", rc);
712 if (rc!=DS_OK)
713 return 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);
719 if (rc!=DS_OK)
720 goto EXIT;
722 ZeroMemory(&bufdesc, sizeof(bufdesc));
723 bufdesc.dwSize=sizeof(bufdesc);
724 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
725 if (has_3d)
726 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
727 else
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);
737 if (rc!=DS_OK)
738 goto EXIT1;
740 if (has_listener) {
741 rc=IDirectSoundBuffer_QueryInterface(primary,
742 &IID_IDirectSound3DListener,
743 (void **)&listener);
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,
760 &listener_param);
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,
767 &listener_param);
768 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
769 "failed: %08lx\n",rc);
770 } else {
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");
775 if (listener) {
776 ref=IDirectSound3DListener_Release(listener);
777 ok(ref==0,"IDirectSound3dListener_Release() listener has "
778 "%d references, should have 0\n",ref);
780 goto EXIT2;
784 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
785 secondary=NULL;
786 ZeroMemory(&bufdesc, sizeof(bufdesc));
787 bufdesc.dwSize=sizeof(bufdesc);
788 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
789 if (has_3dbuffer)
790 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
791 bufdesc.dwFlags|= DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
792 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
793 wfx.nBlockAlign);
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?
804 "moving 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?
815 "moving 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);
824 if(rc==DS_OK)
825 IDirectSound3DBuffer_Release(ds3d);
827 if (!has_3d) {
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",
851 vol);
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",
857 pan);
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",
862 refvol,vol);
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",
866 refpan,pan);
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) {
873 LONG pan;
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);
881 if (has_duplicate) {
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);
902 duplicated=NULL;
903 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,
904 &duplicated);
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) {
918 double duration;
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",
926 ref);
929 EXIT1:
930 if (has_listener) {
931 ref=IDirectSound3DListener_Release(listener);
932 ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
933 "references, should have 0\n",ref);
934 } else {
935 ref=IDirectSoundBuffer_Release(primary);
936 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
937 "should have 0\n",ref);
939 } else {
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");
944 if (primary) {
945 ref=IDirectSoundBuffer_Release(primary);
946 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
947 "should have 0\n",ref);
950 EXIT2:
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);
956 EXIT:
957 ref=IDirectSound_Release(dso);
958 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
959 if (ref!=0)
960 return DSERR_GENERIC;
962 return rc;
965 static HRESULT test_for_driver(LPGUID lpGuid)
967 HRESULT rc;
968 LPDIRECTSOUND dso=NULL;
969 int ref;
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);
975 if (rc!=DS_OK)
976 return rc;
978 ref=IDirectSound_Release(dso);
979 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
980 if (ref!=0)
981 return DSERR_GENERIC;
983 return rc;
986 static HRESULT test_primary(LPGUID lpGuid)
988 HRESULT rc;
989 LPDIRECTSOUND dso=NULL;
990 LPDIRECTSOUNDBUFFER primary=NULL;
991 DSBUFFERDESC bufdesc;
992 DSCAPS dscaps;
993 int ref, i;
995 /* Create the DirectSound object */
996 rc = DirectSoundCreate(lpGuid, &dso, NULL);
997 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08lx\n", rc);
998 if (rc!=DS_OK)
999 return 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);
1006 if (rc!=DS_OK)
1007 goto EXIT;
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);
1013 if (rc!=DS_OK)
1014 goto EXIT;
1016 /* Testing the primary buffer */
1017 primary=NULL;
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,
1029 FALSE,0);
1030 if (winetest_interactive) {
1031 LONG volume,pan;
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);
1042 pan = DSBPAN_LEFT;
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);
1060 EXIT:
1061 ref=IDirectSound_Release(dso);
1062 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1063 if (ref!=0)
1064 return DSERR_GENERIC;
1066 return rc;
1069 static HRESULT test_primary_3d(LPGUID lpGuid)
1071 HRESULT rc;
1072 LPDIRECTSOUND dso=NULL;
1073 LPDIRECTSOUNDBUFFER primary=NULL;
1074 DSBUFFERDESC bufdesc;
1075 DSCAPS dscaps;
1076 int ref;
1078 /* Create the DirectSound object */
1079 rc = DirectSoundCreate(lpGuid, &dso, NULL);
1080 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08lx\n", rc);
1081 if (rc!=DS_OK)
1082 return 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);
1089 if (rc!=DS_OK)
1090 goto EXIT;
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);
1096 if (rc!=DS_OK)
1097 goto EXIT;
1099 primary=NULL;
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);
1110 primary=NULL;
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,
1120 FALSE,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);
1131 EXIT:
1132 ref=IDirectSound_Release(dso);
1133 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1134 if (ref!=0)
1135 return DSERR_GENERIC;
1137 return rc;
1140 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
1142 HRESULT rc;
1143 LPDIRECTSOUND dso=NULL;
1144 LPDIRECTSOUNDBUFFER primary=NULL;
1145 DSBUFFERDESC bufdesc;
1146 DSCAPS dscaps;
1147 int ref;
1149 /* Create the DirectSound object */
1150 rc = DirectSoundCreate(lpGuid, &dso, NULL);
1151 ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate() failed: %08lx\n", rc);
1152 if (rc!=DS_OK)
1153 return 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);
1160 if (rc!=DS_OK)
1161 goto EXIT;
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);
1167 if (rc!=DS_OK)
1168 goto EXIT;
1169 primary=NULL;
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);
1199 temp_buffer=NULL;
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);
1217 temp_buffer = NULL;
1218 rc = IDirectSound3DListener_QueryInterface(listener, &IID_IKsPropertySet,
1219 (void **)&propset);
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);
1231 propset = NULL;
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);
1243 EXIT:
1244 ref=IDirectSound_Release(dso);
1245 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1246 if (ref!=0)
1247 return DSERR_GENERIC;
1249 return rc;
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;
1260 DSBUFFERDESC desc;
1261 DWORD locked_size;
1262 void *locked_data;
1263 HRESULT hr;
1264 DWORD freq;
1265 DWORD size;
1266 char *data;
1267 LONG ref;
1269 if (play)
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);
1293 desc.dwFlags = 0;
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);
1378 freq = 0xdeadbeef;
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);
1383 if (play)
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);
1388 Sleep(500);
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);
1395 Sleep(500);
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;
1412 DSBUFFERDESC desc;
1413 HRESULT hr;
1414 HWND hwnd;
1415 LONG ref;
1417 hwnd = get_hwnd();
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)
1460 HRESULT rc;
1461 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
1462 driver_count++;
1464 rc = test_for_driver(lpGuid);
1465 if (rc == DSERR_NODRIVER) {
1466 trace(" No Driver\n");
1467 return TRUE;
1468 } else if (rc == DSERR_ALLOCATED) {
1469 trace(" Already In Use\n");
1470 return TRUE;
1471 } else if (rc == E_FAIL) {
1472 trace(" No Device\n");
1473 return TRUE;
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);
1503 return TRUE;
1506 static void ds3d_tests(void)
1508 HRESULT rc;
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);
1514 START_TEST(ds3d)
1516 CoInitialize(NULL);
1518 ds3d_tests();
1520 CoUninitialize();