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
12 * Copyright (c) 2007 Maarten Lankhorst
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
36 #include "dsound_test.h"
38 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
39 static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID,LPDIRECTSOUND*,
42 static void IDirectSound_test(LPDIRECTSOUND dso, BOOL initialized,
51 DWORD speaker_config, new_speaker_config;
53 /* Try to Query for objects */
54 rc=IDirectSound_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
55 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IUnknown) failed: %s\n",
56 DXGetErrorString8(rc));
58 IDirectSound_Release(unknown);
60 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
61 ok(rc==DS_OK,"IDirectSound_QueryInterface(IID_IDirectSound) failed: %s\n",
62 DXGetErrorString8(rc));
64 IDirectSound_Release(ds);
66 rc=IDirectSound_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
67 ok(rc==E_NOINTERFACE,"IDirectSound_QueryInterface(IID_IDirectSound8) "
68 "should have failed: %s\n",DXGetErrorString8(rc));
70 IDirectSound8_Release(ds8);
72 if (initialized == FALSE) {
73 /* try uninitialized object */
74 rc=IDirectSound_GetCaps(dso,0);
75 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps(NULL) "
76 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
77 DXGetErrorString8(rc));
79 rc=IDirectSound_GetCaps(dso,&dscaps);
80 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetCaps() "
81 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
82 DXGetErrorString8(rc));
84 rc=IDirectSound_Compact(dso);
85 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_Compact() "
86 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
87 DXGetErrorString8(rc));
89 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
90 ok(rc==DSERR_UNINITIALIZED,"IDirectSound_GetSpeakerConfig() "
91 "should have returned DSERR_UNINITIALIZED, returned: %s\n",
92 DXGetErrorString8(rc));
94 rc=IDirectSound_Initialize(dso,lpGuid);
95 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
96 "IDirectSound_Initialize() failed: %s\n",DXGetErrorString8(rc));
97 if (rc==DSERR_NODRIVER) {
98 trace(" No Driver\n");
100 } else if (rc==E_FAIL) {
101 trace(" No Device\n");
103 } else if (rc==DSERR_ALLOCATED) {
104 trace(" Already In Use\n");
109 rc=IDirectSound_Initialize(dso,lpGuid);
110 ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound_Initialize() "
111 "should have returned DSERR_ALREADYINITIALIZED: %s\n",
112 DXGetErrorString8(rc));
114 /* DSOUND: Error: Invalid caps buffer */
115 rc=IDirectSound_GetCaps(dso,0);
116 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps(NULL) "
117 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
118 DXGetErrorString8(rc));
120 ZeroMemory(&dscaps, sizeof(dscaps));
122 /* DSOUND: Error: Invalid caps buffer */
123 rc=IDirectSound_GetCaps(dso,&dscaps);
124 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetCaps() "
125 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
126 DXGetErrorString8(rc));
128 dscaps.dwSize=sizeof(dscaps);
130 /* DSOUND: Running on a certified driver */
131 rc=IDirectSound_GetCaps(dso,&dscaps);
132 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
134 rc=IDirectSound_Compact(dso);
135 ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound_Compact() failed: %s\n",
136 DXGetErrorString8(rc));
138 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
139 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
140 DXGetErrorString8(rc));
142 rc=IDirectSound_Compact(dso);
143 ok(rc==DS_OK,"IDirectSound_Compact() failed: %s\n",DXGetErrorString8(rc));
145 rc=IDirectSound_GetSpeakerConfig(dso,0);
146 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_GetSpeakerConfig(NULL) "
147 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
148 DXGetErrorString8(rc));
150 rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
151 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
152 DXGetErrorString8(rc));
154 speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
155 DSSPEAKER_GEOMETRY_WIDE);
156 rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
157 ok(rc==DS_OK,"IDirectSound_SetSpeakerConfig() failed: %s\n",
158 DXGetErrorString8(rc));
160 rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
161 ok(rc==DS_OK,"IDirectSound_GetSpeakerConfig() failed: %s\n",
162 DXGetErrorString8(rc));
163 if (rc==DS_OK && speaker_config!=new_speaker_config)
164 trace("IDirectSound_GetSpeakerConfig() failed to set speaker "
165 "config: expected 0x%08x, got 0x%08x\n",
166 speaker_config,new_speaker_config);
170 ref=IDirectSound_Release(dso);
171 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
174 static void IDirectSound_tests(void)
177 LPDIRECTSOUND dso=NULL;
178 LPCLASSFACTORY cf=NULL;
180 trace("Testing IDirectSound\n");
182 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
183 &IID_IClassFactory, (void**)&cf);
184 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IClassFactory) "
185 "failed: %s\n", DXGetErrorString8(rc));
187 rc=CoGetClassObject(&CLSID_DirectSound, CLSCTX_INPROC_SERVER, NULL,
188 &IID_IUnknown, (void**)&cf);
189 ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound, IID_IUnknown) "
190 "failed: %s\n", DXGetErrorString8(rc));
192 /* try the COM class factory method of creation with no device specified */
193 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
194 &IID_IDirectSound, (void**)&dso);
195 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
196 DXGetErrorString8(rc));
198 IDirectSound_test(dso, FALSE, NULL);
200 /* try the COM class factory method of creation with default playback
201 * device specified */
202 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
203 &IID_IDirectSound, (void**)&dso);
204 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
205 DXGetErrorString8(rc));
207 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultPlayback);
209 /* try the COM class factory method of creation with default voice
210 * playback device specified */
211 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
212 &IID_IDirectSound, (void**)&dso);
213 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
214 DXGetErrorString8(rc));
216 IDirectSound_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);
218 /* try the COM class factory method of creation with a bad
220 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
221 &CLSID_DirectSoundPrivate, (void**)&dso);
222 ok(rc==E_NOINTERFACE,
223 "CoCreateInstance(CLSID_DirectSound,CLSID_DirectSoundPrivate) "
224 "should have failed: %s\n",DXGetErrorString8(rc));
226 /* try the COM class factory method of creation with a bad
227 * GUID and IID specified */
228 rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
229 &IID_IDirectSound, (void**)&dso);
230 ok(rc==REGDB_E_CLASSNOTREG,
231 "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound) "
232 "should have failed: %s\n",DXGetErrorString8(rc));
234 /* try with no device specified */
235 rc=pDirectSoundCreate(NULL,&dso,NULL);
236 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
237 "DirectSoundCreate(NULL) failed: %s\n",DXGetErrorString8(rc));
239 IDirectSound_test(dso, TRUE, NULL);
241 /* try with default playback device specified */
242 rc=pDirectSoundCreate(&DSDEVID_DefaultPlayback,&dso,NULL);
243 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
244 "DirectSoundCreate(DSDEVID_DefaultPlayback) failed: %s\n",
245 DXGetErrorString8(rc));
246 if (rc==DS_OK && dso)
247 IDirectSound_test(dso, TRUE, NULL);
249 /* try with default voice playback device specified */
250 rc=pDirectSoundCreate(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
251 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
252 "DirectSoundCreate(DSDEVID_DefaultVoicePlayback) failed: %s\n",
253 DXGetErrorString8(rc));
254 if (rc==DS_OK && dso)
255 IDirectSound_test(dso, TRUE, NULL);
257 /* try with a bad device specified */
258 rc=pDirectSoundCreate(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
259 ok(rc==DSERR_NODRIVER,"DirectSoundCreate(DSDEVID_DefaultVoiceCapture) "
260 "should have failed: %s\n",DXGetErrorString8(rc));
261 if (rc==DS_OK && dso)
262 IDirectSound_Release(dso);
265 static HRESULT test_dsound(LPGUID lpGuid)
268 LPDIRECTSOUND dso=NULL;
271 /* DSOUND: Error: Invalid interface buffer */
272 rc=pDirectSoundCreate(lpGuid,0,NULL);
273 ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate() should have returned "
274 "DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
276 /* Create the DirectSound object */
277 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
278 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
279 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
283 /* Try the enumerated device */
284 IDirectSound_test(dso, TRUE, lpGuid);
286 /* Try the COM class factory method of creation with enumerated device */
287 rc=CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
288 &IID_IDirectSound, (void**)&dso);
289 ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %s\n",
290 DXGetErrorString8(rc));
292 IDirectSound_test(dso, FALSE, lpGuid);
294 /* Create a DirectSound object */
295 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
296 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
298 LPDIRECTSOUND dso1=NULL;
300 /* Create a second DirectSound object */
301 rc=pDirectSoundCreate(lpGuid,&dso1,NULL);
302 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
304 /* Release the second DirectSound object */
305 ref=IDirectSound_Release(dso1);
306 ok(ref==0,"IDirectSound_Release() has %d references, should have "
308 ok(dso!=dso1,"DirectSound objects should be unique: dso=%p,dso1=%p\n",dso,dso1);
311 /* Release the first DirectSound object */
312 ref=IDirectSound_Release(dso);
313 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
316 return DSERR_GENERIC;
320 /* Create a DirectSound object */
321 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
322 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
324 LPDIRECTSOUNDBUFFER secondary;
325 DSBUFFERDESC bufdesc;
328 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
329 ZeroMemory(&bufdesc, sizeof(bufdesc));
330 bufdesc.dwSize=sizeof(bufdesc);
331 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
332 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
334 bufdesc.lpwfxFormat=&wfx;
335 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
336 ok(rc==DS_OK && secondary!=NULL,
337 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
338 "buffer %s\n",DXGetErrorString8(rc));
339 if (rc==DS_OK && secondary!=NULL) {
340 LPDIRECTSOUND3DBUFFER buffer3d;
341 rc=IDirectSound_QueryInterface(secondary, &IID_IDirectSound3DBuffer,
343 ok(rc==DS_OK && buffer3d!=NULL,"IDirectSound_QueryInterface() "
344 "failed: %s\n",DXGetErrorString8(rc));
345 if (rc==DS_OK && buffer3d!=NULL) {
346 ref=IDirectSound3DBuffer_AddRef(buffer3d);
347 ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
348 "should have 2\n",ref);
350 ref=IDirectSoundBuffer_AddRef(secondary);
351 ok(ref==2,"IDirectSoundBuffer_AddRef() has %d references, "
352 "should have 2\n",ref);
354 /* release with buffer */
355 ref=IDirectSound_Release(dso);
356 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",
359 return DSERR_GENERIC;
366 static HRESULT test_primary(LPGUID lpGuid)
369 LPDIRECTSOUND dso=NULL;
370 LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
371 DSBUFFERDESC bufdesc;
376 /* Create the DirectSound object */
377 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
378 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
379 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
383 /* Get the device capabilities */
384 ZeroMemory(&dscaps, sizeof(dscaps));
385 dscaps.dwSize=sizeof(dscaps);
386 rc=IDirectSound_GetCaps(dso,&dscaps);
387 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
391 /* DSOUND: Error: Invalid buffer description pointer */
392 rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
393 ok(rc==DSERR_INVALIDPARAM,
394 "IDirectSound_CreateSoundBuffer() should have failed: %s\n",
395 DXGetErrorString8(rc));
397 /* DSOUND: Error: Invalid buffer description pointer */
398 rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
399 ok(rc==DSERR_INVALIDPARAM && primary==0,
400 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
401 "dsbo=%p\n",DXGetErrorString8(rc),primary);
403 /* DSOUND: Error: Invalid buffer description pointer */
404 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
405 ok(rc==DSERR_INVALIDPARAM && primary==0,
406 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
407 "dsbo=0x%p\n",DXGetErrorString8(rc),primary);
409 ZeroMemory(&bufdesc, sizeof(bufdesc));
411 /* DSOUND: Error: Invalid size */
412 /* DSOUND: Error: Invalid buffer description */
413 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
414 ok(rc==DSERR_INVALIDPARAM && primary==0,
415 "IDirectSound_CreateSoundBuffer() should have failed: rc=%s,"
416 "primary=%p\n",DXGetErrorString8(rc),primary);
418 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
419 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
420 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
421 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
422 DXGetErrorString8(rc));
426 /* Testing the primary buffer */
428 ZeroMemory(&bufdesc, sizeof(bufdesc));
429 bufdesc.dwSize=sizeof(bufdesc);
430 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
431 bufdesc.lpwfxFormat = &wfx;
432 init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
433 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
434 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() should have "
435 "returned DSERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(rc));
436 if (rc==DS_OK && primary!=NULL)
437 IDirectSoundBuffer_Release(primary);
440 ZeroMemory(&bufdesc, sizeof(bufdesc));
441 bufdesc.dwSize=sizeof(bufdesc);
442 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
443 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
444 ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
445 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer: "
446 "%s\n",DXGetErrorString8(rc));
447 if (rc==DSERR_CONTROLUNAVAIL)
448 trace(" No Primary\n");
449 else if (rc==DS_OK && primary!=NULL) {
452 /* Try to create a second primary buffer */
453 /* DSOUND: Error: The primary buffer already exists.
454 * Any changes made to the buffer description will be ignored. */
455 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
456 ok(rc==DS_OK && second==primary,
457 "IDirectSound_CreateSoundBuffer() should have returned original "
458 "primary buffer: %s\n",DXGetErrorString8(rc));
459 ref=IDirectSoundBuffer_Release(second);
460 ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
461 "should have 1\n",ref);
463 /* Try to duplicate a primary buffer */
464 /* DSOUND: Error: Can't duplicate primary buffers */
465 rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
467 ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer() primary buffer "
468 "should have failed %s\n",DXGetErrorString8(rc));
470 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
471 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
472 DXGetErrorString8(rc));
474 if (winetest_interactive) {
475 trace("Playing a 5 seconds reference tone at the current "
478 trace("(the current volume is %d according to DirectSound)\n",
480 trace("All subsequent tones should be identical to this one.\n");
481 trace("Listen for stutter, changes in pitch, volume, etc.\n");
483 test_buffer(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive &&
484 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
486 ref=IDirectSoundBuffer_Release(primary);
487 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
488 "should have 0\n",ref);
491 /* Set the CooperativeLevel back to normal */
492 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
493 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
494 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
495 DXGetErrorString8(rc));
498 ref=IDirectSound_Release(dso);
499 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
501 return DSERR_GENERIC;
507 * Test the primary buffer at different formats while keeping the
508 * secondary buffer at a constant format.
510 static HRESULT test_primary_secondary(LPGUID lpGuid)
513 LPDIRECTSOUND dso=NULL;
514 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
515 DSBUFFERDESC bufdesc;
517 WAVEFORMATEX wfx, wfx2;
520 /* Create the DirectSound object */
521 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
522 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
523 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
527 /* Get the device capabilities */
528 ZeroMemory(&dscaps, sizeof(dscaps));
529 dscaps.dwSize=sizeof(dscaps);
530 rc=IDirectSound_GetCaps(dso,&dscaps);
531 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
535 /* We must call SetCooperativeLevel before creating primary buffer */
536 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
537 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
538 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
539 DXGetErrorString8(rc));
543 ZeroMemory(&bufdesc, sizeof(bufdesc));
544 bufdesc.dwSize=sizeof(bufdesc);
545 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
546 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
547 ok(rc==DS_OK && primary!=NULL,
548 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
549 "%s\n",DXGetErrorString8(rc));
551 if (rc==DS_OK && primary!=NULL) {
552 for (f=0;f<NB_FORMATS;f++) {
553 /* We must call SetCooperativeLevel to be allowed to call
555 /* DSOUND: Setting DirectSound cooperative level to
557 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
558 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
559 DXGetErrorString8(rc));
563 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
566 rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
567 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %s\n",
568 format_string(&wfx), DXGetErrorString8(rc));
570 /* There is no guarantee that SetFormat will actually change the
571 * format to what we asked for. It depends on what the soundcard
572 * supports. So we must re-query the format.
574 rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
575 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
576 DXGetErrorString8(rc));
578 (wfx.wFormatTag!=wfx2.wFormatTag ||
579 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
580 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
581 wfx.nChannels!=wfx2.nChannels)) {
582 trace("Requested primary format tag=0x%04x %dx%dx%d "
583 "avg.B/s=%d align=%d\n",
584 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
585 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
586 trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
587 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
588 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
591 /* Set the CooperativeLevel back to normal */
592 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
593 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
594 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
595 DXGetErrorString8(rc));
597 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
600 ZeroMemory(&bufdesc, sizeof(bufdesc));
601 bufdesc.dwSize=sizeof(bufdesc);
602 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
603 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
605 bufdesc.lpwfxFormat=&wfx2;
606 if (winetest_interactive) {
607 trace(" Testing a primary buffer at %dx%dx%d with a "
608 "secondary buffer at %dx%dx%d\n",
609 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
610 wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
612 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
613 ok(rc==DS_OK && secondary!=NULL,
614 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
615 "buffer %s\n",DXGetErrorString8(rc));
617 if (rc==DS_OK && secondary!=NULL) {
618 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
619 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
621 ref=IDirectSoundBuffer_Release(secondary);
622 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
623 "should have 0\n",ref);
627 ref=IDirectSoundBuffer_Release(primary);
628 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
629 "should have 0\n",ref);
632 /* Set the CooperativeLevel back to normal */
633 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
634 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
635 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
636 DXGetErrorString8(rc));
639 ref=IDirectSound_Release(dso);
640 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
642 return DSERR_GENERIC;
647 static HRESULT test_secondary(LPGUID lpGuid)
650 LPDIRECTSOUND dso=NULL;
651 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
652 DSBUFFERDESC bufdesc;
654 WAVEFORMATEX wfx, wfx1;
658 /* Create the DirectSound object */
659 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
660 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
661 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
665 /* Get the device capabilities */
666 ZeroMemory(&dscaps, sizeof(dscaps));
667 dscaps.dwSize=sizeof(dscaps);
668 rc=IDirectSound_GetCaps(dso,&dscaps);
669 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
673 /* We must call SetCooperativeLevel before creating primary buffer */
674 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
675 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
676 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
677 DXGetErrorString8(rc));
681 ZeroMemory(&bufdesc, sizeof(bufdesc));
682 bufdesc.dwSize=sizeof(bufdesc);
683 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
684 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
685 ok(rc==DS_OK && primary!=NULL,
686 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
687 "%s\n",DXGetErrorString8(rc));
689 if (rc==DS_OK && primary!=NULL) {
690 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
691 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
692 DXGetErrorString8(rc));
696 for (f=0;f<NB_FORMATS;f++) {
697 init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],
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 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
706 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_CreateSoundBuffer() "
707 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
708 DXGetErrorString8(rc));
709 if (rc==DS_OK && secondary!=NULL)
710 IDirectSoundBuffer_Release(secondary);
713 ZeroMemory(&bufdesc, sizeof(bufdesc));
714 bufdesc.dwSize=sizeof(bufdesc);
715 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
716 bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
718 bufdesc.lpwfxFormat=&wfx;
719 if (winetest_interactive) {
720 trace(" Testing a secondary buffer at %dx%dx%d "
721 "with a primary buffer at %dx%dx%d\n",
722 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
723 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
725 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
726 ok(rc==DS_OK && secondary!=NULL,
727 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
728 "buffer %s\n",DXGetErrorString8(rc));
730 if (rc==DS_OK && secondary!=NULL) {
731 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
732 winetest_interactive,1.0,0,NULL,0,0,FALSE,0);
734 ref=IDirectSoundBuffer_Release(secondary);
735 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
736 "should have 0\n",ref);
740 ref=IDirectSoundBuffer_Release(primary);
741 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
742 "should have 0\n",ref);
745 /* Set the CooperativeLevel back to normal */
746 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
747 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
748 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
749 DXGetErrorString8(rc));
752 ref=IDirectSound_Release(dso);
753 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
755 return DSERR_GENERIC;
760 static HRESULT test_block_align(LPGUID lpGuid)
763 LPDIRECTSOUND dso=NULL;
764 LPDIRECTSOUNDBUFFER secondary=NULL;
765 DSBUFFERDESC bufdesc;
771 /* Create the DirectSound object */
772 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
773 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
774 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
778 init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2);
779 ZeroMemory(&bufdesc, sizeof(bufdesc));
780 bufdesc.dwSize=sizeof(bufdesc);
781 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
782 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1;
783 bufdesc.lpwfxFormat=&wfx;
784 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
785 ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() "
786 "should have returned DS_OK, returned: %s\n",
787 DXGetErrorString8(rc));
789 if (rc==DS_OK && secondary!=NULL) {
790 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
791 dsbcaps.dwSize = sizeof(dsbcaps);
792 rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps);
793 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, "
794 "returned: %s\n", DXGetErrorString8(rc));
795 if (rc==DS_OK && wfx.nBlockAlign > 1)
797 ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign),
798 "Buffer size not a multiple of nBlockAlign: requested %d, "
799 "got %d, should be %d\n", bufdesc.dwBufferBytes,
800 dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign);
802 rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0);
803 ok(rc == DS_OK, "Could not set position to 0: %s\n", DXGetErrorString8(rc));
804 rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL);
805 ok(rc == DS_OK, "Could not get position: %s\n", DXGetErrorString8(rc));
806 rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1);
807 ok(rc == DS_OK, "Could not set position to 1: %s\n", DXGetErrorString8(rc));
808 rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL);
809 ok(rc == DS_OK, "Could not get new position: %s\n", DXGetErrorString8(rc));
810 ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2);
812 ref=IDirectSoundBuffer_Release(secondary);
813 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, "
814 "should have 0\n",ref);
817 ref=IDirectSound_Release(dso);
818 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
820 return DSERR_GENERIC;
828 } fmts[] = { { 8, 1 }, { 8, 2 }, { 16, 1 }, {16, 2 } };
830 static HRESULT test_frequency(LPGUID lpGuid)
833 LPDIRECTSOUND dso=NULL;
834 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
835 DSBUFFERDESC bufdesc;
837 WAVEFORMATEX wfx, wfx1;
840 int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
843 /* Create the DirectSound object */
844 rc=pDirectSoundCreate(lpGuid,&dso,NULL);
845 ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
846 "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
850 /* Get the device capabilities */
851 ZeroMemory(&dscaps, sizeof(dscaps));
852 dscaps.dwSize=sizeof(dscaps);
853 rc=IDirectSound_GetCaps(dso,&dscaps);
854 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
858 /* We must call SetCooperativeLevel before creating primary buffer */
859 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
860 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
861 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
862 DXGetErrorString8(rc));
866 ZeroMemory(&bufdesc, sizeof(bufdesc));
867 bufdesc.dwSize=sizeof(bufdesc);
868 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
869 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
870 ok(rc==DS_OK && primary!=NULL,
871 "IDirectSound_CreateSoundBuffer() failed to create a primary buffer "
872 "%s\n",DXGetErrorString8(rc));
874 if (rc==DS_OK && primary!=NULL) {
875 rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
876 ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n",
877 DXGetErrorString8(rc));
881 for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) {
882 for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) {
883 init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits,
886 ZeroMemory(&bufdesc, sizeof(bufdesc));
887 bufdesc.dwSize=sizeof(bufdesc);
888 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY;
889 bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)*
890 BUFFER_LEN/1000,wfx.nBlockAlign);
891 bufdesc.lpwfxFormat=&wfx;
892 if (winetest_interactive) {
893 trace(" Testing a secondary buffer at %dx%dx%d "
894 "with a primary buffer at %dx%dx%d\n",
895 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
896 wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
898 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
899 ok(rc==DS_OK && secondary!=NULL,
900 "IDirectSound_CreateSoundBuffer() failed to create a secondary "
901 "buffer %s\n",DXGetErrorString8(rc));
903 if (rc==DS_OK && secondary!=NULL) {
904 test_buffer(dso,&secondary,0,FALSE,0,FALSE,0,
905 winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]);
907 ref=IDirectSoundBuffer_Release(secondary);
908 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
909 "should have 0\n",ref);
914 ref=IDirectSoundBuffer_Release(primary);
915 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
916 "should have 0\n",ref);
919 /* Set the CooperativeLevel back to normal */
920 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
921 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
922 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
923 DXGetErrorString8(rc));
926 ref=IDirectSound_Release(dso);
927 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
929 return DSERR_GENERIC;
934 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
935 LPCSTR lpcstrModule, LPVOID lpContext)
938 trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
939 rc = test_dsound(lpGuid);
940 if (rc == DSERR_NODRIVER)
941 trace(" No Driver\n");
942 else if (rc == DSERR_ALLOCATED)
943 trace(" Already In Use\n");
944 else if (rc == E_FAIL)
945 trace(" No Device\n");
947 test_block_align(lpGuid);
948 test_primary(lpGuid);
949 test_primary_secondary(lpGuid);
950 test_secondary(lpGuid);
951 test_frequency(lpGuid);
957 static void dsound_tests(void)
960 rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
961 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));
970 hDsound = LoadLibrary("dsound.dll");
973 ok( FreeLibrary(hDsound), "FreeLibrary(1) returned %d\n", GetLastError());
974 ok( FreeLibrary(hDsound), "FreeLibrary(2) returned %d\n", GetLastError());
975 ok(!FreeLibrary(hDsound), "DirectSound DLL still loaded\n");
978 hDsound = LoadLibrary("dsound.dll");
981 trace("DLL Version: %s\n", get_file_version("dsound.dll"));
983 pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
984 "DirectSoundEnumerateA");
985 pDirectSoundCreate = (void*)GetProcAddress(hDsound,
986 "DirectSoundCreate");
988 IDirectSound_tests();
991 FreeLibrary(hDsound);
994 skip("dsound.dll not found!\n");