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()
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: "
295 "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
298 /* Release the first DirectSound object */
299 ref=IDirectSound_Release(dso);
300 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
303 return DSERR_GENERIC;
307 /* Create a DirectSound object */
308 rc=DirectSoundCreate(lpGuid,&dso,NULL);
309 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
311 LPDIRECTSOUNDBUFFER secondary;
312 DSBUFFERDESC bufdesc;
315 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
316 ZeroMemory(&bufdesc, sizeof(bufdesc));
317 bufdesc.dwSize=sizeof(bufdesc);
318 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
319 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
321 bufdesc.lpwfxFormat=&wfx;
322 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
323 ok(rc==DS_OK && secondary!=NULL,
324 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
325 "buffer %s\n",DXGetErrorString8(rc));
326 if (rc==DS_OK && secondary!=NULL) {
327 LPDIRECTSOUND3DBUFFER buffer3d;
328 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
330 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
331 "failed: %s\n",DXGetErrorString8(rc));
332 if (rc==DS_OK && buffer3d!=NULL) {
333 ref=IDirectSound3DBuffer_AddRef(buffer3d);
334 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
335 "should have 2\n",ref);
337 ref=IDirectSoundBuffer_AddRef(secondary);
338 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
339 "should have 2\n",ref);
341 /* release with buffer */
342 ref=IDirectSound_Release(dso);
343 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
346 return DSERR_GENERIC;
353 static HRESULT test_primary(LPGUID lpGuid)
356 LPDIRECTSOUND dso=NULL;
357 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
358 DSBUFFERDESC bufdesc;
363 /* Create the DirectSound object */
364 rc=DirectSoundCreate(lpGuid,&dso,NULL);
365 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
366 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
370 /* Get the device capabilities */
371 ZeroMemory(&dscaps, sizeof(dscaps));
372 dscaps.dwSize=sizeof(dscaps);
373 rc=IDirectSound_GetCaps(dso,&dscaps);
374 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
378 /* DSOUND: Error: Invalid buffer description pointer */
379 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
380 ok(rc==DSERR_INVALIDPARAM,
381 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
382 DXGetErrorString8(rc));
384 /* DSOUND: Error: Invalid buffer description pointer */
385 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
386 ok(rc==DSERR_INVALIDPARAM && primary==0,
387 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
388 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
390 /* DSOUND: Error: Invalid buffer description pointer */
391 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
392 ok(rc==DSERR_INVALIDPARAM && primary==0,
393 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
394 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
396 ZeroMemory(&bufdesc, sizeof(bufdesc));
398 /* DSOUND: Error: Invalid size */
399 /* DSOUND: Error: Invalid buffer description */
400 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
401 ok(rc==DSERR_INVALIDPARAM && primary==0,
402 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
403 "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
405 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
406 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
407 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
408 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
409 DXGetErrorString8(rc));
413 /* Testing the primary buffer */
415 ZeroMemory(&bufdesc, sizeof(bufdesc));
416 bufdesc.dwSize=sizeof(bufdesc);
417 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
418 bufdesc.lpwfxFormat = &wfx;
419 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
420 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
421 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
422 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
423 if (rc==DS_OK && primary!=NULL)
424 IDirectSoundBuffer_Release(primary);
427 ZeroMemory(&bufdesc, sizeof(bufdesc));
428 bufdesc.dwSize=sizeof(bufdesc);
429 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
430 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
431 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
432 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
433 "%s\n",DXGetErrorString8(rc));
434 if (rc==DSERR_CONTROLUNAVAIL)
435 trace(" No Primary\n");
436 else if (rc==DS_OK && primary!=NULL) {
439 /* Try to create a second primary buffer */
440 /* DSOUND: Error: The primary buffer already exists.
441 * Any changes made to the buffer description will be ignored. */
442 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
443 ok(rc==DS_OK && second==primary,
444 "IDirectSound_CreateSoundBuffer() should have returned original "
445 "primary buffer: %s\n",DXGetErrorString8(rc));
446 ref=IDirectSoundBuffer_Release(second);
447 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
448 "should have 1\n",ref);
450 /* Try to duplicate a primary buffer */
451 /* DSOUND: Error: Can't duplicate primary buffers */
452 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
454 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
455 "should have failed %s\n",DXGetErrorString8(rc));
457 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
458 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
459 DXGetErrorString8(rc));
461 if (winetest_interactive) {
462 trace("Playing a 5 seconds reference tone at the current "
465 trace("(the current volume is %ld according to DirectSound)\n",
467 trace("All subsequent tones should be identical to this one.\n");
468 trace("Listen for stutter, changes in pitch, volume, etc.\n");
470 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
471 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
473 ref=IDirectSoundBuffer_Release(primary);
474 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
475 "should have 0\n",ref);
478 /* Set the CooperativeLevel back to normal */
479 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
480 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
481 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
482 DXGetErrorString8(rc));
485 ref=IDirectSound_Release(dso);
486 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
488 return DSERR_GENERIC;
494 * Test the primary buffer at different formats while keeping the
495 * secondary buffer at a constant format.
497 static HRESULT test_primary_secondary(LPGUID lpGuid)
500 LPDIRECTSOUND dso=NULL;
501 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
502 DSBUFFERDESC bufdesc;
504 WAVEFORMATEX wfx, wfx2;
507 /* Create the DirectSound object */
508 rc=DirectSoundCreate(lpGuid,&dso,NULL);
509 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
510 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
514 /* Get the device capabilities */
515 ZeroMemory(&dscaps, sizeof(dscaps));
516 dscaps.dwSize=sizeof(dscaps);
517 rc=IDirectSound_GetCaps(dso,&dscaps);
518 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
522 /* We must call SetCooperativeLevel before creating primary buffer */
523 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
524 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
525 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
526 DXGetErrorString8(rc));
530 ZeroMemory(&bufdesc, sizeof(bufdesc));
531 bufdesc.dwSize=sizeof(bufdesc);
532 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
533 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
534 ok(rc==DS_OK && primary!=NULL,
535 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
536 "%s\n",DXGetErrorString8(rc));
538 if (rc==DS_OK && primary!=NULL) {
539 for (f=0;f<NB_FORMATS;f++) {
540 /* We must call SetCooperativeLevel to be allowed to call
542 /* DSOUND: Setting DirectSound cooperative level to
544 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
545 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
546 DXGetErrorString8(rc));
550 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
553 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
554 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
555 DXGetErrorString8(rc));
557 /* There is no garantee that SetFormat will actually change the
558 * format to what we asked for. It depends on what the soundcard
559 * supports. So we must re-query the format.
561 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
562 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
563 DXGetErrorString8(rc));
565 (wfx.wFormatTag!=wfx2.wFormatTag ||
566 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
567 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
568 wfx.nChannels!=wfx2.nChannels)) {
569 trace("Requested primary format tag=0x%04x %ldx%dx%d "
570 "avg.B/s=%ld align=%d\n",
571 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
572 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
573 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
574 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
575 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
578 /* Set the CooperativeLevel back to normal */
579 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
580 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
581 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
582 DXGetErrorString8(rc));
584 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
587 ZeroMemory(&bufdesc, sizeof(bufdesc));
588 bufdesc.dwSize=sizeof(bufdesc);
589 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
590 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
592 bufdesc.lpwfxFormat=&wfx2;
593 if (winetest_interactive) {
594 trace(" Testing a primary buffer at %ldx%dx%d with a "
595 "secondary buffer at %ldx%dx%d\n",
596 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
597 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
599 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
600 ok(rc==DS_OK && secondary!=NULL,
601 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
602 "buffer %s\n",DXGetErrorString8(rc));
604 if (rc==DS_OK && secondary!=NULL) {
605 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
606 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
608 ref=IDirectSoundBuffer_Release(secondary);
609 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
610 "should have 0\n",ref);
614 ref=IDirectSoundBuffer_Release(primary);
615 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
616 "should have 0\n",ref);
619 /* Set the CooperativeLevel back to normal */
620 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
621 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
622 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
623 DXGetErrorString8(rc));
626 ref=IDirectSound_Release(dso);
627 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
629 return DSERR_GENERIC;
634 static HRESULT test_secondary(LPGUID lpGuid)
637 LPDIRECTSOUND dso=NULL;
638 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
639 DSBUFFERDESC bufdesc;
641 WAVEFORMATEX wfx, wfx1;
645 /* Create the DirectSound object */
646 rc=DirectSoundCreate(lpGuid,&dso,NULL);
647 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
648 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
652 /* Get the device capabilities */
653 ZeroMemory(&dscaps, sizeof(dscaps));
654 dscaps.dwSize=sizeof(dscaps);
655 rc=IDirectSound_GetCaps(dso,&dscaps);
656 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
660 /* We must call SetCooperativeLevel before creating primary buffer */
661 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
662 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
663 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
664 DXGetErrorString8(rc));
668 ZeroMemory(&bufdesc, sizeof(bufdesc));
669 bufdesc.dwSize=sizeof(bufdesc);
670 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
671 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
672 ok(rc==DS_OK && primary!=NULL,
673 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
674 "%s\n",DXGetErrorString8(rc));
676 if (rc==DS_OK && primary!=NULL) {
677 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
678 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
679 DXGetErrorString8(rc));
683 for (f=0;f<NB_FORMATS;f++) {
684 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
687 ZeroMemory(&bufdesc, sizeof(bufdesc));
688 bufdesc.dwSize=sizeof(bufdesc);
689 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
690 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
692 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
693 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
694 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
695 DXGetErrorString8(rc));
696 if (rc==DS_OK && secondary!=NULL)
697 IDirectSoundBuffer_Release(secondary);
700 ZeroMemory(&bufdesc, sizeof(bufdesc));
701 bufdesc.dwSize=sizeof(bufdesc);
702 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
703 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
705 bufdesc.lpwfxFormat=&wfx;
706 if (winetest_interactive) {
707 trace(" Testing a secondary buffer at %ldx%dx%d "
708 "with a primary buffer at %ldx%dx%d\n",
709 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
710 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
712 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
713 ok(rc==DS_OK && secondary!=NULL,
714 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
715 "buffer %s\n",DXGetErrorString8(rc));
717 if (rc==DS_OK && secondary!=NULL) {
718 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
719 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
721 ref=IDirectSoundBuffer_Release(secondary);
722 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
723 "should have 0\n",ref);
727 ref=IDirectSoundBuffer_Release(primary);
728 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
729 "should have 0\n",ref);
732 /* Set the CooperativeLevel back to normal */
733 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
734 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
735 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
736 DXGetErrorString8(rc));
739 ref=IDirectSound_Release(dso);
740 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
742 return DSERR_GENERIC;
747 static HRESULT test_block_align(LPGUID lpGuid)
750 LPDIRECTSOUND dso=NULL;
751 LPDIRECTSOUNDBUFFER secondary=NULL;
752 DSBUFFERDESC bufdesc;
757 /* Create the DirectSound object */
758 rc=DirectSoundCreate(lpGuid,&dso,NULL);
759 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
760 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
764 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
765 ZeroMemory(&bufdesc, sizeof(bufdesc));
766 bufdesc.dwSize=sizeof(bufdesc);
767 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
768 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
769 bufdesc.lpwfxFormat=&wfx;
770 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
771 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
772 "should have returned DS_OK, returned: %s\n",
773 DXGetErrorString8(rc));
775 if (rc==DS_OK && secondary!=NULL) {
776 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
777 dsbcaps.dwSize = sizeof(dsbcaps);
778 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
779 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
780 "returned: %s\n", DXGetErrorString8(rc));
782 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
783 "Buffer size not a multiple of nBlockAlign: requested %ld, "
784 "got %ld, should be %ld\n", bufdesc.dwBufferBytes,
785 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
786 ref=IDirectSoundBuffer_Release(secondary);
787 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
788 "should have 0\n",ref);
791 ref=IDirectSound_Release(dso);
792 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
794 return DSERR_GENERIC;
802 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
804 static HRESULT test_frequency(LPGUID lpGuid)
807 LPDIRECTSOUND dso=NULL;
808 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
809 DSBUFFERDESC bufdesc;
811 WAVEFORMATEX wfx, wfx1;
814 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
817 /* Create the DirectSound object */
818 rc=DirectSoundCreate(lpGuid,&dso,NULL);
819 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
820 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
824 /* Get the device capabilities */
825 ZeroMemory(&dscaps, sizeof(dscaps));
826 dscaps.dwSize=sizeof(dscaps);
827 rc=IDirectSound_GetCaps(dso,&dscaps);
828 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
832 /* We must call SetCooperativeLevel before creating primary buffer */
833 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
834 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
835 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
836 DXGetErrorString8(rc));
840 ZeroMemory(&bufdesc, sizeof(bufdesc));
841 bufdesc.dwSize=sizeof(bufdesc);
842 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
843 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
844 ok(rc==DS_OK && primary!=NULL,
845 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
846 "%s\n",DXGetErrorString8(rc));
848 if (rc==DS_OK && primary!=NULL) {
849 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
850 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
851 DXGetErrorString8(rc));
855 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
856 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
857 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
860 ZeroMemory(&bufdesc, sizeof(bufdesc));
861 bufdesc.dwSize=sizeof(bufdesc);
862 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
863 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
864 BUFFER_LEN/1000,wfx.nBlockAlign);
865 bufdesc.lpwfxFormat=&wfx;
866 if (winetest_interactive) {
867 trace(" Testing a secondary buffer at %ldx%dx%d "
868 "with a primary buffer at %ldx%dx%d\n",
869 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
870 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
872 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
873 ok(rc==DS_OK && secondary!=NULL,
874 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
875 "buffer %s\n",DXGetErrorString8(rc));
877 if (rc==DS_OK && secondary!=NULL) {
878 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
879 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
881 ref=IDirectSoundBuffer_Release(secondary);
882 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
883 "should have 0\n",ref);
888 ref=IDirectSoundBuffer_Release(primary);
889 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
890 "should have 0\n",ref);
893 /* Set the CooperativeLevel back to normal */
894 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
895 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
896 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
897 DXGetErrorString8(rc));
900 ref=IDirectSound_Release(dso);
901 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
903 return DSERR_GENERIC;
908 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
909 LPCSTR lpcstrModule, LPVOID lpContext)
912 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
913 rc = test_dsound(lpGuid);
914 if (rc == DSERR_NODRIVER)
915 trace(" No Driver\n");
916 else if (rc == DSERR_ALLOCATED)
917 trace(" Already In Use\n");
918 else if (rc == E_FAIL)
919 trace(" No Device\n");
921 test_block_align(lpGuid);
922 test_primary(lpGuid);
923 test_primary_secondary(lpGuid);
924 test_secondary(lpGuid);
925 test_frequency(lpGuid);
931 static void dsound_tests()
934 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
935 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
942 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
944 IDirectSound_tests();