2 * Tests basic sound playback in DirectSound.
3 * In particular we test each standard Windows sound format to make sure
4 * we handle the sound card/driver quirks correctly.
6 * Part of this test involves playing test tones. But this only makes
7 * sense if someone is going to carefully listen to it, and would only
8 * bother everyone else.
9 * So this is only done if the test is being run in interactive mode.
11 * Copyright (c) 2002-2004 Francois Gouget
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #define NONAMELESSSTRUCT
29 #define NONAMELESSUNION
32 #include "wine/test.h"
37 #include "dsound_test.h"
39 static void IDirectSound_test(LPDIRECTSOUND dso
, BOOL initialized
,
48 DWORD speaker_config
, new_speaker_config
;
50 /* Try to Query for objects */
51 rc
=IDirectSound_QueryInterface(dso
,&IID_IUnknown
,(LPVOID
*)&unknown
);
52 ok(rc
==DS_OK
,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
53 DXGetErrorString8(rc
));
55 IDirectSound_Release(unknown
);
57 rc
=IDirectSound_QueryInterface(dso
,&IID_IDirectSound
,(LPVOID
*)&ds
);
58 ok(rc
==DS_OK
,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
59 DXGetErrorString8(rc
));
61 IDirectSound_Release(ds
);
63 rc
=IDirectSound_QueryInterface(dso
,&IID_IDirectSound8
,(LPVOID
*)&ds8
);
64 ok(rc
==E_NOINTERFACE
,"IDirectSound_QueryInterface(IID_IDirectSound8) "
65 "should have failed: %s\n",DXGetErrorString8(rc
));
67 IDirectSound8_Release(ds8
);
69 if (initialized
== FALSE
) {
70 /* try unitialized object */
71 rc
=IDirectSound_GetCaps(dso
,0);
72 ok(rc
==DSERR_UNINITIALIZED
,"IDirectSound_GetCaps(NULL) "
73 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
74 DXGetErrorString8(rc
));
76 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
77 ok(rc
==DSERR_UNINITIALIZED
,"IDirectSound_GetCaps() "
78 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
79 DXGetErrorString8(rc
));
81 rc
=IDirectSound_Compact(dso
);
82 ok(rc
==DSERR_UNINITIALIZED
,"IDirectSound_Compact() "
83 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
84 DXGetErrorString8(rc
));
86 rc
=IDirectSound_GetSpeakerConfig(dso
,&speaker_config
);
87 ok(rc
==DSERR_UNINITIALIZED
,"IDirectSound_GetSpeakerConfig() "
88 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
89 DXGetErrorString8(rc
));
91 rc
=IDirectSound_Initialize(dso
,lpGuid
);
92 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
93 "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc
));
94 if (rc
==DSERR_NODRIVER
) {
95 trace(" No Driver\n");
97 } else if (rc
==E_FAIL
) {
98 trace(" No Device\n");
100 } else if (rc
==DSERR_ALLOCATED
) {
101 trace(" Already In Use\n");
106 rc
=IDirectSound_Initialize(dso
,lpGuid
);
107 ok(rc
==DSERR_ALREADYINITIALIZED
, "IDirectSound_Initialize() "
108 "should have returned DSERR_ALREADYINITIALIZED: %s\n",
109 DXGetErrorString8(rc
));
111 /* DSOUND: Error: Invalid caps buffer */
112 rc
=IDirectSound_GetCaps(dso
,0);
113 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound_GetCaps(NULL) "
114 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
115 DXGetErrorString8(rc
));
117 ZeroMemory(&dscaps
, sizeof(dscaps
));
119 /* DSOUND: Error: Invalid caps buffer */
120 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
121 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound_GetCaps() "
122 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
123 DXGetErrorString8(rc
));
125 dscaps
.dwSize
=sizeof(dscaps
);
127 /* DSOUND: Running on a certified driver */
128 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
129 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc
));
131 rc
=IDirectSound_Compact(dso
);
132 ok(rc
==DSERR_PRIOLEVELNEEDED
,"IDirectSound_Compact() failed: %s\n",
133 DXGetErrorString8(rc
));
135 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
136 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
137 DXGetErrorString8(rc
));
139 rc
=IDirectSound_Compact(dso
);
140 ok(rc
==DS_OK
,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc
));
142 rc
=IDirectSound_GetSpeakerConfig(dso
,0);
143 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound_GetSpeakerConfig(NULL) "
144 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
145 DXGetErrorString8(rc
));
147 rc
=IDirectSound_GetSpeakerConfig(dso
,&speaker_config
);
148 ok(rc
==DS_OK
,"IDirectSound_GetSpeakerConfig() failed: %s\n",
149 DXGetErrorString8(rc
));
151 speaker_config
= DSSPEAKER_COMBINED(DSSPEAKER_STEREO
,
152 DSSPEAKER_GEOMETRY_WIDE
);
153 rc
=IDirectSound_SetSpeakerConfig(dso
,speaker_config
);
154 ok(rc
==DS_OK
,"IDirectSound_SetSpeakerConfig() failed: %s\n",
155 DXGetErrorString8(rc
));
157 rc
=IDirectSound_GetSpeakerConfig(dso
,&new_speaker_config
);
158 ok(rc
==DS_OK
,"IDirectSound_GetSpeakerConfig() failed: %s\n",
159 DXGetErrorString8(rc
));
160 if (rc
==DS_OK
&& speaker_config
!=new_speaker_config
)
161 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
162 "config: expected 0x%08lx, got 0x%08lx\n",
163 speaker_config
,new_speaker_config
);
167 ref
=IDirectSound_Release(dso
);
168 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
171 static void IDirectSound_tests(void)
174 LPDIRECTSOUND dso
=NULL
;
176 trace("Testing IDirectSound\n");
178 /* try the COM class factory method of creation with no device specified */
179 rc
=CoCreateInstance(&CLSID_DirectSound
, NULL
, CLSCTX_INPROC_SERVER
,
180 &IID_IDirectSound
, (void**)&dso
);
181 ok(rc
==S_OK
,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
182 DXGetErrorString8(rc
));
184 IDirectSound_test(dso
, FALSE
, NULL
);
186 /* try the COM class factory method of creation with default playback
187 * device specified */
188 rc
=CoCreateInstance(&CLSID_DirectSound
, NULL
, CLSCTX_INPROC_SERVER
,
189 &IID_IDirectSound
, (void**)&dso
);
190 ok(rc
==S_OK
,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
191 DXGetErrorString8(rc
));
193 IDirectSound_test(dso
, FALSE
, &DSDEVID_DefaultPlayback
);
195 /* try the COM class factory method of creation with default voice
196 * playback device specified */
197 rc
=CoCreateInstance(&CLSID_DirectSound
, NULL
, CLSCTX_INPROC_SERVER
,
198 &IID_IDirectSound
, (void**)&dso
);
199 ok(rc
==S_OK
,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
200 DXGetErrorString8(rc
));
202 IDirectSound_test(dso
, FALSE
, &DSDEVID_DefaultVoicePlayback
);
204 /* try the COM class factory method of creation with a bad
206 rc
=CoCreateInstance(&CLSID_DirectSound
, NULL
, CLSCTX_INPROC_SERVER
,
207 &CLSID_DirectSoundPrivate
, (void**)&dso
);
208 ok(rc
==E_NOINTERFACE
,
209 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
210 "should have failed: %s\n",DXGetErrorString8(rc
));
212 /* try the COM class factory method of creation with a bad
213 * GUID and IID specified */
214 rc
=CoCreateInstance(&CLSID_DirectSoundPrivate
, NULL
, CLSCTX_INPROC_SERVER
,
215 &IID_IDirectSound
, (void**)&dso
);
216 ok(rc
==REGDB_E_CLASSNOTREG
,
217 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
218 "should have failed: %s\n",DXGetErrorString8(rc
));
220 /* try with no device specified */
221 rc
=DirectSoundCreate(NULL
,&dso
,NULL
);
222 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
223 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc
));
225 IDirectSound_test(dso
, TRUE
, NULL
);
227 /* try with default playback device specified */
228 rc
=DirectSoundCreate(&DSDEVID_DefaultPlayback
,&dso
,NULL
);
229 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
230 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
231 DXGetErrorString8(rc
));
232 if (rc
==DS_OK
&& dso
)
233 IDirectSound_test(dso
, TRUE
, NULL
);
235 /* try with default voice playback device specified */
236 rc
=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback
,&dso
,NULL
);
237 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
238 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
239 DXGetErrorString8(rc
));
240 if (rc
==DS_OK
&& dso
)
241 IDirectSound_test(dso
, TRUE
, NULL
);
243 /* try with a bad device specified */
244 rc
=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture
,&dso
,NULL
);
245 ok(rc
==DSERR_NODRIVER
,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
246 "should have failed: %s\n",DXGetErrorString8(rc
));
247 if (rc
==DS_OK
&& dso
)
248 IDirectSound_Release(dso
);
251 static HRESULT
test_dsound(LPGUID lpGuid
)
254 LPDIRECTSOUND dso
=NULL
;
257 /* DSOUND: Error: Invalid interface buffer */
258 rc
=DirectSoundCreate(lpGuid
,0,NULL
);
259 ok(rc
==DSERR_INVALIDPARAM
,"DirectSoundCreate() should have returned "
260 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc
));
262 /* Create the DirectSound object */
263 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
264 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
||rc
==E_FAIL
,
265 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
269 /* Try the enumerated device */
270 IDirectSound_test(dso
, TRUE
, lpGuid
);
272 /* Try the COM class factory method of creation with enumerated device */
273 rc
=CoCreateInstance(&CLSID_DirectSound
, NULL
, CLSCTX_INPROC_SERVER
,
274 &IID_IDirectSound
, (void**)&dso
);
275 ok(rc
==S_OK
,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
276 DXGetErrorString8(rc
));
278 IDirectSound_test(dso
, FALSE
, lpGuid
);
280 /* Create a DirectSound object */
281 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
282 ok(rc
==DS_OK
,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
284 LPDIRECTSOUND dso1
=NULL
;
286 /* Create a second DirectSound object */
287 rc
=DirectSoundCreate(lpGuid
,&dso1
,NULL
);
288 ok(rc
==DS_OK
,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
290 /* Release the second DirectSound object */
291 ref
=IDirectSound_Release(dso1
);
292 ok(ref
==0,"IDirectSound_Release() has %d references, should have "
294 ok(dso
!=dso1
,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso
,dso1
);
297 /* Release the first DirectSound object */
298 ref
=IDirectSound_Release(dso
);
299 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",
302 return DSERR_GENERIC
;
306 /* Create a DirectSound object */
307 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
308 ok(rc
==DS_OK
,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
310 LPDIRECTSOUNDBUFFER secondary
;
311 DSBUFFERDESC bufdesc
;
314 init_format(&wfx
,WAVE_FORMAT_PCM
,11025,8,1);
315 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
316 bufdesc
.dwSize
=sizeof(bufdesc
);
317 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
| DSBCAPS_CTRL3D
;
318 bufdesc
.dwBufferBytes
=align(wfx
.nAvgBytesPerSec
*BUFFER_LEN
/1000,
320 bufdesc
.lpwfxFormat
=&wfx
;
321 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
322 ok(rc
==DS_OK
&& secondary
!=NULL
,
323 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
324 "buffer %s\n",DXGetErrorString8(rc
));
325 if (rc
==DS_OK
&& secondary
!=NULL
) {
326 LPDIRECTSOUND3DBUFFER buffer3d
;
327 rc
=IDirectSound_QueryInterface(secondary
, &IID_IDirectSound3DBuffer
,
329 ok(rc
==DS_OK
&& buffer3d
!=NULL
,"IDirectSound_QueryInterface() "
330 "failed: %s\n",DXGetErrorString8(rc
));
331 if (rc
==DS_OK
&& buffer3d
!=NULL
) {
332 ref
=IDirectSound3DBuffer_AddRef(buffer3d
);
333 ok(ref
==2,"IDirectSound3DBuffer_AddRef() has %d references, "
334 "should have 2\n",ref
);
336 ref
=IDirectSoundBuffer_AddRef(secondary
);
337 ok(ref
==2,"IDirectSoundBuffer_AddRef() has %d references, "
338 "should have 2\n",ref
);
340 /* release with buffer */
341 ref
=IDirectSound_Release(dso
);
342 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",
345 return DSERR_GENERIC
;
352 static HRESULT
test_primary(LPGUID lpGuid
)
355 LPDIRECTSOUND dso
=NULL
;
356 LPDIRECTSOUNDBUFFER primary
=NULL
,second
=NULL
,third
=NULL
;
357 DSBUFFERDESC bufdesc
;
362 /* Create the DirectSound object */
363 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
364 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
,
365 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
369 /* Get the device capabilities */
370 ZeroMemory(&dscaps
, sizeof(dscaps
));
371 dscaps
.dwSize
=sizeof(dscaps
);
372 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
373 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc
));
377 /* DSOUND: Error: Invalid buffer description pointer */
378 rc
=IDirectSound_CreateSoundBuffer(dso
,0,0,NULL
);
379 ok(rc
==DSERR_INVALIDPARAM
,
380 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
381 DXGetErrorString8(rc
));
383 /* DSOUND: Error: Invalid buffer description pointer */
384 rc
=IDirectSound_CreateSoundBuffer(dso
,0,&primary
,NULL
);
385 ok(rc
==DSERR_INVALIDPARAM
&& primary
==0,
386 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
387 "dsbo=%p\n",DXGetErrorString8(rc
),primary
);
389 /* DSOUND: Error: Invalid buffer description pointer */
390 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,0,NULL
);
391 ok(rc
==DSERR_INVALIDPARAM
&& primary
==0,
392 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
393 "dsbo=0x%p\n",DXGetErrorString8(rc
),primary
);
395 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
397 /* DSOUND: Error: Invalid size */
398 /* DSOUND: Error: Invalid buffer description */
399 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
400 ok(rc
==DSERR_INVALIDPARAM
&& primary
==0,
401 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
402 "primary=%p\n",DXGetErrorString8(rc
),primary
);
404 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
405 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
406 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
407 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
408 DXGetErrorString8(rc
));
412 /* Testing the primary buffer */
414 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
415 bufdesc
.dwSize
=sizeof(bufdesc
);
416 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
|DSBCAPS_CTRLVOLUME
;
417 bufdesc
.lpwfxFormat
= &wfx
;
418 init_format(&wfx
,WAVE_FORMAT_PCM
,11025,8,2);
419 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
420 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound_CreateSoundBuffer() should have "
421 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc
));
422 if (rc
==DS_OK
&& primary
!=NULL
)
423 IDirectSoundBuffer_Release(primary
);
426 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
427 bufdesc
.dwSize
=sizeof(bufdesc
);
428 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
|DSBCAPS_CTRLVOLUME
;
429 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
430 ok((rc
==DS_OK
&& primary
!=NULL
) || (rc
==DSERR_CONTROLUNAVAIL
),
431 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
432 "%s\n",DXGetErrorString8(rc
));
433 if (rc
==DSERR_CONTROLUNAVAIL
)
434 trace(" No Primary\n");
435 else if (rc
==DS_OK
&& primary
!=NULL
) {
438 /* Try to create a second primary buffer */
439 /* DSOUND: Error: The primary buffer already exists.
440 * Any changes made to the buffer description will be ignored. */
441 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&second
,NULL
);
442 ok(rc
==DS_OK
&& second
==primary
,
443 "IDirectSound_CreateSoundBuffer() should have returned original "
444 "primary buffer: %s\n",DXGetErrorString8(rc
));
445 ref
=IDirectSoundBuffer_Release(second
);
446 ok(ref
==1,"IDirectSoundBuffer_Release() primary has %d references, "
447 "should have 1\n",ref
);
449 /* Try to duplicate a primary buffer */
450 /* DSOUND: Error: Can't duplicate primary buffers */
451 rc
=IDirectSound_DuplicateSoundBuffer(dso
,primary
,&third
);
453 ok(rc
!=DS_OK
,"IDirectSound_DuplicateSoundBuffer() primary buffer "
454 "should have failed %s\n",DXGetErrorString8(rc
));
456 rc
=IDirectSoundBuffer_GetVolume(primary
,&vol
);
457 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetVolume() failed: %s\n",
458 DXGetErrorString8(rc
));
460 if (winetest_interactive
) {
461 trace("Playing a 5 seconds reference tone at the current "
464 trace("(the current volume is %ld according to DirectSound)\n",
466 trace("All subsequent tones should be identical to this one.\n");
467 trace("Listen for stutter, changes in pitch, volume, etc.\n");
469 test_buffer(dso
,primary
,1,FALSE
,0,FALSE
,0,winetest_interactive
&&
470 !(dscaps
.dwFlags
& DSCAPS_EMULDRIVER
),5.0,0,0,0,0,FALSE
,0);
472 ref
=IDirectSoundBuffer_Release(primary
);
473 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
474 "should have 0\n",ref
);
477 /* Set the CooperativeLevel back to normal */
478 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
479 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
480 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
481 DXGetErrorString8(rc
));
484 ref
=IDirectSound_Release(dso
);
485 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
487 return DSERR_GENERIC
;
493 * Test the primary buffer at different formats while keeping the
494 * secondary buffer at a constant format.
496 static HRESULT
test_primary_secondary(LPGUID lpGuid
)
499 LPDIRECTSOUND dso
=NULL
;
500 LPDIRECTSOUNDBUFFER primary
=NULL
,secondary
=NULL
;
501 DSBUFFERDESC bufdesc
;
503 WAVEFORMATEX wfx
, wfx2
;
506 /* Create the DirectSound object */
507 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
508 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
,
509 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
513 /* Get the device capabilities */
514 ZeroMemory(&dscaps
, sizeof(dscaps
));
515 dscaps
.dwSize
=sizeof(dscaps
);
516 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
517 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc
));
521 /* We must call SetCooperativeLevel before creating primary buffer */
522 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
523 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
524 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
525 DXGetErrorString8(rc
));
529 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
530 bufdesc
.dwSize
=sizeof(bufdesc
);
531 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
;
532 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
533 ok(rc
==DS_OK
&& primary
!=NULL
,
534 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
535 "%s\n",DXGetErrorString8(rc
));
537 if (rc
==DS_OK
&& primary
!=NULL
) {
538 for (f
=0;f
<NB_FORMATS
;f
++) {
539 /* We must call SetCooperativeLevel to be allowed to call
541 /* DSOUND: Setting DirectSound cooperative level to
543 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
544 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
545 DXGetErrorString8(rc
));
549 init_format(&wfx
,WAVE_FORMAT_PCM
,formats
[f
][0],formats
[f
][1],
552 rc
=IDirectSoundBuffer_SetFormat(primary
,&wfx
);
553 ok(rc
==DS_OK
,"IDirectSoundBuffer_SetFormat() failed: %s\n",
554 DXGetErrorString8(rc
));
556 /* There is no garantee that SetFormat will actually change the
557 * format to what we asked for. It depends on what the soundcard
558 * supports. So we must re-query the format.
560 rc
=IDirectSoundBuffer_GetFormat(primary
,&wfx
,sizeof(wfx
),NULL
);
561 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetFormat() failed: %s\n",
562 DXGetErrorString8(rc
));
564 (wfx
.wFormatTag
!=wfx2
.wFormatTag
||
565 wfx
.nSamplesPerSec
!=wfx2
.nSamplesPerSec
||
566 wfx
.wBitsPerSample
!=wfx2
.wBitsPerSample
||
567 wfx
.nChannels
!=wfx2
.nChannels
)) {
568 trace("Requested primary format tag=0x%04x %ldx%dx%d "
569 "avg.B/s=%ld align=%d\n",
570 wfx2
.wFormatTag
,wfx2
.nSamplesPerSec
,wfx2
.wBitsPerSample
,
571 wfx2
.nChannels
,wfx2
.nAvgBytesPerSec
,wfx2
.nBlockAlign
);
572 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
573 wfx
.wFormatTag
,wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,
574 wfx
.nChannels
,wfx
.nAvgBytesPerSec
,wfx
.nBlockAlign
);
577 /* Set the CooperativeLevel back to normal */
578 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
579 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
580 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
581 DXGetErrorString8(rc
));
583 init_format(&wfx2
,WAVE_FORMAT_PCM
,11025,16,2);
586 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
587 bufdesc
.dwSize
=sizeof(bufdesc
);
588 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
;
589 bufdesc
.dwBufferBytes
=align(wfx
.nAvgBytesPerSec
*BUFFER_LEN
/1000,
591 bufdesc
.lpwfxFormat
=&wfx2
;
592 if (winetest_interactive
) {
593 trace(" Testing a primary buffer at %ldx%dx%d with a "
594 "secondary buffer at %ldx%dx%d\n",
595 wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,wfx
.nChannels
,
596 wfx2
.nSamplesPerSec
,wfx2
.wBitsPerSample
,wfx2
.nChannels
);
598 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
599 ok(rc
==DS_OK
&& secondary
!=NULL
,
600 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
601 "buffer %s\n",DXGetErrorString8(rc
));
603 if (rc
==DS_OK
&& secondary
!=NULL
) {
604 test_buffer(dso
,secondary
,0,FALSE
,0,FALSE
,0,
605 winetest_interactive
,1.0,0,NULL
,0,0,FALSE
,0);
607 ref
=IDirectSoundBuffer_Release(secondary
);
608 ok(ref
==0,"IDirectSoundBuffer_Release() has %d references, "
609 "should have 0\n",ref
);
613 ref
=IDirectSoundBuffer_Release(primary
);
614 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
615 "should have 0\n",ref
);
618 /* Set the CooperativeLevel back to normal */
619 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
620 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
621 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
622 DXGetErrorString8(rc
));
625 ref
=IDirectSound_Release(dso
);
626 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
628 return DSERR_GENERIC
;
633 static HRESULT
test_secondary(LPGUID lpGuid
)
636 LPDIRECTSOUND dso
=NULL
;
637 LPDIRECTSOUNDBUFFER primary
=NULL
,secondary
=NULL
;
638 DSBUFFERDESC bufdesc
;
640 WAVEFORMATEX wfx
, wfx1
;
644 /* Create the DirectSound object */
645 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
646 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
,
647 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
651 /* Get the device capabilities */
652 ZeroMemory(&dscaps
, sizeof(dscaps
));
653 dscaps
.dwSize
=sizeof(dscaps
);
654 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
655 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc
));
659 /* We must call SetCooperativeLevel before creating primary buffer */
660 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
661 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
662 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
663 DXGetErrorString8(rc
));
667 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
668 bufdesc
.dwSize
=sizeof(bufdesc
);
669 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
;
670 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
671 ok(rc
==DS_OK
&& primary
!=NULL
,
672 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
673 "%s\n",DXGetErrorString8(rc
));
675 if (rc
==DS_OK
&& primary
!=NULL
) {
676 rc
=IDirectSoundBuffer_GetFormat(primary
,&wfx1
,sizeof(wfx1
),NULL
);
677 ok(rc
==DS_OK
,"IDirectSoundBuffer8_Getformat() failed: %s\n",
678 DXGetErrorString8(rc
));
682 for (f
=0;f
<NB_FORMATS
;f
++) {
683 init_format(&wfx
,WAVE_FORMAT_PCM
,formats
[f
][0],formats
[f
][1],
686 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
687 bufdesc
.dwSize
=sizeof(bufdesc
);
688 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
;
689 bufdesc
.dwBufferBytes
=align(wfx
.nAvgBytesPerSec
*BUFFER_LEN
/1000,
691 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
692 ok(rc
==DSERR_INVALIDPARAM
,"IDirectSound_CreateSoundBuffer() "
693 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
694 DXGetErrorString8(rc
));
695 if (rc
==DS_OK
&& secondary
!=NULL
)
696 IDirectSoundBuffer_Release(secondary
);
699 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
700 bufdesc
.dwSize
=sizeof(bufdesc
);
701 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
;
702 bufdesc
.dwBufferBytes
=align(wfx
.nAvgBytesPerSec
*BUFFER_LEN
/1000,
704 bufdesc
.lpwfxFormat
=&wfx
;
705 if (winetest_interactive
) {
706 trace(" Testing a secondary buffer at %ldx%dx%d "
707 "with a primary buffer at %ldx%dx%d\n",
708 wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,wfx
.nChannels
,
709 wfx1
.nSamplesPerSec
,wfx1
.wBitsPerSample
,wfx1
.nChannels
);
711 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
712 ok(rc
==DS_OK
&& secondary
!=NULL
,
713 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
714 "buffer %s\n",DXGetErrorString8(rc
));
716 if (rc
==DS_OK
&& secondary
!=NULL
) {
717 test_buffer(dso
,secondary
,0,FALSE
,0,FALSE
,0,
718 winetest_interactive
,1.0,0,NULL
,0,0,FALSE
,0);
720 ref
=IDirectSoundBuffer_Release(secondary
);
721 ok(ref
==0,"IDirectSoundBuffer_Release() has %d references, "
722 "should have 0\n",ref
);
726 ref
=IDirectSoundBuffer_Release(primary
);
727 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
728 "should have 0\n",ref
);
731 /* Set the CooperativeLevel back to normal */
732 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
733 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
734 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
735 DXGetErrorString8(rc
));
738 ref
=IDirectSound_Release(dso
);
739 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
741 return DSERR_GENERIC
;
746 static HRESULT
test_block_align(LPGUID lpGuid
)
749 LPDIRECTSOUND dso
=NULL
;
750 LPDIRECTSOUNDBUFFER secondary
=NULL
;
751 DSBUFFERDESC bufdesc
;
756 /* Create the DirectSound object */
757 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
758 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
,
759 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
763 init_format(&wfx
,WAVE_FORMAT_PCM
,11025,16,2);
764 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
765 bufdesc
.dwSize
=sizeof(bufdesc
);
766 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
;
767 bufdesc
.dwBufferBytes
=wfx
.nAvgBytesPerSec
+ 1;
768 bufdesc
.lpwfxFormat
=&wfx
;
769 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
770 ok(rc
==DS_OK
,"IDirectSound_CreateSoundBuffer() "
771 "should have returned DS_OK, returned: %s\n",
772 DXGetErrorString8(rc
));
774 if (rc
==DS_OK
&& secondary
!=NULL
) {
775 ZeroMemory(&dsbcaps
, sizeof(dsbcaps
));
776 dsbcaps
.dwSize
= sizeof(dsbcaps
);
777 rc
=IDirectSoundBuffer_GetCaps(secondary
,&dsbcaps
);
778 ok(rc
==DS_OK
,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
779 "returned: %s\n", DXGetErrorString8(rc
));
781 ok(dsbcaps
.dwBufferBytes
==(wfx
.nAvgBytesPerSec
+ wfx
.nBlockAlign
),
782 "Buffer size not a multiple of nBlockAlign: requested %ld, "
783 "got %ld, should be %ld\n", bufdesc
.dwBufferBytes
,
784 dsbcaps
.dwBufferBytes
, wfx
.nAvgBytesPerSec
+ wfx
.nBlockAlign
);
785 ref
=IDirectSoundBuffer_Release(secondary
);
786 ok(ref
==0,"IDirectSoundBuffer_Release() secondary has %d references, "
787 "should have 0\n",ref
);
790 ref
=IDirectSound_Release(dso
);
791 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
793 return DSERR_GENERIC
;
801 } fmts
[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
803 static HRESULT
test_frequency(LPGUID lpGuid
)
806 LPDIRECTSOUND dso
=NULL
;
807 LPDIRECTSOUNDBUFFER primary
=NULL
,secondary
=NULL
;
808 DSBUFFERDESC bufdesc
;
810 WAVEFORMATEX wfx
, wfx1
;
813 int rates
[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
816 /* Create the DirectSound object */
817 rc
=DirectSoundCreate(lpGuid
,&dso
,NULL
);
818 ok(rc
==DS_OK
||rc
==DSERR_NODRIVER
||rc
==DSERR_ALLOCATED
,
819 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc
));
823 /* Get the device capabilities */
824 ZeroMemory(&dscaps
, sizeof(dscaps
));
825 dscaps
.dwSize
=sizeof(dscaps
);
826 rc
=IDirectSound_GetCaps(dso
,&dscaps
);
827 ok(rc
==DS_OK
,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc
));
831 /* We must call SetCooperativeLevel before creating primary buffer */
832 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
833 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_PRIORITY
);
834 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
835 DXGetErrorString8(rc
));
839 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
840 bufdesc
.dwSize
=sizeof(bufdesc
);
841 bufdesc
.dwFlags
=DSBCAPS_PRIMARYBUFFER
;
842 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&primary
,NULL
);
843 ok(rc
==DS_OK
&& primary
!=NULL
,
844 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
845 "%s\n",DXGetErrorString8(rc
));
847 if (rc
==DS_OK
&& primary
!=NULL
) {
848 rc
=IDirectSoundBuffer_GetFormat(primary
,&wfx1
,sizeof(wfx1
),NULL
);
849 ok(rc
==DS_OK
,"IDirectSoundBuffer8_Getformat() failed: %s\n",
850 DXGetErrorString8(rc
));
854 for (f
=0;f
<sizeof(fmts
)/sizeof(fmts
[0]);f
++) {
855 for (r
=0;r
<sizeof(rates
)/sizeof(rates
[0]);r
++) {
856 init_format(&wfx
,WAVE_FORMAT_PCM
,11025,fmts
[f
].bits
,
859 ZeroMemory(&bufdesc
, sizeof(bufdesc
));
860 bufdesc
.dwSize
=sizeof(bufdesc
);
861 bufdesc
.dwFlags
=DSBCAPS_GETCURRENTPOSITION2
|DSBCAPS_CTRLFREQUENCY
;
862 bufdesc
.dwBufferBytes
=align((wfx
.nAvgBytesPerSec
*rates
[r
]/11025)*
863 BUFFER_LEN
/1000,wfx
.nBlockAlign
);
864 bufdesc
.lpwfxFormat
=&wfx
;
865 if (winetest_interactive
) {
866 trace(" Testing a secondary buffer at %ldx%dx%d "
867 "with a primary buffer at %ldx%dx%d\n",
868 wfx
.nSamplesPerSec
,wfx
.wBitsPerSample
,wfx
.nChannels
,
869 wfx1
.nSamplesPerSec
,wfx1
.wBitsPerSample
,wfx1
.nChannels
);
871 rc
=IDirectSound_CreateSoundBuffer(dso
,&bufdesc
,&secondary
,NULL
);
872 ok(rc
==DS_OK
&& secondary
!=NULL
,
873 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
874 "buffer %s\n",DXGetErrorString8(rc
));
876 if (rc
==DS_OK
&& secondary
!=NULL
) {
877 test_buffer(dso
,secondary
,0,FALSE
,0,FALSE
,0,
878 winetest_interactive
,1.0,0,NULL
,0,0,TRUE
,rates
[r
]);
880 ref
=IDirectSoundBuffer_Release(secondary
);
881 ok(ref
==0,"IDirectSoundBuffer_Release() has %d references, "
882 "should have 0\n",ref
);
887 ref
=IDirectSoundBuffer_Release(primary
);
888 ok(ref
==0,"IDirectSoundBuffer_Release() primary has %d references, "
889 "should have 0\n",ref
);
892 /* Set the CooperativeLevel back to normal */
893 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
894 rc
=IDirectSound_SetCooperativeLevel(dso
,get_hwnd(),DSSCL_NORMAL
);
895 ok(rc
==DS_OK
,"IDirectSound_SetCooperativeLevel() failed: %s\n",
896 DXGetErrorString8(rc
));
899 ref
=IDirectSound_Release(dso
);
900 ok(ref
==0,"IDirectSound_Release() has %d references, should have 0\n",ref
);
902 return DSERR_GENERIC
;
907 static BOOL WINAPI
dsenum_callback(LPGUID lpGuid
, LPCSTR lpcstrDescription
,
908 LPCSTR lpcstrModule
, LPVOID lpContext
)
911 trace("*** Testing %s - %s ***\n",lpcstrDescription
,lpcstrModule
);
912 rc
= test_dsound(lpGuid
);
913 if (rc
== DSERR_NODRIVER
)
914 trace(" No Driver\n");
915 else if (rc
== DSERR_ALLOCATED
)
916 trace(" Already In Use\n");
917 else if (rc
== E_FAIL
)
918 trace(" No Device\n");
920 test_block_align(lpGuid
);
921 test_primary(lpGuid
);
922 test_primary_secondary(lpGuid
);
923 test_secondary(lpGuid
);
924 test_frequency(lpGuid
);
930 static void dsound_tests(void)
933 rc
=DirectSoundEnumerateA(&dsenum_callback
,NULL
);
934 ok(rc
==DS_OK
,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc
));
941 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
943 IDirectSound_tests();