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
30 #include "wine/test.h"
35 #include "dsound_test.h"
37 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
38 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*,
41 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
50 DWORD speaker_config, new_speaker_config;
52 /* Try to Query for objects */
53 rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
54 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
55 DXGetErrorString8(rc));
57 IDirectSound_Release(unknown);
59 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
60 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
61 DXGetErrorString8(rc));
63 IDirectSound_Release(ds);
65 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
66 ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
67 "should have failed: %s\n",DXGetErrorString8(rc));
69 IDirectSound8_Release(ds8);
71 if (initialized == FALSE) {
72 /* try uninitialized object */
73 rc=IDirectSound_GetCaps(dso,0);
74 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
75 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
76 DXGetErrorString8(rc));
78 rc=IDirectSound_GetCaps(dso,&dscaps);
79 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
80 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
81 DXGetErrorString8(rc));
83 rc=IDirectSound_Compact(dso);
84 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
85 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
86 DXGetErrorString8(rc));
88 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
89 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
90 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
91 DXGetErrorString8(rc));
93 rc=IDirectSound_Initialize(dso,lpGuid);
94 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
95 "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
96 if (rc==DSERR_NODRIVER) {
97 trace(" No Driver\n");
99 } else if (rc==E_FAIL) {
100 trace(" No Device\n");
102 } else if (rc==DSERR_ALLOCATED) {
103 trace(" Already In Use\n");
108 rc=IDirectSound_Initialize(dso,lpGuid);
109 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
110 "should have returned DSERR_ALREADYINITIALIZED: %s\n",
111 DXGetErrorString8(rc));
113 /* DSOUND: Error: Invalid caps buffer */
114 rc=IDirectSound_GetCaps(dso,0);
115 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
116 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
117 DXGetErrorString8(rc));
119 ZeroMemory(&dscaps, sizeof(dscaps));
121 /* DSOUND: Error: Invalid caps buffer */
122 rc=IDirectSound_GetCaps(dso,&dscaps);
123 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
124 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
125 DXGetErrorString8(rc));
127 dscaps.dwSize=sizeof(dscaps);
129 /* DSOUND: Running on a certified driver */
130 rc=IDirectSound_GetCaps(dso,&dscaps);
131 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
133 rc=IDirectSound_Compact(dso);
134 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
135 DXGetErrorString8(rc));
137 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
138 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
139 DXGetErrorString8(rc));
141 rc=IDirectSound_Compact(dso);
142 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
144 rc=IDirectSound_GetSpeakerConfig(dso,0);
145 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
146 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
147 DXGetErrorString8(rc));
149 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
150 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
151 DXGetErrorString8(rc));
153 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
154 DSSPEAKER_GEOMETRY_WIDE);
155 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
156 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
157 DXGetErrorString8(rc));
159 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
160 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
161 DXGetErrorString8(rc));
162 if (rc==DS_OK && speaker_config!=new_speaker_config)
163 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
164 "config: expected 0x%08x, got 0x%08x\n",
165 speaker_config,new_speaker_config);
169 ref=IDirectSound_Release(dso);
170 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
173 static void IDirectSound_tests(void)
176 LPDIRECTSOUND dso=NULL;
177 LPCLASSFACTORY cf=NULL;
179 trace("Testing IDirectSound\n");
181 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
182 &IID_IClassFactory, (void**)&cf);
183 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
184 "failed: %s\n", DXGetErrorString8(rc));
186 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
187 &IID_IUnknown, (void**)&cf);
188 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
189 "failed: %s\n", DXGetErrorString8(rc));
191 /* try the COM class factory method of creation with no device specified */
192 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
193 &IID_IDirectSound, (void**)&dso);
194 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
195 DXGetErrorString8(rc));
197 IDirectSound_test(dso, FALSE, NULL);
199 /* try the COM class factory method of creation with default playback
200 * device specified */
201 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
202 &IID_IDirectSound, (void**)&dso);
203 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
204 DXGetErrorString8(rc));
206 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
208 /* try the COM class factory method of creation with default voice
209 * playback device specified */
210 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
211 &IID_IDirectSound, (void**)&dso);
212 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
213 DXGetErrorString8(rc));
215 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
217 /* try the COM class factory method of creation with a bad
219 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
220 &CLSID_DirectSoundPrivate, (void**)&dso);
221 ok(rc==E_NOINTERFACE,
222 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
223 "should have failed: %s\n",DXGetErrorString8(rc));
225 /* try the COM class factory method of creation with a bad
226 * GUID and IID specified */
227 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
228 &IID_IDirectSound, (void**)&dso);
229 ok(rc==REGDB_E_CLASSNOTREG,
230 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
231 "should have failed: %s\n",DXGetErrorString8(rc));
233 /* try with no device specified */
234 rc=pDirectSoundCreate(NULL,&dso,NULL);
235 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
236 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
238 IDirectSound_test(dso, TRUE, NULL);
240 /* try with default playback device specified */
241 rc=pDirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
242 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
243 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
244 DXGetErrorString8(rc));
245 if (rc==DS_OK && dso)
246 IDirectSound_test(dso, TRUE, NULL);
248 /* try with default voice playback device specified */
249 rc=pDirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
250 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
251 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
252 DXGetErrorString8(rc));
253 if (rc==DS_OK && dso)
254 IDirectSound_test(dso, TRUE, NULL);
256 /* try with a bad device specified */
257 rc=pDirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
258 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
259 "should have failed: %s\n",DXGetErrorString8(rc));
260 if (rc==DS_OK && dso)
261 IDirectSound_Release(dso);
264 static HRESULT test_dsound(LPGUID lpGuid)
267 LPDIRECTSOUND dso=NULL;
270 /* DSOUND: Error: Invalid interface buffer */
271 rc=pDirectSoundCreate(lpGuid,0,NULL);
272 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
273 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
275 /* Create the DirectSound object */
276 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
277 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
278 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
282 /* Try the enumerated device */
283 IDirectSound_test(dso, TRUE, lpGuid);
285 /* Try the COM class factory method of creation with enumerated device */
286 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
287 &IID_IDirectSound, (void**)&dso);
288 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
289 DXGetErrorString8(rc));
291 IDirectSound_test(dso, FALSE, lpGuid);
293 /* Create a DirectSound object */
294 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
295 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
297 LPDIRECTSOUND dso1=NULL;
299 /* Create a second DirectSound object */
300 rc=pDirectSoundCreate(lpGuid,&dso1,NULL);
301 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
303 /* Release the second DirectSound object */
304 ref=IDirectSound_Release(dso1);
305 ok(ref==0,"IDirectSound_Release() has %d references, should have "
307 ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
310 /* Release the first DirectSound object */
311 ref=IDirectSound_Release(dso);
312 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
315 return DSERR_GENERIC;
319 /* Create a DirectSound object */
320 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
321 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
323 LPDIRECTSOUNDBUFFER secondary;
324 DSBUFFERDESC bufdesc;
327 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
328 ZeroMemory(&bufdesc, sizeof(bufdesc));
329 bufdesc.dwSize=sizeof(bufdesc);
330 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
331 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
333 bufdesc.lpwfxFormat=&wfx;
334 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
335 ok(rc==DS_OK && secondary!=NULL,
336 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
337 "buffer %s\n",DXGetErrorString8(rc));
338 if (rc==DS_OK && secondary!=NULL) {
339 LPDIRECTSOUND3DBUFFER buffer3d;
340 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
342 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
343 "failed: %s\n",DXGetErrorString8(rc));
344 if (rc==DS_OK && buffer3d!=NULL) {
345 ref=IDirectSound3DBuffer_AddRef(buffer3d);
346 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
347 "should have 2\n",ref);
349 ref=IDirectSoundBuffer_AddRef(secondary);
350 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
351 "should have 2\n",ref);
353 /* release with buffer */
354 ref=IDirectSound_Release(dso);
355 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
358 return DSERR_GENERIC;
365 static HRESULT test_primary(LPGUID lpGuid)
368 LPDIRECTSOUND dso=NULL;
369 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
370 DSBUFFERDESC bufdesc;
375 /* Create the DirectSound object */
376 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
377 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
378 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
382 /* Get the device capabilities */
383 ZeroMemory(&dscaps, sizeof(dscaps));
384 dscaps.dwSize=sizeof(dscaps);
385 rc=IDirectSound_GetCaps(dso,&dscaps);
386 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
390 /* DSOUND: Error: Invalid buffer description pointer */
391 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
392 ok(rc==DSERR_INVALIDPARAM,
393 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
394 DXGetErrorString8(rc));
396 /* DSOUND: Error: Invalid buffer description pointer */
397 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
398 ok(rc==DSERR_INVALIDPARAM && primary==0,
399 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
400 "dsbo=%p\n",DXGetErrorString8(rc),primary);
402 /* DSOUND: Error: Invalid buffer description pointer */
403 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
404 ok(rc==DSERR_INVALIDPARAM && primary==0,
405 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
406 "dsbo=0x%p\n",DXGetErrorString8(rc),primary);
408 ZeroMemory(&bufdesc, sizeof(bufdesc));
410 /* DSOUND: Error: Invalid size */
411 /* DSOUND: Error: Invalid buffer description */
412 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
413 ok(rc==DSERR_INVALIDPARAM && primary==0,
414 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
415 "primary=%p\n",DXGetErrorString8(rc),primary);
417 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
418 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
419 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
420 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
421 DXGetErrorString8(rc));
425 /* Testing the primary buffer */
427 ZeroMemory(&bufdesc, sizeof(bufdesc));
428 bufdesc.dwSize=sizeof(bufdesc);
429 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
430 bufdesc.lpwfxFormat = &wfx;
431 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
432 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
433 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
434 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
435 if (rc==DS_OK && primary!=NULL)
436 IDirectSoundBuffer_Release(primary);
439 ZeroMemory(&bufdesc, sizeof(bufdesc));
440 bufdesc.dwSize=sizeof(bufdesc);
441 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
442 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
443 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
444 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
445 "%s\n",DXGetErrorString8(rc));
446 if (rc==DSERR_CONTROLUNAVAIL)
447 trace(" No Primary\n");
448 else if (rc==DS_OK && primary!=NULL) {
451 /* Try to create a second primary buffer */
452 /* DSOUND: Error: The primary buffer already exists.
453 * Any changes made to the buffer description will be ignored. */
454 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
455 ok(rc==DS_OK && second==primary,
456 "IDirectSound_CreateSoundBuffer() should have returned original "
457 "primary buffer: %s\n",DXGetErrorString8(rc));
458 ref=IDirectSoundBuffer_Release(second);
459 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
460 "should have 1\n",ref);
462 /* Try to duplicate a primary buffer */
463 /* DSOUND: Error: Can't duplicate primary buffers */
464 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
466 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
467 "should have failed %s\n",DXGetErrorString8(rc));
469 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
470 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
471 DXGetErrorString8(rc));
473 if (winetest_interactive) {
474 trace("Playing a 5 seconds reference tone at the current "
477 trace("(the current volume is %d according to DirectSound)\n",
479 trace("All subsequent tones should be identical to this one.\n");
480 trace("Listen for stutter, changes in pitch, volume, etc.\n");
482 test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
483 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
485 ref=IDirectSoundBuffer_Release(primary);
486 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
487 "should have 0\n",ref);
490 /* Set the CooperativeLevel back to normal */
491 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
492 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
493 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
494 DXGetErrorString8(rc));
497 ref=IDirectSound_Release(dso);
498 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
500 return DSERR_GENERIC;
506 * Test the primary buffer at different formats while keeping the
507 * secondary buffer at a constant format.
509 static HRESULT test_primary_secondary(LPGUID lpGuid)
512 LPDIRECTSOUND dso=NULL;
513 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
514 DSBUFFERDESC bufdesc;
516 WAVEFORMATEX wfx, wfx2;
519 /* Create the DirectSound object */
520 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
521 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
522 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
526 /* Get the device capabilities */
527 ZeroMemory(&dscaps, sizeof(dscaps));
528 dscaps.dwSize=sizeof(dscaps);
529 rc=IDirectSound_GetCaps(dso,&dscaps);
530 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
534 /* We must call SetCooperativeLevel before creating primary buffer */
535 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
536 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
537 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
538 DXGetErrorString8(rc));
542 ZeroMemory(&bufdesc, sizeof(bufdesc));
543 bufdesc.dwSize=sizeof(bufdesc);
544 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
545 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
546 ok(rc==DS_OK && primary!=NULL,
547 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
548 "%s\n",DXGetErrorString8(rc));
550 if (rc==DS_OK && primary!=NULL) {
551 for (f=0;f<NB_FORMATS;f++) {
552 /* We must call SetCooperativeLevel to be allowed to call
554 /* DSOUND: Setting DirectSound cooperative level to
556 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
557 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
558 DXGetErrorString8(rc));
562 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
565 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
566 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
567 format_string(&wfx), DXGetErrorString8(rc));
569 /* There is no guarantee that SetFormat will actually change the
570 * format to what we asked for. It depends on what the soundcard
571 * supports. So we must re-query the format.
573 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
574 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
575 DXGetErrorString8(rc));
577 (wfx.wFormatTag!=wfx2.wFormatTag ||
578 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
579 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
580 wfx.nChannels!=wfx2.nChannels)) {
581 trace("Requested primary format tag=0x%04x %dx%dx%d "
582 "avg.B/s=%d align=%d\n",
583 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
584 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
585 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
586 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
587 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
590 /* Set the CooperativeLevel back to normal */
591 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
592 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
593 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
594 DXGetErrorString8(rc));
596 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
599 ZeroMemory(&bufdesc, sizeof(bufdesc));
600 bufdesc.dwSize=sizeof(bufdesc);
601 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
602 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
604 bufdesc.lpwfxFormat=&wfx2;
605 if (winetest_interactive) {
606 trace(" Testing a primary buffer at %dx%dx%d with a "
607 "secondary buffer at %dx%dx%d\n",
608 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
609 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
611 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
612 ok(rc==DS_OK && secondary!=NULL,
613 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
614 "buffer %s\n",DXGetErrorString8(rc));
616 if (rc==DS_OK && secondary!=NULL) {
617 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
618 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
620 ref=IDirectSoundBuffer_Release(secondary);
621 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
622 "should have 0\n",ref);
626 ref=IDirectSoundBuffer_Release(primary);
627 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
628 "should have 0\n",ref);
631 /* Set the CooperativeLevel back to normal */
632 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
633 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
634 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
635 DXGetErrorString8(rc));
638 ref=IDirectSound_Release(dso);
639 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
641 return DSERR_GENERIC;
646 static HRESULT test_secondary(LPGUID lpGuid)
649 LPDIRECTSOUND dso=NULL;
650 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
651 DSBUFFERDESC bufdesc;
653 WAVEFORMATEX wfx, wfx1;
657 /* Create the DirectSound object */
658 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
659 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
660 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
664 /* Get the device capabilities */
665 ZeroMemory(&dscaps, sizeof(dscaps));
666 dscaps.dwSize=sizeof(dscaps);
667 rc=IDirectSound_GetCaps(dso,&dscaps);
668 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
672 /* We must call SetCooperativeLevel before creating primary buffer */
673 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
674 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
675 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
676 DXGetErrorString8(rc));
680 ZeroMemory(&bufdesc, sizeof(bufdesc));
681 bufdesc.dwSize=sizeof(bufdesc);
682 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
683 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
684 ok(rc==DS_OK && primary!=NULL,
685 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
686 "%s\n",DXGetErrorString8(rc));
688 if (rc==DS_OK && primary!=NULL) {
689 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
690 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
691 DXGetErrorString8(rc));
695 for (f=0;f<NB_FORMATS;f++) {
696 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
699 ZeroMemory(&bufdesc, sizeof(bufdesc));
700 bufdesc.dwSize=sizeof(bufdesc);
701 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
702 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
704 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
705 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
706 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
707 DXGetErrorString8(rc));
708 if (rc==DS_OK && secondary!=NULL)
709 IDirectSoundBuffer_Release(secondary);
712 ZeroMemory(&bufdesc, sizeof(bufdesc));
713 bufdesc.dwSize=sizeof(bufdesc);
714 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
715 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
717 bufdesc.lpwfxFormat=&wfx;
718 if (winetest_interactive) {
719 trace(" Testing a secondary buffer at %dx%dx%d "
720 "with a primary buffer at %dx%dx%d\n",
721 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
722 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
724 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
725 ok(rc==DS_OK && secondary!=NULL,
726 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
727 "buffer %s\n",DXGetErrorString8(rc));
729 if (rc==DS_OK && secondary!=NULL) {
730 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
731 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
733 ref=IDirectSoundBuffer_Release(secondary);
734 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
735 "should have 0\n",ref);
739 ref=IDirectSoundBuffer_Release(primary);
740 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
741 "should have 0\n",ref);
744 /* Set the CooperativeLevel back to normal */
745 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
746 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
747 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
748 DXGetErrorString8(rc));
751 ref=IDirectSound_Release(dso);
752 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
754 return DSERR_GENERIC;
759 static HRESULT test_block_align(LPGUID lpGuid)
762 LPDIRECTSOUND dso=NULL;
763 LPDIRECTSOUNDBUFFER secondary=NULL;
764 DSBUFFERDESC bufdesc;
769 /* Create the DirectSound object */
770 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
771 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
772 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
776 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
777 ZeroMemory(&bufdesc, sizeof(bufdesc));
778 bufdesc.dwSize=sizeof(bufdesc);
779 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
780 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
781 bufdesc.lpwfxFormat=&wfx;
782 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
783 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
784 "should have returned DS_OK, returned: %s\n",
785 DXGetErrorString8(rc));
787 if (rc==DS_OK && secondary!=NULL) {
788 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
789 dsbcaps.dwSize = sizeof(dsbcaps);
790 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
791 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
792 "returned: %s\n", DXGetErrorString8(rc));
794 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
795 "Buffer size not a multiple of nBlockAlign: requested %d, "
796 "got %d, should be %d\n", bufdesc.dwBufferBytes,
797 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
798 ref=IDirectSoundBuffer_Release(secondary);
799 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
800 "should have 0\n",ref);
803 ref=IDirectSound_Release(dso);
804 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
806 return DSERR_GENERIC;
814 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
816 static HRESULT test_frequency(LPGUID lpGuid)
819 LPDIRECTSOUND dso=NULL;
820 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
821 DSBUFFERDESC bufdesc;
823 WAVEFORMATEX wfx, wfx1;
826 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
829 /* Create the DirectSound object */
830 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
831 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
832 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
836 /* Get the device capabilities */
837 ZeroMemory(&dscaps, sizeof(dscaps));
838 dscaps.dwSize=sizeof(dscaps);
839 rc=IDirectSound_GetCaps(dso,&dscaps);
840 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
844 /* We must call SetCooperativeLevel before creating primary buffer */
845 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
846 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
847 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
848 DXGetErrorString8(rc));
852 ZeroMemory(&bufdesc, sizeof(bufdesc));
853 bufdesc.dwSize=sizeof(bufdesc);
854 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
855 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
856 ok(rc==DS_OK && primary!=NULL,
857 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
858 "%s\n",DXGetErrorString8(rc));
860 if (rc==DS_OK && primary!=NULL) {
861 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
862 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
863 DXGetErrorString8(rc));
867 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
868 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
869 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
872 ZeroMemory(&bufdesc, sizeof(bufdesc));
873 bufdesc.dwSize=sizeof(bufdesc);
874 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
875 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
876 BUFFER_LEN/1000,wfx.nBlockAlign);
877 bufdesc.lpwfxFormat=&wfx;
878 if (winetest_interactive) {
879 trace(" Testing a secondary buffer at %dx%dx%d "
880 "with a primary buffer at %dx%dx%d\n",
881 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
882 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
884 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
885 ok(rc==DS_OK && secondary!=NULL,
886 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
887 "buffer %s\n",DXGetErrorString8(rc));
889 if (rc==DS_OK && secondary!=NULL) {
890 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
891 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
893 ref=IDirectSoundBuffer_Release(secondary);
894 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
895 "should have 0\n",ref);
900 ref=IDirectSoundBuffer_Release(primary);
901 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
902 "should have 0\n",ref);
905 /* Set the CooperativeLevel back to normal */
906 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
907 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
908 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
909 DXGetErrorString8(rc));
912 ref=IDirectSound_Release(dso);
913 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
915 return DSERR_GENERIC;
920 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
921 LPCSTR lpcstrModule, LPVOID lpContext)
924 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
925 rc = test_dsound(lpGuid);
926 if (rc == DSERR_NODRIVER)
927 trace(" No Driver\n");
928 else if (rc == DSERR_ALLOCATED)
929 trace(" Already In Use\n");
930 else if (rc == E_FAIL)
931 trace(" No Device\n");
933 test_block_align(lpGuid);
934 test_primary(lpGuid);
935 test_primary_secondary(lpGuid);
936 test_secondary(lpGuid);
937 test_frequency(lpGuid);
943 static void dsound_tests(void)
946 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
947 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
956 hDsound = LoadLibrary("dsound.dll");
959 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
961 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
962 "DirectSoundEnumerateA");
963 pDirectSoundCreate = (void*)GetProcAddress(hDsound,
964 "DirectSoundCreate");
966 IDirectSound_tests();
969 FreeLibrary(hDsound);
972 skip("dsound.dll not found!\n");