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 Allocated\n");
106 /* DSOUND: Error: Invalid caps buffer */
107 rc=IDirectSound_GetCaps(dso,0);
108 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
109 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
110 DXGetErrorString8(rc));
112 ZeroMemory(&dscaps, sizeof(dscaps));
114 /* DSOUND: Error: Invalid caps buffer */
115 rc=IDirectSound_GetCaps(dso,&dscaps);
116 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
117 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
118 DXGetErrorString8(rc));
120 dscaps.dwSize=sizeof(dscaps);
122 /* DSOUND: Running on a certified driver */
123 rc=IDirectSound_GetCaps(dso,&dscaps);
124 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
126 rc=IDirectSound_Compact(dso);
127 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
128 DXGetErrorString8(rc));
130 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
131 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
132 DXGetErrorString8(rc));
134 rc=IDirectSound_Compact(dso);
135 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
137 rc=IDirectSound_GetSpeakerConfig(dso,0);
138 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
139 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
140 DXGetErrorString8(rc));
142 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
143 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
144 DXGetErrorString8(rc));
146 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
147 DSSPEAKER_GEOMETRY_WIDE);
148 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
149 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
150 DXGetErrorString8(rc));
152 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
153 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
154 DXGetErrorString8(rc));
155 if (rc==DS_OK && speaker_config!=new_speaker_config)
156 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
157 "config: expected 0x%08lx, got 0x%08lx\n",
158 speaker_config,new_speaker_config);
161 ref=IDirectSound_Release(dso);
162 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
165 static void IDirectSound_tests()
168 LPDIRECTSOUND dso=NULL;
170 trace("Testing IDirectSound\n");
172 /* try the COM class factory method of creation with no device specified */
173 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
174 &IID_IDirectSound, (void**)&dso);
175 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
176 DXGetErrorString8(rc));
178 IDirectSound_test(dso, FALSE, NULL);
180 /* try the COM class factory method of creation with default playback
181 * device specified */
182 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
183 &IID_IDirectSound, (void**)&dso);
184 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
185 DXGetErrorString8(rc));
187 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
189 /* try the COM class factory method of creation with default voice
190 * playback device specified */
191 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
192 &IID_IDirectSound, (void**)&dso);
193 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
194 DXGetErrorString8(rc));
196 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
198 /* try the COM class factory method of creation with a bad
200 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
201 &CLSID_DirectSoundPrivate, (void**)&dso);
202 ok(rc==E_NOINTERFACE,
203 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
204 "should have failed: %s\n",DXGetErrorString8(rc));
206 /* try the COM class factory method of creation with a bad
207 * GUID and IID specified */
208 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
209 &IID_IDirectSound, (void**)&dso);
210 ok(rc==REGDB_E_CLASSNOTREG,
211 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
212 "should have failed: %s\n",DXGetErrorString8(rc));
214 /* try with no device specified */
215 rc=DirectSoundCreate(NULL,&dso,NULL);
216 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
217 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
219 IDirectSound_test(dso, TRUE, NULL);
221 /* try with default playback device specified */
222 rc=DirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
223 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
224 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
225 DXGetErrorString8(rc));
226 if (rc==DS_OK && dso)
227 IDirectSound_test(dso, TRUE, NULL);
229 /* try with default voice playback device specified */
230 rc=DirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
231 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
232 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
233 DXGetErrorString8(rc));
234 if (rc==DS_OK && dso)
235 IDirectSound_test(dso, TRUE, NULL);
237 /* try with a bad device specified */
238 rc=DirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
239 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
240 "should have failed: %s\n",DXGetErrorString8(rc));
243 static HRESULT test_dsound(LPGUID lpGuid)
246 LPDIRECTSOUND dso=NULL;
249 /* DSOUND: Error: Invalid interface buffer */
250 rc=DirectSoundCreate(lpGuid,0,NULL);
251 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
252 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
254 /* Create the DirectSound object */
255 rc=DirectSoundCreate(lpGuid,&dso,NULL);
256 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
257 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
261 /* Try the enumerated device */
262 IDirectSound_test(dso, TRUE, lpGuid);
264 /* Try the COM class factory method of creation with enumerated device */
265 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
266 &IID_IDirectSound, (void**)&dso);
267 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
268 DXGetErrorString8(rc));
270 IDirectSound_test(dso, FALSE, lpGuid);
272 /* Create a DirectSound object */
273 rc=DirectSoundCreate(lpGuid,&dso,NULL);
274 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
276 LPDIRECTSOUND dso1=NULL;
278 /* Create a second DirectSound object */
279 rc=DirectSoundCreate(lpGuid,&dso1,NULL);
280 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
282 /* Release the second DirectSound object */
283 ref=IDirectSound_Release(dso1);
284 ok(ref==0,"IDirectSound_Release() has %d references, should have "
286 ok(dso!=dso1,"DirectSound objects should be unique: "
287 "dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
290 /* Release the first DirectSound object */
291 ref=IDirectSound_Release(dso);
292 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
295 return DSERR_GENERIC;
299 /* Create a DirectSound object */
300 rc=DirectSoundCreate(lpGuid,&dso,NULL);
301 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
303 LPDIRECTSOUNDBUFFER secondary;
304 DSBUFFERDESC bufdesc;
307 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
308 ZeroMemory(&bufdesc, sizeof(bufdesc));
309 bufdesc.dwSize=sizeof(bufdesc);
310 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
311 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
313 bufdesc.lpwfxFormat=&wfx;
314 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
315 ok(rc==DS_OK && secondary!=NULL,
316 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
317 "buffer %s\n",DXGetErrorString8(rc));
318 if (rc==DS_OK && secondary!=NULL) {
319 LPDIRECTSOUND3DBUFFER buffer3d;
320 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
322 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
323 "failed: %s\n",DXGetErrorString8(rc));
324 if (rc==DS_OK && buffer3d!=NULL) {
325 ref=IDirectSound3DBuffer_AddRef(buffer3d);
326 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
327 "should have 2\n",ref);
329 ref=IDirectSoundBuffer_AddRef(secondary);
330 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
331 "should have 2\n",ref);
333 /* release with buffer */
334 ref=IDirectSound_Release(dso);
335 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
338 return DSERR_GENERIC;
345 static HRESULT test_primary(LPGUID lpGuid)
348 LPDIRECTSOUND dso=NULL;
349 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
350 DSBUFFERDESC bufdesc;
355 /* Create the DirectSound object */
356 rc=DirectSoundCreate(lpGuid,&dso,NULL);
357 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
358 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
362 /* Get the device capabilities */
363 ZeroMemory(&dscaps, sizeof(dscaps));
364 dscaps.dwSize=sizeof(dscaps);
365 rc=IDirectSound_GetCaps(dso,&dscaps);
366 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
370 /* DSOUND: Error: Invalid buffer description pointer */
371 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
372 ok(rc==DSERR_INVALIDPARAM,
373 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
374 DXGetErrorString8(rc));
376 /* DSOUND: Error: Invalid buffer description pointer */
377 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
378 ok(rc==DSERR_INVALIDPARAM && primary==0,
379 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
380 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
382 /* DSOUND: Error: Invalid buffer description pointer */
383 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
384 ok(rc==DSERR_INVALIDPARAM && primary==0,
385 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
386 "dsbo=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
388 ZeroMemory(&bufdesc, sizeof(bufdesc));
390 /* DSOUND: Error: Invalid size */
391 /* DSOUND: Error: Invalid buffer description */
392 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
393 ok(rc==DSERR_INVALIDPARAM && primary==0,
394 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
395 "primary=0x%lx\n",DXGetErrorString8(rc),(DWORD)primary);
397 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
398 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
399 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
400 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
401 DXGetErrorString8(rc));
405 /* Testing the primary buffer */
407 ZeroMemory(&bufdesc, sizeof(bufdesc));
408 bufdesc.dwSize=sizeof(bufdesc);
409 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
410 bufdesc.lpwfxFormat = &wfx;
411 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
412 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
413 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
414 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
415 if (rc==DS_OK && primary!=NULL)
416 IDirectSoundBuffer_Release(primary);
419 ZeroMemory(&bufdesc, sizeof(bufdesc));
420 bufdesc.dwSize=sizeof(bufdesc);
421 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
422 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
423 ok(rc==DS_OK && primary!=NULL,
424 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
425 "%s\n",DXGetErrorString8(rc));
426 if (rc==DS_OK && primary!=NULL) {
429 /* Try to create a second primary buffer */
430 /* DSOUND: Error: The primary buffer already exists.
431 * Any changes made to the buffer description will be ignored. */
432 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
433 ok(rc==DS_OK && second==primary,
434 "IDirectSound_CreateSoundBuffer() should have returned original "
435 "primary buffer: %s\n",DXGetErrorString8(rc));
436 ref=IDirectSoundBuffer_Release(second);
437 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
438 "should have 1\n",ref);
440 /* Try to duplicate a primary buffer */
441 /* DSOUND: Error: Can't duplicate primary buffers */
442 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
444 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
445 "should have failed %s\n",DXGetErrorString8(rc));
447 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
448 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
449 DXGetErrorString8(rc));
451 if (winetest_interactive) {
452 trace("Playing a 5 seconds reference tone at the current "
455 trace("(the current volume is %ld according to DirectSound)\n",
457 trace("All subsequent tones should be identical to this one.\n");
458 trace("Listen for stutter, changes in pitch, volume, etc.\n");
460 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
461 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
463 ref=IDirectSoundBuffer_Release(primary);
464 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
465 "should have 0\n",ref);
468 /* Set the CooperativeLevel back to normal */
469 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
470 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
471 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
472 DXGetErrorString8(rc));
475 ref=IDirectSound_Release(dso);
476 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
478 return DSERR_GENERIC;
484 * Test the primary buffer at different formats while keeping the
485 * secondary buffer at a constant format.
487 static HRESULT test_primary_secondary(LPGUID lpGuid)
490 LPDIRECTSOUND dso=NULL;
491 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
492 DSBUFFERDESC bufdesc;
494 WAVEFORMATEX wfx, wfx2;
497 /* Create the DirectSound object */
498 rc=DirectSoundCreate(lpGuid,&dso,NULL);
499 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
500 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
504 /* Get the device capabilities */
505 ZeroMemory(&dscaps, sizeof(dscaps));
506 dscaps.dwSize=sizeof(dscaps);
507 rc=IDirectSound_GetCaps(dso,&dscaps);
508 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
512 /* We must call SetCooperativeLevel before creating primary buffer */
513 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
514 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
515 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
516 DXGetErrorString8(rc));
520 ZeroMemory(&bufdesc, sizeof(bufdesc));
521 bufdesc.dwSize=sizeof(bufdesc);
522 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
523 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
524 ok(rc==DS_OK && primary!=NULL,
525 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
526 "%s\n",DXGetErrorString8(rc));
528 if (rc==DS_OK && primary!=NULL) {
529 for (f=0;f<NB_FORMATS;f++) {
530 /* We must call SetCooperativeLevel to be allowed to call
532 /* DSOUND: Setting DirectSound cooperative level to
534 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
535 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
536 DXGetErrorString8(rc));
540 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
543 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
544 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
545 DXGetErrorString8(rc));
547 /* There is no garantee that SetFormat will actually change the
548 * format to what we asked for. It depends on what the soundcard
549 * supports. So we must re-query the format.
551 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
552 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
553 DXGetErrorString8(rc));
555 (wfx.wFormatTag!=wfx2.wFormatTag ||
556 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
557 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
558 wfx.nChannels!=wfx2.nChannels)) {
559 trace("Requested primary format tag=0x%04x %ldx%dx%d "
560 "avg.B/s=%ld align=%d\n",
561 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
562 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
563 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
564 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
565 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
568 /* Set the CooperativeLevel back to normal */
569 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
570 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
571 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
572 DXGetErrorString8(rc));
574 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
577 ZeroMemory(&bufdesc, sizeof(bufdesc));
578 bufdesc.dwSize=sizeof(bufdesc);
579 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
580 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
582 bufdesc.lpwfxFormat=&wfx2;
583 if (winetest_interactive) {
584 trace(" Testing a primary buffer at %ldx%dx%d with a "
585 "secondary buffer at %ldx%dx%d\n",
586 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
587 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
589 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
590 ok(rc==DS_OK && secondary!=NULL,
591 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
592 "buffer %s\n",DXGetErrorString8(rc));
594 if (rc==DS_OK && secondary!=NULL) {
595 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
596 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
598 ref=IDirectSoundBuffer_Release(secondary);
599 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
600 "should have 0\n",ref);
604 ref=IDirectSoundBuffer_Release(primary);
605 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
606 "should have 0\n",ref);
609 /* Set the CooperativeLevel back to normal */
610 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
611 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
612 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
613 DXGetErrorString8(rc));
616 ref=IDirectSound_Release(dso);
617 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
619 return DSERR_GENERIC;
624 static HRESULT test_secondary(LPGUID lpGuid)
627 LPDIRECTSOUND dso=NULL;
628 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
629 DSBUFFERDESC bufdesc;
631 WAVEFORMATEX wfx, wfx1;
635 /* Create the DirectSound object */
636 rc=DirectSoundCreate(lpGuid,&dso,NULL);
637 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
638 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
642 /* Get the device capabilities */
643 ZeroMemory(&dscaps, sizeof(dscaps));
644 dscaps.dwSize=sizeof(dscaps);
645 rc=IDirectSound_GetCaps(dso,&dscaps);
646 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
650 /* We must call SetCooperativeLevel before creating primary buffer */
651 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
652 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
653 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
654 DXGetErrorString8(rc));
658 ZeroMemory(&bufdesc, sizeof(bufdesc));
659 bufdesc.dwSize=sizeof(bufdesc);
660 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
661 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
662 ok(rc==DS_OK && primary!=NULL,
663 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
664 "%s\n",DXGetErrorString8(rc));
666 if (rc==DS_OK && primary!=NULL) {
667 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
668 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
669 DXGetErrorString8(rc));
673 for (f=0;f<NB_FORMATS;f++) {
674 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
677 ZeroMemory(&bufdesc, sizeof(bufdesc));
678 bufdesc.dwSize=sizeof(bufdesc);
679 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
680 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
682 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
683 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
684 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
685 DXGetErrorString8(rc));
686 if (rc==DS_OK && secondary!=NULL)
687 IDirectSoundBuffer_Release(secondary);
690 ZeroMemory(&bufdesc, sizeof(bufdesc));
691 bufdesc.dwSize=sizeof(bufdesc);
692 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
693 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
695 bufdesc.lpwfxFormat=&wfx;
696 if (winetest_interactive) {
697 trace(" Testing a secondary buffer at %ldx%dx%d "
698 "with a primary buffer at %ldx%dx%d\n",
699 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
700 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
702 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
703 ok(rc==DS_OK && secondary!=NULL,
704 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
705 "buffer %s\n",DXGetErrorString8(rc));
707 if (rc==DS_OK && secondary!=NULL) {
708 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
709 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
711 ref=IDirectSoundBuffer_Release(secondary);
712 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
713 "should have 0\n",ref);
717 ref=IDirectSoundBuffer_Release(primary);
718 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
719 "should have 0\n",ref);
722 /* Set the CooperativeLevel back to normal */
723 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
724 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
725 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
726 DXGetErrorString8(rc));
729 ref=IDirectSound_Release(dso);
730 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
732 return DSERR_GENERIC;
737 static HRESULT test_block_align(LPGUID lpGuid)
740 LPDIRECTSOUND dso=NULL;
741 LPDIRECTSOUNDBUFFER secondary=NULL;
742 DSBUFFERDESC bufdesc;
747 /* Create the DirectSound object */
748 rc=DirectSoundCreate(lpGuid,&dso,NULL);
749 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
750 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
754 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
755 ZeroMemory(&bufdesc, sizeof(bufdesc));
756 bufdesc.dwSize=sizeof(bufdesc);
757 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
758 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
759 bufdesc.lpwfxFormat=&wfx;
760 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
761 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
762 "should have returned DS_OK, returned: %s\n",
763 DXGetErrorString8(rc));
765 if (rc==DS_OK && secondary!=NULL) {
766 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
767 dsbcaps.dwSize = sizeof(dsbcaps);
768 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
769 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
770 "returned: %s\n", DXGetErrorString8(rc));
772 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
773 "Buffer size not a multiple of nBlockAlign: requested %ld, "
774 "got %ld, should be %ld\n", bufdesc.dwBufferBytes,
775 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
776 ref=IDirectSoundBuffer_Release(secondary);
777 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
778 "should have 0\n",ref);
781 ref=IDirectSound_Release(dso);
782 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
784 return DSERR_GENERIC;
792 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
794 static HRESULT test_frequency(LPGUID lpGuid)
797 LPDIRECTSOUND dso=NULL;
798 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
799 DSBUFFERDESC bufdesc;
801 WAVEFORMATEX wfx, wfx1;
804 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
807 /* Create the DirectSound object */
808 rc=DirectSoundCreate(lpGuid,&dso,NULL);
809 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
810 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
814 /* Get the device capabilities */
815 ZeroMemory(&dscaps, sizeof(dscaps));
816 dscaps.dwSize=sizeof(dscaps);
817 rc=IDirectSound_GetCaps(dso,&dscaps);
818 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
822 /* We must call SetCooperativeLevel before creating primary buffer */
823 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
824 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
825 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
826 DXGetErrorString8(rc));
830 ZeroMemory(&bufdesc, sizeof(bufdesc));
831 bufdesc.dwSize=sizeof(bufdesc);
832 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
833 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
834 ok(rc==DS_OK && primary!=NULL,
835 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
836 "%s\n",DXGetErrorString8(rc));
838 if (rc==DS_OK && primary!=NULL) {
839 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
840 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
841 DXGetErrorString8(rc));
845 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
846 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
847 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
850 ZeroMemory(&bufdesc, sizeof(bufdesc));
851 bufdesc.dwSize=sizeof(bufdesc);
852 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
853 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
854 BUFFER_LEN/1000,wfx.nBlockAlign);
855 bufdesc.lpwfxFormat=&wfx;
856 if (winetest_interactive) {
857 trace(" Testing a secondary buffer at %ldx%dx%d "
858 "with a primary buffer at %ldx%dx%d\n",
859 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
860 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
862 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
863 ok(rc==DS_OK && secondary!=NULL,
864 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
865 "buffer %s\n",DXGetErrorString8(rc));
867 if (rc==DS_OK && secondary!=NULL) {
868 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
869 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
871 ref=IDirectSoundBuffer_Release(secondary);
872 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
873 "should have 0\n",ref);
878 ref=IDirectSoundBuffer_Release(primary);
879 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
880 "should have 0\n",ref);
883 /* Set the CooperativeLevel back to normal */
884 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
885 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
886 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
887 DXGetErrorString8(rc));
890 ref=IDirectSound_Release(dso);
891 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
893 return DSERR_GENERIC;
898 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
899 LPCSTR lpcstrModule, LPVOID lpContext)
902 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
903 rc = test_dsound(lpGuid);
904 if (rc == DSERR_NODRIVER)
905 trace(" No Driver\n");
906 else if (rc == DSERR_ALLOCATED)
907 trace(" Already In Use\n");
908 else if (rc == E_FAIL)
909 trace(" No Device\n");
911 test_block_align(lpGuid);
912 test_primary(lpGuid);
913 test_primary_secondary(lpGuid);
914 test_secondary(lpGuid);
915 test_frequency(lpGuid);
921 static void dsound_tests()
924 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
925 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
932 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
934 IDirectSound_tests();