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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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%08x, got 0x%08x\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;
175 LPCLASSFACTORY cf=NULL;
177 trace("Testing IDirectSound\n");
179 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
180 &IID_IClassFactory, (void**)&cf);
181 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
182 "failed: %s\n", DXGetErrorString8(rc));
184 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
185 &IID_IUnknown, (void**)&cf);
186 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
187 "failed: %s\n", DXGetErrorString8(rc));
189 /* try the COM class factory method of creation with no device specified */
190 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
191 &IID_IDirectSound, (void**)&dso);
192 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
193 DXGetErrorString8(rc));
195 IDirectSound_test(dso, FALSE, NULL);
197 /* try the COM class factory method of creation with default playback
198 * device specified */
199 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
200 &IID_IDirectSound, (void**)&dso);
201 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
202 DXGetErrorString8(rc));
204 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
206 /* try the COM class factory method of creation with default voice
207 * playback device specified */
208 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
209 &IID_IDirectSound, (void**)&dso);
210 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
211 DXGetErrorString8(rc));
213 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
215 /* try the COM class factory method of creation with a bad
217 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
218 &CLSID_DirectSoundPrivate, (void**)&dso);
219 ok(rc==E_NOINTERFACE,
220 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
221 "should have failed: %s\n",DXGetErrorString8(rc));
223 /* try the COM class factory method of creation with a bad
224 * GUID and IID specified */
225 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
226 &IID_IDirectSound, (void**)&dso);
227 ok(rc==REGDB_E_CLASSNOTREG,
228 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
229 "should have failed: %s\n",DXGetErrorString8(rc));
231 /* try with no device specified */
232 rc=DirectSoundCreate(NULL,&dso,NULL);
233 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
234 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
236 IDirectSound_test(dso, TRUE, NULL);
238 /* try with default playback device specified */
239 rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
240 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
241 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
242 DXGetErrorString8(rc));
243 if (rc==DS_OK && dso)
244 IDirectSound_test(dso, TRUE, NULL);
246 /* try with default voice playback device specified */
247 rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
248 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
249 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
250 DXGetErrorString8(rc));
251 if (rc==DS_OK && dso)
252 IDirectSound_test(dso, TRUE, NULL);
254 /* try with a bad device specified */
255 rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
256 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
257 "should have failed: %s\n",DXGetErrorString8(rc));
258 if (rc==DS_OK && dso)
259 IDirectSound_Release(dso);
262 static HRESULT test_dsound(LPGUID lpGuid)
265 LPDIRECTSOUND dso=NULL;
268 /* DSOUND: Error: Invalid interface buffer */
269 rc=DirectSoundCreate(lpGuid,0,NULL);
270 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
271 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
273 /* Create the DirectSound object */
274 rc=DirectSoundCreate(lpGuid,&dso,NULL);
275 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
276 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
280 /* Try the enumerated device */
281 IDirectSound_test(dso, TRUE, lpGuid);
283 /* Try the COM class factory method of creation with enumerated device */
284 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
285 &IID_IDirectSound, (void**)&dso);
286 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
287 DXGetErrorString8(rc));
289 IDirectSound_test(dso, FALSE, lpGuid);
291 /* Create a DirectSound object */
292 rc=DirectSoundCreate(lpGuid,&dso,NULL);
293 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
295 LPDIRECTSOUND dso1=NULL;
297 /* Create a second DirectSound object */
298 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
299 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
301 /* Release the second DirectSound object */
302 ref=IDirectSound_Release(dso1);
303 ok(ref==0,"IDirectSound_Release() has %d references, should have "
305 ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
308 /* Release the first DirectSound object */
309 ref=IDirectSound_Release(dso);
310 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
313 return DSERR_GENERIC;
317 /* Create a DirectSound object */
318 rc=DirectSoundCreate(lpGuid,&dso,NULL);
319 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
321 LPDIRECTSOUNDBUFFER secondary;
322 DSBUFFERDESC bufdesc;
325 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
326 ZeroMemory(&bufdesc, sizeof(bufdesc));
327 bufdesc.dwSize=sizeof(bufdesc);
328 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
329 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
331 bufdesc.lpwfxFormat=&wfx;
332 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
333 ok(rc==DS_OK && secondary!=NULL,
334 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
335 "buffer %s\n",DXGetErrorString8(rc));
336 if (rc==DS_OK && secondary!=NULL) {
337 LPDIRECTSOUND3DBUFFER buffer3d;
338 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
340 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
341 "failed: %s\n",DXGetErrorString8(rc));
342 if (rc==DS_OK && buffer3d!=NULL) {
343 ref=IDirectSound3DBuffer_AddRef(buffer3d);
344 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
345 "should have 2\n",ref);
347 ref=IDirectSoundBuffer_AddRef(secondary);
348 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
349 "should have 2\n",ref);
351 /* release with buffer */
352 ref=IDirectSound_Release(dso);
353 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
356 return DSERR_GENERIC;
363 static HRESULT test_primary(LPGUID lpGuid)
366 LPDIRECTSOUND dso=NULL;
367 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
368 DSBUFFERDESC bufdesc;
373 /* Create the DirectSound object */
374 rc=DirectSoundCreate(lpGuid,&dso,NULL);
375 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
376 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
380 /* Get the device capabilities */
381 ZeroMemory(&dscaps, sizeof(dscaps));
382 dscaps.dwSize=sizeof(dscaps);
383 rc=IDirectSound_GetCaps(dso,&dscaps);
384 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
388 /* DSOUND: Error: Invalid buffer description pointer */
389 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
390 ok(rc==DSERR_INVALIDPARAM,
391 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
392 DXGetErrorString8(rc));
394 /* DSOUND: Error: Invalid buffer description pointer */
395 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
396 ok(rc==DSERR_INVALIDPARAM && primary==0,
397 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
398 "dsbo=%p\n",DXGetErrorString8(rc),primary);
400 /* DSOUND: Error: Invalid buffer description pointer */
401 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
402 ok(rc==DSERR_INVALIDPARAM && primary==0,
403 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
404 "dsbo=0x%p\n",DXGetErrorString8(rc),primary);
406 ZeroMemory(&bufdesc, sizeof(bufdesc));
408 /* DSOUND: Error: Invalid size */
409 /* DSOUND: Error: Invalid buffer description */
410 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
411 ok(rc==DSERR_INVALIDPARAM && primary==0,
412 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
413 "primary=%p\n",DXGetErrorString8(rc),primary);
415 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
416 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
417 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
418 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
419 DXGetErrorString8(rc));
423 /* Testing the primary buffer */
425 ZeroMemory(&bufdesc, sizeof(bufdesc));
426 bufdesc.dwSize=sizeof(bufdesc);
427 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
428 bufdesc.lpwfxFormat = &wfx;
429 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
430 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
431 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
432 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
433 if (rc==DS_OK && primary!=NULL)
434 IDirectSoundBuffer_Release(primary);
437 ZeroMemory(&bufdesc, sizeof(bufdesc));
438 bufdesc.dwSize=sizeof(bufdesc);
439 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
440 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
441 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
442 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
443 "%s\n",DXGetErrorString8(rc));
444 if (rc==DSERR_CONTROLUNAVAIL)
445 trace(" No Primary\n");
446 else if (rc==DS_OK && primary!=NULL) {
449 /* Try to create a second primary buffer */
450 /* DSOUND: Error: The primary buffer already exists.
451 * Any changes made to the buffer description will be ignored. */
452 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
453 ok(rc==DS_OK && second==primary,
454 "IDirectSound_CreateSoundBuffer() should have returned original "
455 "primary buffer: %s\n",DXGetErrorString8(rc));
456 ref=IDirectSoundBuffer_Release(second);
457 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
458 "should have 1\n",ref);
460 /* Try to duplicate a primary buffer */
461 /* DSOUND: Error: Can't duplicate primary buffers */
462 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
464 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
465 "should have failed %s\n",DXGetErrorString8(rc));
467 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
468 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
469 DXGetErrorString8(rc));
471 if (winetest_interactive) {
472 trace("Playing a 5 seconds reference tone at the current "
475 trace("(the current volume is %d according to DirectSound)\n",
477 trace("All subsequent tones should be identical to this one.\n");
478 trace("Listen for stutter, changes in pitch, volume, etc.\n");
480 test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
481 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
483 ref=IDirectSoundBuffer_Release(primary);
484 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
485 "should have 0\n",ref);
488 /* Set the CooperativeLevel back to normal */
489 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
490 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
491 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
492 DXGetErrorString8(rc));
495 ref=IDirectSound_Release(dso);
496 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
498 return DSERR_GENERIC;
504 * Test the primary buffer at different formats while keeping the
505 * secondary buffer at a constant format.
507 static HRESULT test_primary_secondary(LPGUID lpGuid)
510 LPDIRECTSOUND dso=NULL;
511 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
512 DSBUFFERDESC bufdesc;
514 WAVEFORMATEX wfx, wfx2;
517 /* Create the DirectSound object */
518 rc=DirectSoundCreate(lpGuid,&dso,NULL);
519 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
520 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
524 /* Get the device capabilities */
525 ZeroMemory(&dscaps, sizeof(dscaps));
526 dscaps.dwSize=sizeof(dscaps);
527 rc=IDirectSound_GetCaps(dso,&dscaps);
528 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
532 /* We must call SetCooperativeLevel before creating primary buffer */
533 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
534 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
535 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
536 DXGetErrorString8(rc));
540 ZeroMemory(&bufdesc, sizeof(bufdesc));
541 bufdesc.dwSize=sizeof(bufdesc);
542 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
543 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
544 ok(rc==DS_OK && primary!=NULL,
545 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
546 "%s\n",DXGetErrorString8(rc));
548 if (rc==DS_OK && primary!=NULL) {
549 for (f=0;f<NB_FORMATS;f++) {
550 /* We must call SetCooperativeLevel to be allowed to call
552 /* DSOUND: Setting DirectSound cooperative level to
554 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
555 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
556 DXGetErrorString8(rc));
560 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
563 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
564 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
565 format_string(&wfx), DXGetErrorString8(rc));
567 /* There is no garantee that SetFormat will actually change the
568 * format to what we asked for. It depends on what the soundcard
569 * supports. So we must re-query the format.
571 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
572 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
573 DXGetErrorString8(rc));
575 (wfx.wFormatTag!=wfx2.wFormatTag ||
576 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
577 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
578 wfx.nChannels!=wfx2.nChannels)) {
579 trace("Requested primary format tag=0x%04x %dx%dx%d "
580 "avg.B/s=%d align=%d\n",
581 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
582 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
583 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
584 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
585 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
588 /* Set the CooperativeLevel back to normal */
589 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
590 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
591 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
592 DXGetErrorString8(rc));
594 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
597 ZeroMemory(&bufdesc, sizeof(bufdesc));
598 bufdesc.dwSize=sizeof(bufdesc);
599 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
600 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
602 bufdesc.lpwfxFormat=&wfx2;
603 if (winetest_interactive) {
604 trace(" Testing a primary buffer at %dx%dx%d with a "
605 "secondary buffer at %dx%dx%d\n",
606 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
607 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
609 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
610 ok(rc==DS_OK && secondary!=NULL,
611 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
612 "buffer %s\n",DXGetErrorString8(rc));
614 if (rc==DS_OK && secondary!=NULL) {
615 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
616 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
618 ref=IDirectSoundBuffer_Release(secondary);
619 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
620 "should have 0\n",ref);
624 ref=IDirectSoundBuffer_Release(primary);
625 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
626 "should have 0\n",ref);
629 /* Set the CooperativeLevel back to normal */
630 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
631 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
632 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
633 DXGetErrorString8(rc));
636 ref=IDirectSound_Release(dso);
637 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
639 return DSERR_GENERIC;
644 static HRESULT test_secondary(LPGUID lpGuid)
647 LPDIRECTSOUND dso=NULL;
648 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
649 DSBUFFERDESC bufdesc;
651 WAVEFORMATEX wfx, wfx1;
655 /* Create the DirectSound object */
656 rc=DirectSoundCreate(lpGuid,&dso,NULL);
657 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
658 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
662 /* Get the device capabilities */
663 ZeroMemory(&dscaps, sizeof(dscaps));
664 dscaps.dwSize=sizeof(dscaps);
665 rc=IDirectSound_GetCaps(dso,&dscaps);
666 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
670 /* We must call SetCooperativeLevel before creating primary buffer */
671 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
672 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
673 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
674 DXGetErrorString8(rc));
678 ZeroMemory(&bufdesc, sizeof(bufdesc));
679 bufdesc.dwSize=sizeof(bufdesc);
680 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
681 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
682 ok(rc==DS_OK && primary!=NULL,
683 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
684 "%s\n",DXGetErrorString8(rc));
686 if (rc==DS_OK && primary!=NULL) {
687 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
688 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
689 DXGetErrorString8(rc));
693 for (f=0;f<NB_FORMATS;f++) {
694 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
697 ZeroMemory(&bufdesc, sizeof(bufdesc));
698 bufdesc.dwSize=sizeof(bufdesc);
699 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
700 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
702 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
703 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
704 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
705 DXGetErrorString8(rc));
706 if (rc==DS_OK && secondary!=NULL)
707 IDirectSoundBuffer_Release(secondary);
710 ZeroMemory(&bufdesc, sizeof(bufdesc));
711 bufdesc.dwSize=sizeof(bufdesc);
712 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
713 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
715 bufdesc.lpwfxFormat=&wfx;
716 if (winetest_interactive) {
717 trace(" Testing a secondary buffer at %dx%dx%d "
718 "with a primary buffer at %dx%dx%d\n",
719 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
720 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
722 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
723 ok(rc==DS_OK && secondary!=NULL,
724 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
725 "buffer %s\n",DXGetErrorString8(rc));
727 if (rc==DS_OK && secondary!=NULL) {
728 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
729 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
731 ref=IDirectSoundBuffer_Release(secondary);
732 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
733 "should have 0\n",ref);
737 ref=IDirectSoundBuffer_Release(primary);
738 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
739 "should have 0\n",ref);
742 /* Set the CooperativeLevel back to normal */
743 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
744 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
745 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
746 DXGetErrorString8(rc));
749 ref=IDirectSound_Release(dso);
750 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
752 return DSERR_GENERIC;
757 static HRESULT test_block_align(LPGUID lpGuid)
760 LPDIRECTSOUND dso=NULL;
761 LPDIRECTSOUNDBUFFER secondary=NULL;
762 DSBUFFERDESC bufdesc;
767 /* Create the DirectSound object */
768 rc=DirectSoundCreate(lpGuid,&dso,NULL);
769 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
770 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
774 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
775 ZeroMemory(&bufdesc, sizeof(bufdesc));
776 bufdesc.dwSize=sizeof(bufdesc);
777 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
778 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
779 bufdesc.lpwfxFormat=&wfx;
780 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
781 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
782 "should have returned DS_OK, returned: %s\n",
783 DXGetErrorString8(rc));
785 if (rc==DS_OK && secondary!=NULL) {
786 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
787 dsbcaps.dwSize = sizeof(dsbcaps);
788 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
789 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
790 "returned: %s\n", DXGetErrorString8(rc));
792 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
793 "Buffer size not a multiple of nBlockAlign: requested %d, "
794 "got %d, should be %d\n", bufdesc.dwBufferBytes,
795 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
796 ref=IDirectSoundBuffer_Release(secondary);
797 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
798 "should have 0\n",ref);
801 ref=IDirectSound_Release(dso);
802 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
804 return DSERR_GENERIC;
812 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
814 static HRESULT test_frequency(LPGUID lpGuid)
817 LPDIRECTSOUND dso=NULL;
818 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
819 DSBUFFERDESC bufdesc;
821 WAVEFORMATEX wfx, wfx1;
824 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
827 /* Create the DirectSound object */
828 rc=DirectSoundCreate(lpGuid,&dso,NULL);
829 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
830 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
834 /* Get the device capabilities */
835 ZeroMemory(&dscaps, sizeof(dscaps));
836 dscaps.dwSize=sizeof(dscaps);
837 rc=IDirectSound_GetCaps(dso,&dscaps);
838 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
842 /* We must call SetCooperativeLevel before creating primary buffer */
843 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
844 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
845 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
846 DXGetErrorString8(rc));
850 ZeroMemory(&bufdesc, sizeof(bufdesc));
851 bufdesc.dwSize=sizeof(bufdesc);
852 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
853 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
854 ok(rc==DS_OK && primary!=NULL,
855 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
856 "%s\n",DXGetErrorString8(rc));
858 if (rc==DS_OK && primary!=NULL) {
859 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
860 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
861 DXGetErrorString8(rc));
865 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
866 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
867 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
870 ZeroMemory(&bufdesc, sizeof(bufdesc));
871 bufdesc.dwSize=sizeof(bufdesc);
872 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
873 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
874 BUFFER_LEN/1000,wfx.nBlockAlign);
875 bufdesc.lpwfxFormat=&wfx;
876 if (winetest_interactive) {
877 trace(" Testing a secondary buffer at %dx%dx%d "
878 "with a primary buffer at %dx%dx%d\n",
879 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
880 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
882 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
883 ok(rc==DS_OK && secondary!=NULL,
884 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
885 "buffer %s\n",DXGetErrorString8(rc));
887 if (rc==DS_OK && secondary!=NULL) {
888 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
889 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
891 ref=IDirectSoundBuffer_Release(secondary);
892 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
893 "should have 0\n",ref);
898 ref=IDirectSoundBuffer_Release(primary);
899 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
900 "should have 0\n",ref);
903 /* Set the CooperativeLevel back to normal */
904 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
905 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
906 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
907 DXGetErrorString8(rc));
910 ref=IDirectSound_Release(dso);
911 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
913 return DSERR_GENERIC;
918 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
919 LPCSTR lpcstrModule, LPVOID lpContext)
922 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
923 rc = test_dsound(lpGuid);
924 if (rc == DSERR_NODRIVER)
925 trace(" No Driver\n");
926 else if (rc == DSERR_ALLOCATED)
927 trace(" Already In Use\n");
928 else if (rc == E_FAIL)
929 trace(" No Device\n");
931 test_block_align(lpGuid);
932 test_primary(lpGuid);
933 test_primary_secondary(lpGuid);
934 test_secondary(lpGuid);
935 test_frequency(lpGuid);
941 static void dsound_tests(void)
944 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
945 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
952 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
954 IDirectSound_tests();