2 * Tests the panning and 3D functions of DirectSound
4 * Part of this test involves playing test tones. But this only makes
5 * sense if someone is going to carefully listen to it, and would only
6 * bother everyone else.
7 * So this is only done if the test is being run in interactive mode.
9 * Copyright (c) 2002-2004 Francois Gouget
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSSTRUCT
27 #define NONAMELESSUNION
33 #include "wine/test.h"
39 #include "dsound_test.h"
41 #define PI 3.14159265358979323846
42 char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
49 nb_samples=(int)(duration*wfx->nSamplesPerSec);
50 *size=nb_samples*wfx->nBlockAlign;
52 for (i=0;i<nb_samples;i++) {
53 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
54 if (wfx->wBitsPerSample==8) {
55 unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
57 if (wfx->nChannels==2)
60 signed short sample=(signed short)((double)32767.5*y-0.5);
64 if (wfx->nChannels==2) {
76 HWND hwnd=GetForegroundWindow();
78 hwnd=GetDesktopWindow();
82 void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth,
85 wfx->wFormatTag=format;
86 wfx->nChannels=channels;
87 wfx->wBitsPerSample=depth;
88 wfx->nSamplesPerSec=rate;
89 wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
90 /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */
91 if (wfx->nBlockAlign==0)
93 /* align compressed formats to byte boundary */
96 wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
104 LPDIRECTSOUNDBUFFER dsbo;
112 static int buffer_refill(play_state_t* state, DWORD size)
118 if (size>state->wave_len-state->written)
119 size=state->wave_len-state->written;
121 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
122 &ptr1,&len1,&ptr2,&len2,0);
123 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n",
124 DXGetErrorString8(rc));
128 memcpy(ptr1,state->wave+state->written,len1);
129 state->written+=len1;
131 memcpy(ptr2,state->wave+state->written,len2);
132 state->written+=len2;
134 state->offset=state->written % state->buffer_size;
135 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
136 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n",
137 DXGetErrorString8(rc));
143 static int buffer_silence(play_state_t* state, DWORD size)
150 rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
151 &ptr1,&len1,&ptr2,&len2,0);
152 ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %s\n",
153 DXGetErrorString8(rc));
157 s=(state->wfx->wBitsPerSample==8?0x80:0);
162 state->offset=(state->offset+size) % state->buffer_size;
163 rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
164 ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %s\n",
165 DXGetErrorString8(rc));
171 static int buffer_service(play_state_t* state)
173 DWORD last_play_pos,play_pos,buf_free;
176 rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
177 ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %s\n",
178 DXGetErrorString8(rc));
183 /* Update the amount played */
184 last_play_pos=state->played % state->buffer_size;
185 if (play_pos<last_play_pos)
186 state->played+=state->buffer_size-last_play_pos+play_pos;
188 state->played+=play_pos-last_play_pos;
190 if (winetest_debug > 1)
191 trace("buf size=%ld last_play_pos=%ld play_pos=%ld played=%ld / %ld\n",
192 state->buffer_size,last_play_pos,play_pos,state->played,
195 if (state->played>state->wave_len)
197 /* Everything has been played */
201 /* Refill the buffer */
202 if (state->offset<=play_pos)
203 buf_free=play_pos-state->offset;
205 buf_free=state->buffer_size-state->offset+play_pos;
207 if (winetest_debug > 1)
208 trace("offset=%ld free=%ld written=%ld / %ld\n",
209 state->offset,buf_free,state->written,state->wave_len);
213 if (state->written<state->wave_len)
215 int w=buffer_refill(state,buf_free);
219 if (state->written==state->wave_len && winetest_debug > 1)
220 trace("last sound byte at %ld\n",
221 (state->written % state->buffer_size));
225 /* Fill with silence */
226 if (winetest_debug > 1)
227 trace("writing %ld bytes of silence\n",buf_free);
228 if (buffer_silence(state,buf_free)==-1)
234 if (winetest_debug > 1)
235 trace("stopping playback\n");
236 rc=IDirectSoundBuffer_Stop(state->dsbo);
237 ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %s\n",
238 DXGetErrorString8(rc));
242 void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
243 BOOL is_primary, BOOL set_volume, LONG volume,
244 BOOL set_pan, LONG pan, BOOL play, double duration,
245 BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
246 BOOL move_listener, BOOL move_sound)
250 WAVEFORMATEX wfx,wfx2;
251 DWORD size,status,freq;
254 /* DSOUND: Error: Invalid caps pointer */
255 rc=IDirectSoundBuffer_GetCaps(dsbo,0);
256 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
257 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
259 ZeroMemory(&dsbcaps, sizeof(dsbcaps));
261 /* DSOUND: Error: Invalid caps pointer */
262 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
263 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
264 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
266 dsbcaps.dwSize=sizeof(dsbcaps);
267 rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
268 ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %s\n",
269 DXGetErrorString8(rc));
270 if (rc==DS_OK && winetest_debug > 1) {
271 trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
272 dsbcaps.dwBufferBytes);
275 /* Query the format size. Note that it may not match sizeof(wfx) */
277 rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
278 ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
279 "returned the needed size: rc=%s size=%ld\n",DXGetErrorString8(rc),size);
281 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
282 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
283 DXGetErrorString8(rc));
284 if (rc==DS_OK && is_primary && winetest_debug > 1) {
285 trace("Primary buffer default format: tag=0x%04x %ldx%dx%d "
286 "avg.B/s=%ld align=%d\n",
287 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
288 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
291 /* DSOUND: Error: Invalid frequency buffer */
292 rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
293 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
294 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
296 /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
297 rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
298 ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
299 (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
300 "IDirectSoundBuffer_GetFrequency() failed: %s\n",DXGetErrorString8(rc));
302 ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
303 "%ld does not match the format %ld\n",freq,wfx.nSamplesPerSec);
306 /* DSOUND: Error: Invalid status pointer */
307 rc=IDirectSoundBuffer_GetStatus(dsbo,0);
308 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
309 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
311 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
312 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %s\n",
313 DXGetErrorString8(rc));
314 ok(status==0,"status=0x%lx instead of 0\n",status);
317 /* We must call SetCooperativeLevel to be allowed to call SetFormat */
318 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
319 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
320 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
321 DXGetErrorString8(rc));
325 /* DSOUND: Error: Invalid format pointer */
326 rc=IDirectSoundBuffer_SetFormat(dsbo,0);
327 ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
328 "returned DSERR_INVALIDPARAM, returned: %s\n",DXGetErrorString8(rc));
330 init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
331 rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
332 ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat() failed: %s\n",
333 DXGetErrorString8(rc));
335 /* There is no garantee that SetFormat will actually change the
336 * format to what we asked for. It depends on what the soundcard
337 * supports. So we must re-query the format.
339 rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
340 ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %s\n",
341 DXGetErrorString8(rc));
343 (wfx.wFormatTag!=wfx2.wFormatTag ||
344 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
345 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
346 wfx.nChannels!=wfx2.nChannels)) {
347 trace("Requested format tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
348 wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
349 wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
350 trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
351 wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
352 wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
355 /* Set the CooperativeLevel back to normal */
356 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
357 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
358 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
359 DXGetErrorString8(rc));
364 DS3DLISTENER listener_param;
365 LPDIRECTSOUND3DBUFFER buffer=NULL;
366 DS3DBUFFER buffer_param;
367 DWORD start_time,now;
369 if (winetest_interactive) {
370 trace(" Playing %g second 440Hz tone at %ldx%dx%d\n", duration,
371 wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
375 /* We must call SetCooperativeLevel to be allowed to call Lock */
376 /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
377 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
378 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
379 DXGetErrorString8(rc));
384 LPDIRECTSOUNDBUFFER temp_buffer;
386 rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,
388 ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %s\n",
389 DXGetErrorString8(rc));
393 /* check the COM interface */
394 rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,
395 (LPVOID *)&temp_buffer);
396 ok(rc==DS_OK && temp_buffer!=NULL,
397 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
398 DXGetErrorString8(rc));
399 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",
400 (DWORD)temp_buffer,(DWORD)dsbo);
401 ref=IDirectSoundBuffer_Release(temp_buffer);
402 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
403 "should have 1\n",ref);
406 rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,
407 (LPVOID *)&temp_buffer);
408 ok(rc==DS_OK && temp_buffer!=NULL,
409 "IDirectSound3DBuffer_QueryInterface() failed: %s\n",
410 DXGetErrorString8(rc));
411 ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",
412 (DWORD)temp_buffer,(DWORD)dsbo);
413 ref=IDirectSoundBuffer_Release(temp_buffer);
414 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
415 "should have 1\n",ref);
418 /* FIXME: this works on windows */
419 ref=IDirectSoundBuffer_Release(dsbo);
420 ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
421 "should have 0\n",ref);
423 rc=IDirectSound3DBuffer_QueryInterface(buffer,
424 &IID_IDirectSoundBuffer,
426 ok(rc==DS_OK && dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
427 "failed: %s\n",DXGetErrorString8(rc));
430 /* DSOUND: Error: Invalid buffer */
431 rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
432 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
433 "failed: %s\n",DXGetErrorString8(rc));
435 ZeroMemory(&buffer_param, sizeof(buffer_param));
437 /* DSOUND: Error: Invalid buffer */
438 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
439 ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
440 "failed: %s\n",DXGetErrorString8(rc));
442 buffer_param.dwSize=sizeof(buffer_param);
443 rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
444 ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %s\n",
445 DXGetErrorString8(rc));
448 if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
450 rc=IDirectSoundBuffer_GetVolume(dsbo,&val);
451 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %s\n",
452 DXGetErrorString8(rc));
454 rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
455 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %s\n",
456 DXGetErrorString8(rc));
458 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
459 rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
460 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
461 "should have failed: %s\n",DXGetErrorString8(rc));
466 if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
468 rc=IDirectSoundBuffer_GetPan(dsbo,&val);
469 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %s\n",
470 DXGetErrorString8(rc));
472 rc=IDirectSoundBuffer_SetPan(dsbo,pan);
473 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %s\n",
474 DXGetErrorString8(rc));
476 /* DSOUND: Error: Buffer does not have CTRLPAN */
477 rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
478 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
479 "should have returned DSERR_CONTROLUNAVAIL, returned: %s\n",
480 DXGetErrorString8(rc));
484 state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
488 state.buffer_size=dsbcaps.dwBufferBytes;
489 state.played=state.written=state.offset=0;
490 buffer_refill(&state,state.buffer_size);
492 rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
493 ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %s\n",
494 DXGetErrorString8(rc));
496 rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
497 ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %s\n",
498 DXGetErrorString8(rc));
499 ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
500 "GetStatus: bad status: %lx\n",status);
503 ZeroMemory(&listener_param,sizeof(listener_param));
504 listener_param.dwSize=sizeof(listener_param);
505 rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
506 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
507 "failed: %s\n",DXGetErrorString8(rc));
510 listener_param.vPosition.x = -5.0;
511 listener_param.vVelocity.x = 10.0/duration;
513 rc=IDirectSound3DListener_SetAllParameters(listener,
516 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %s\n",
517 DXGetErrorString8(rc));
522 buffer_param.vPosition.x = 100.0;
523 buffer_param.vVelocity.x = -200.0/duration;
525 buffer_param.flMinDistance = 10;
526 rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
528 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %s\n",
529 DXGetErrorString8(rc));
532 start_time=GetTickCount();
533 while (buffer_service(&state)) {
534 WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
536 if (listener && move_listener) {
537 listener_param.vPosition.x = -5.0+10.0*(now-start_time)/
539 if (winetest_debug>2)
540 trace("listener position=%g\n",listener_param.vPosition.x);
541 rc=IDirectSound3DListener_SetPosition(listener,
542 listener_param.vPosition.x,listener_param.vPosition.y,
543 listener_param.vPosition.z,DS3D_IMMEDIATE);
545 "IDirectSound3dListener_SetPosition() failed: %s\n",
546 DXGetErrorString8(rc));
548 if (buffer3d && move_sound) {
549 buffer_param.vPosition.x = 100-200.0*(now-start_time)/
551 if (winetest_debug>2)
552 trace("sound position=%g\n",buffer_param.vPosition.x);
553 rc=IDirectSound3DBuffer_SetPosition(buffer,
554 buffer_param.vPosition.x,buffer_param.vPosition.y,
555 buffer_param.vPosition.z,DS3D_IMMEDIATE);
556 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %s\n",
557 DXGetErrorString8(rc));
560 /* Check the sound duration was within 10% of the expected value */
562 ok(fabs(1000*duration-now+start_time)<=100*duration,
563 "The sound played for %ld ms instead of %g ms\n",
564 now-start_time,1000*duration);
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));
575 ref=IDirectSound3DBuffer_Release(buffer);
576 ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
577 "should have 0\n",ref);
582 static HRESULT test_secondary(LPGUID lpGuid, int play,
583 int has_3d, int has_3dbuffer,
584 int has_listener, int has_duplicate,
585 int move_listener, int move_sound)
588 LPDIRECTSOUND dso=NULL;
589 LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
590 LPDIRECTSOUND3DLISTENER listener=NULL;
591 DSBUFFERDESC bufdesc;
595 /* Create the DirectSound object */
596 rc=DirectSoundCreate(lpGuid,&dso,NULL);
597 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
601 /* We must call SetCooperativeLevel before creating primary buffer */
602 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
603 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
604 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
605 DXGetErrorString8(rc));
609 ZeroMemory(&bufdesc, sizeof(bufdesc));
610 bufdesc.dwSize=sizeof(bufdesc);
611 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
613 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
615 bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
616 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
617 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
618 "to create a %sprimary buffer: %s\n",has_3d?"3D ":"",
619 DXGetErrorString8(rc));
621 if (rc==DS_OK && primary!=NULL) {
623 rc=IDirectSoundBuffer_QueryInterface(primary,
624 &IID_IDirectSound3DListener,(void **)&listener);
625 ok(rc==DS_OK && listener!=NULL,
626 "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
627 "listener: %s\n",DXGetErrorString8(rc));
628 ref=IDirectSoundBuffer_Release(primary);
629 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
630 "should have 0\n",ref);
631 if (rc==DS_OK && listener!=NULL) {
632 DS3DLISTENER listener_param;
633 ZeroMemory(&listener_param,sizeof(listener_param));
634 /* DSOUND: Error: Invalid buffer */
635 rc=IDirectSound3DListener_GetAllParameters(listener,0);
636 ok(rc==DSERR_INVALIDPARAM,
637 "IDirectSound3dListener_GetAllParameters() failed: %s\n",
638 DXGetErrorString8(rc));
640 /* DSOUND: Error: Invalid buffer */
641 rc=IDirectSound3DListener_GetAllParameters(listener,
643 ok(rc==DSERR_INVALIDPARAM,
644 "IDirectSound3dListener_GetAllParameters() failed: %s\n",
645 DXGetErrorString8(rc));
647 listener_param.dwSize=sizeof(listener_param);
648 rc=IDirectSound3DListener_GetAllParameters(listener,
650 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
651 "failed: %s\n",DXGetErrorString8(rc));
657 init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
659 ZeroMemory(&bufdesc, sizeof(bufdesc));
660 bufdesc.dwSize=sizeof(bufdesc);
661 bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
663 bufdesc.dwFlags|=DSBCAPS_CTRL3D;
666 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
667 bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
668 bufdesc.lpwfxFormat=&wfx;
669 if (winetest_interactive) {
670 trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
671 has_3dbuffer?"3D ":"",
672 has_duplicate?"duplicated ":"",
673 listener!=NULL||move_sound?"with ":"",
674 move_listener?"moving ":"",
675 listener!=NULL?"listener ":"",
676 listener&&move_sound?"and moving sound ":move_sound?
678 wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
680 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
681 ok(rc==DS_OK && secondary!=NULL,"IDirectSound_CreateSoundBuffer() "
682 "failed to create a 3D secondary buffer: %s\n",
683 DXGetErrorString8(rc));
684 if (rc==DS_OK && secondary!=NULL) {
690 /* Check the initial secondary buffer's volume and pan */
691 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
692 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: "
693 "%s\n",DXGetErrorString8(rc));
694 ok(vol==0,"wrong volume for a new secondary buffer: %ld\n",vol);
695 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
696 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: "
697 "%s\n",DXGetErrorString8(rc));
698 ok(pan==0,"wrong pan for a new secondary buffer: %ld\n",pan);
700 /* Check that changing the secondary buffer's volume and pan
701 * does not impact the primary buffer's volume and pan
703 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
704 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: "
705 "%s\n",DXGetErrorString8(rc));
706 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
707 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %s\n",
708 DXGetErrorString8(rc));
710 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
711 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
712 "%s\n",DXGetErrorString8(rc));
713 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
714 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
715 "%s\n",DXGetErrorString8(rc));
716 ok(vol==-1000,"secondary: wrong volume %ld instead of -1000\n",
718 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
719 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
720 "%s\n",DXGetErrorString8(rc));
721 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
722 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
723 "%s\n",DXGetErrorString8(rc));
724 ok(pan==-1000,"secondary: wrong pan %ld instead of -1000\n",
727 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
728 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: "
729 "%s\n",DXGetErrorString8(rc));
730 ok(vol==refvol,"The primary volume changed from %ld to %ld\n",
732 rc=IDirectSoundBuffer_GetPan(primary,&pan);
733 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %s\n",
734 DXGetErrorString8(rc));
735 ok(pan==refpan,"The primary pan changed from %ld to %ld\n",
738 rc=IDirectSoundBuffer_SetVolume(secondary,0);
739 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: "
740 "%s\n",DXGetErrorString8(rc));
741 rc=IDirectSoundBuffer_SetPan(secondary,0);
742 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: "
743 "%s\n",DXGetErrorString8(rc));
746 LPDIRECTSOUNDBUFFER duplicated=NULL;
748 /* DSOUND: Error: Invalid source buffer */
749 rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
750 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer() "
751 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
752 DXGetErrorString8(rc));
754 /* DSOUND: Error: Invalid dest buffer */
755 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
756 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer() "
757 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
758 DXGetErrorString8(rc));
760 /* DSOUND: Error: Invalid source buffer */
761 rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
762 ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer() "
763 "should have returned DSERR_INVALIDPARAM, returned: %s\n",
764 DXGetErrorString8(rc));
767 rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
768 ok(rc==DS_OK && duplicated!=NULL,
769 "IDirectSound_DuplicateSoundBuffer() failed to duplicate "
770 "a secondary buffer: %s\n",DXGetErrorString8(rc));
772 if (rc==DS_OK && duplicated!=NULL) {
773 ref=IDirectSoundBuffer_Release(secondary);
774 ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
775 "references, should have 0\n",ref);
776 secondary=duplicated;
780 if (rc==DS_OK && secondary!=NULL) {
782 duration=(move_listener || move_sound?4.0:1.0);
783 test_buffer(dso,secondary,0,FALSE,0,FALSE,0,
784 winetest_interactive,duration,has_3dbuffer,
785 listener,move_listener,move_sound);
786 ref=IDirectSoundBuffer_Release(secondary);
787 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
788 "should have 0\n",has_duplicate?"duplicated":"secondary",ref);
793 ref=IDirectSound3DListener_Release(listener);
794 ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
795 "references, should have 0\n",ref);
797 ref=IDirectSoundBuffer_Release(primary);
798 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
799 "should have 0\n",ref);
802 /* Set the CooperativeLevel back to normal */
803 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
804 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
805 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
806 DXGetErrorString8(rc));
809 ref=IDirectSound_Release(dso);
810 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
812 return DSERR_GENERIC;
817 static HRESULT test_primary(LPGUID lpGuid)
820 LPDIRECTSOUND dso=NULL;
821 LPDIRECTSOUNDBUFFER primary=NULL;
822 DSBUFFERDESC bufdesc;
826 /* Create the DirectSound object */
827 rc=DirectSoundCreate(lpGuid,&dso,NULL);
828 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
832 /* Get the device capabilities */
833 ZeroMemory(&dscaps, sizeof(dscaps));
834 dscaps.dwSize=sizeof(dscaps);
835 rc=IDirectSound_GetCaps(dso,&dscaps);
836 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
840 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
841 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
842 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
843 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
844 DXGetErrorString8(rc));
848 /* Testing the primary buffer */
850 ZeroMemory(&bufdesc, sizeof(bufdesc));
851 bufdesc.dwSize=sizeof(bufdesc);
852 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
853 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
854 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
855 "to create a primary buffer: %s\n",DXGetErrorString8(rc));
856 if (rc==DS_OK && primary!=NULL) {
857 test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive &&
858 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
859 if (winetest_interactive) {
862 volume = DSBVOLUME_MAX;
863 for (i = 0; i < 6; i++) {
864 test_buffer(dso,primary,1,TRUE,volume,TRUE,0,
865 winetest_interactive &&
866 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
868 volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
872 for (i = 0; i < 7; i++) {
873 test_buffer(dso,primary,1,TRUE,0,TRUE,pan,
874 winetest_interactive &&
875 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
876 pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
879 ref=IDirectSoundBuffer_Release(primary);
880 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
881 "should have 0\n",ref);
884 /* Set the CooperativeLevel back to normal */
885 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
886 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
887 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
888 DXGetErrorString8(rc));
891 ref=IDirectSound_Release(dso);
892 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
894 return DSERR_GENERIC;
899 static HRESULT test_primary_3d(LPGUID lpGuid)
902 LPDIRECTSOUND dso=NULL;
903 LPDIRECTSOUNDBUFFER primary=NULL;
904 DSBUFFERDESC bufdesc;
908 /* Create the DirectSound object */
909 rc=DirectSoundCreate(lpGuid,&dso,NULL);
910 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
914 /* Get the device capabilities */
915 ZeroMemory(&dscaps, sizeof(dscaps));
916 dscaps.dwSize=sizeof(dscaps);
917 rc=IDirectSound_GetCaps(dso,&dscaps);
918 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
922 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
923 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
924 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
925 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
926 DXGetErrorString8(rc));
931 ZeroMemory(&bufdesc, sizeof(bufdesc));
932 bufdesc.dwSize=sizeof(bufdesc);
933 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
934 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
935 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
936 "to create a primary buffer: %s\n",DXGetErrorString8(rc));
937 if (rc==DS_OK && primary!=NULL) {
938 ref=IDirectSoundBuffer_Release(primary);
939 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
940 "should have 0\n",ref);
942 ZeroMemory(&bufdesc, sizeof(bufdesc));
943 bufdesc.dwSize=sizeof(bufdesc);
944 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
945 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
946 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() "
947 "failed to create a 3D primary buffer: %s\n",DXGetErrorString8(rc));
948 if (rc==DS_OK && primary!=NULL) {
949 test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive &&
950 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
951 ref=IDirectSoundBuffer_Release(primary);
952 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
953 "should have 0\n",ref);
956 /* Set the CooperativeLevel back to normal */
957 /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
958 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
959 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
960 DXGetErrorString8(rc));
963 ref=IDirectSound_Release(dso);
964 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
966 return DSERR_GENERIC;
971 static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
974 LPDIRECTSOUND dso=NULL;
975 LPDIRECTSOUNDBUFFER primary=NULL;
976 DSBUFFERDESC bufdesc;
980 /* Create the DirectSound object */
981 rc=DirectSoundCreate(lpGuid,&dso,NULL);
982 ok(rc==DS_OK,"DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc));
986 /* Get the device capabilities */
987 ZeroMemory(&dscaps, sizeof(dscaps));
988 dscaps.dwSize=sizeof(dscaps);
989 rc=IDirectSound_GetCaps(dso,&dscaps);
990 ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc));
994 /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
995 /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
996 rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
997 ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n",
998 DXGetErrorString8(rc));
1002 ZeroMemory(&bufdesc, sizeof(bufdesc));
1003 bufdesc.dwSize=sizeof(bufdesc);
1004 bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
1005 rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
1006 ok(rc==DS_OK && primary!=NULL,"IDirectSound_CreateSoundBuffer() failed "
1007 "to create a 3D primary buffer: %s\n",DXGetErrorString8(rc));
1008 if (rc==DS_OK && primary!=NULL) {
1009 LPDIRECTSOUND3DLISTENER listener=NULL;
1010 rc=IDirectSoundBuffer_QueryInterface(primary,
1011 &IID_IDirectSound3DListener,(void **)&listener);
1012 ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface() "
1013 "failed to get a 3D listener: %s\n",DXGetErrorString8(rc));
1014 if (rc==DS_OK && listener!=NULL) {
1015 LPDIRECTSOUNDBUFFER temp_buffer=NULL;
1017 /* Checking the COM interface */
1018 rc=IDirectSoundBuffer_QueryInterface(primary,
1019 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1020 ok(rc==DS_OK && temp_buffer!=NULL,
1021 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
1022 DXGetErrorString8(rc));
1023 ok(temp_buffer==primary,
1024 "COM interface broken: 0x%08lx != 0x%08lx\n",
1025 (DWORD)temp_buffer,(DWORD)primary);
1026 if (rc==DS_OK && temp_buffer!=NULL) {
1027 ref=IDirectSoundBuffer_Release(temp_buffer);
1028 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1029 "should have 1\n",ref);
1032 rc=IDirectSound3DListener_QueryInterface(listener,
1033 &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
1034 ok(rc==DS_OK && temp_buffer!=NULL,
1035 "IDirectSoundBuffer_QueryInterface() failed: %s\n",
1036 DXGetErrorString8(rc));
1037 ok(temp_buffer==primary,
1038 "COM interface broken: 0x%08lx != 0x%08lx\n",
1039 (DWORD)temp_buffer,(DWORD)primary);
1040 ref=IDirectSoundBuffer_Release(temp_buffer);
1041 ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
1042 "should have 1\n",ref);
1044 /* Testing the buffer */
1045 test_buffer(dso,primary,1,FALSE,0,FALSE,0,
1046 winetest_interactive &&
1047 !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,
1051 /* Testing the reference counting */
1052 ref=IDirectSound3DListener_Release(listener);
1053 ok(ref==0,"IDirectSound3DListener_Release() listener has %d "
1054 "references, should have 0\n",ref);
1057 /* Testing the reference counting */
1058 ref=IDirectSoundBuffer_Release(primary);
1059 ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
1060 "should have 0\n",ref);
1064 ref=IDirectSound_Release(dso);
1065 ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref);
1067 return DSERR_GENERIC;
1072 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
1073 LPCSTR lpcstrModule, LPVOID lpContext)
1075 trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
1077 trace(" Testing the primary buffer\n");
1078 test_primary(lpGuid);
1080 trace(" Testing 3D primary buffer\n");
1081 test_primary_3d(lpGuid);
1083 trace(" Testing 3D primary buffer with listener\n");
1084 test_primary_3d_with_listener(lpGuid);
1086 /* Testing secondary buffers */
1087 test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
1088 test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
1090 /* Testing 3D secondary buffers */
1091 test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
1092 test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
1093 test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
1094 test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
1095 test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
1096 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
1097 test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
1098 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
1099 test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
1100 test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
1105 static void ds3d_tests()
1108 rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
1109 ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %s\n",DXGetErrorString8(rc));