Split the dsound test

Francois Gouget fgouget at codeweavers.com
Sun May 23 04:18:27 CDT 2004


To play the current main DirectSound test in interactive mode, do:

WINETEST_INTERACTVE=1 ../../../tools/runtest -P wine -M dsound.dll -T 
../../.. -p dsound_test.exe.so dsound.c

You will notice the following problems:
  * the test takes awfully long (>6 minutes here). It loops through the 
known formats and for each of them it plays, in turn, the regular test, 
a test through a duplicated buffer, with a listener, etc.
  * as a result of the above, a user listening to the test does not know 
what to expect, which makes it hard to know whether the sound was played 
correctly.

So this patch splits the 'dsound' test into two parts:
  * the first one, 'dsound', tests each supported sound format and plays 
a single test tone for each. Also this test does not touch the volume 
control to see whether DirectSound modifies the volume on its own.
  * the second one, 'ds3d', tests the volume control and all the 3D 
sound aspects. It does not repeat these tests at each supported sound 
format as this would be redundant.

So users running the 'dsound' test get a simple to understand setries of 
test tones. The ds3d test is more complex but it is now much shorter.


Changelog:

  * dlls/dsound/tests/Makefile.in
    dlls/dsound/tests/capture.c
    dlls/dsound/tests/dsound.c
    dlls/dsound/tests/ds3d.c
    dlls/dsound/tests/dsound_test.h

    Split the 'dsound' test into two parts:
    - the sound format test. Plays a 5 second reference tone to help 
debug issues with the tone duration and help detect stutter issues. 
Prints explanations describing the sound format interactive test. Then 
plays a 1 second test tone for each supported sound format.
    - the 3D sound tests. Performs the volume, panning, moving listener 
tests, etc.


-- 
Francois Gouget
fgouget at codeweavers.com

-------------- next part --------------
Index: dlls/dsound/tests/Makefile.in
===================================================================
RCS file: /var/cvs/wine/dlls/dsound/tests/Makefile.in,v
retrieving revision 1.6
diff -u -r1.6 Makefile.in
--- a/dlls/dsound/tests/Makefile.in	6 Apr 2004 20:08:54 -0000	1.6
+++ b/dlls/dsound/tests/Makefile.in	19 May 2004 14:45:20 -0000
@@ -4,7 +4,8 @@
 
 CTESTS = \
 	capture.c \
+	ds3d.c \
 	dsound.c \
 	propset.c
 
Index: dlls/dsound/tests/capture.c
===================================================================
RCS file: /var/cvs/wine/dlls/dsound/tests/capture.c,v
retrieving revision 1.4
diff -u -r1.4 capture.c
--- a/dlls/dsound/tests/capture.c	6 Apr 2004 20:08:54 -0000	1.4
+++ b/dlls/dsound/tests/capture.c	19 May 2004 12:08:24 -0000
@@ -34,48 +34,10 @@
 #include "mmreg.h"
 #include "dxerr9.h"
 
-static const unsigned int formats[][3]={
-    { 8000,  8, 1},
-    { 8000,  8, 2},
-    { 8000, 16, 1},
-    { 8000, 16, 2},
-    {11025,  8, 1},
-    {11025,  8, 2},
-    {11025, 16, 1},
-    {11025, 16, 2},
-    {22050,  8, 1},
-    {22050,  8, 2},
-    {22050, 16, 1},
-    {22050, 16, 2},
-    {44100,  8, 1},
-    {44100,  8, 2},
-    {44100, 16, 1},
-    {44100, 16, 2},
-    {48000,  8, 1},
-    {48000,  8, 2},
-    {48000, 16, 1},
-    {48000, 16, 2},
-    {96000,  8, 1},
-    {96000,  8, 2},
-    {96000, 16, 1},
-    {96000, 16, 2}
-};
-#define NB_FORMATS (sizeof(formats)/sizeof(*formats))
+#include "dsound_test.h"
 
 #define NOTIFICATIONS    5
 
-static void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels)
-{
-    wfx->wFormatTag=format;
-    wfx->nChannels=channels;
-    wfx->wBitsPerSample=depth;
-    wfx->nSamplesPerSec=rate;
-    wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
-    if (wfx->nBlockAlign==0)	/* align compressed formats to byte boundry */
-	wfx->nBlockAlign=1;
-    wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nChannels*wfx->wBitsPerSample/8;
-    wfx->cbSize=0;
-}
 
 static char * format_string(WAVEFORMATEX* wfx)
 {
Index: dlls/dsound/tests/dsound.c
===================================================================
RCS file: /var/cvs/wine/dlls/dsound/tests/dsound.c,v
retrieving revision 1.20
diff -u -r1.20 dsound.c
--- a/dlls/dsound/tests/dsound.c	20 Jan 2004 21:49:48 -0000	1.20
+++ b/dlls/dsound/tests/dsound.c	20 May 2004 08:59:34 -0000
@@ -1,7 +1,14 @@
 /*
- * Unit tests for dsound functions
+ * Tests basic sound playback in DirectSound.
+ * In particular we test each standard Windows sound format to make sure
+ * we handle the sound card/driver quirks correctly.
  *
- * Copyright (c) 2002 Francois Gouget
+ * Part of this test involves playing test tones. But this only makes
+ * sense if someone is going to carefully listen to it, and would only
+ * bother everyone else.
+ * So this is only done if the test is being run in interactive mode.
+ *
+ * Copyright (c) 2002-2004 Francois Gouget
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,666 +37,14 @@
 #include "wingdi.h"
 #include "dsound.h"
 
-static const unsigned int formats[][3]={
-    { 8000,  8, 1},
-    { 8000,  8, 2},
-    { 8000, 16, 1},
-    { 8000, 16, 2},
-    {11025,  8, 1},
-    {11025,  8, 2},
-    {11025, 16, 1},
-    {11025, 16, 2},
-    {22050,  8, 1},
-    {22050,  8, 2},
-    {22050, 16, 1},
-    {22050, 16, 2},
-    {44100,  8, 1},
-    {44100,  8, 2},
-    {44100, 16, 1},
-    {44100, 16, 2},
-    {48000,  8, 1},
-    {48000,  8, 2},
-    {48000, 16, 1},
-    {48000, 16, 2},
-    {96000,  8, 1},
-    {96000,  8, 2},
-    {96000, 16, 1},
-    {96000, 16, 2}
-};
-#define NB_FORMATS (sizeof(formats)/sizeof(*formats))
-
-/* The time slice determines how often we will service the buffer and the
- * buffer will be four time slices long
- */
-#define TIME_SLICE    100
-#define BUFFER_LEN    (4*TIME_SLICE)
-#define TONE_DURATION (6*TIME_SLICE)
-
-/* This test can play a test tone. But this only makes sense if someone
- * is going to carefully listen to it, and would only bother everyone else.
- * So this is only done if the test is being run in interactive mode.
- */
-
-#define PI 3.14159265358979323846
-static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
-{
-    int i;
-    int nb_samples;
-    char* buf;
-    char* b;
-
-    nb_samples=(int)(duration*wfx->nSamplesPerSec);
-    *size=nb_samples*wfx->nBlockAlign;
-    b=buf=malloc(*size);
-    for (i=0;i<nb_samples;i++) {
-	double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
-	if (wfx->wBitsPerSample==8) {
-	    unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
-	    *b++=sample;
-	    if (wfx->nChannels==2)
-	       *b++=sample;
-	} else {
-	    signed short sample=(signed short)((double)32767.5*y-0.5);
-	    b[0]=sample & 0xff;
-	    b[1]=sample >> 8;
-	    b+=2;
-	    if (wfx->nChannels==2) {
-		b[0]=sample & 0xff;
-		b[1]=sample >> 8;
-		b+=2;
-	    }
-	}
-    }
-    return buf;
-}
-
-static HWND get_hwnd()
-{
-    HWND hwnd=GetForegroundWindow();
-    if (!hwnd)
-	hwnd=GetDesktopWindow();
-    return hwnd;
-}
-
-static void init_format(WAVEFORMATEX* wfx, int rate, int depth, int channels)
-{
-    wfx->wFormatTag=WAVE_FORMAT_PCM;
-    wfx->nChannels=channels;
-    wfx->wBitsPerSample=depth;
-    wfx->nSamplesPerSec=rate;
-    wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
-    wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
-    wfx->cbSize=0;
-}
-
-typedef struct {
-    char* wave;
-    DWORD wave_len;
-
-    LPDIRECTSOUNDBUFFER dsbo;
-    LPWAVEFORMATEX wfx;
-    DWORD buffer_size;
-    DWORD written;
-    DWORD offset;
-
-    DWORD last_pos;
-} play_state_t;
-
-static int buffer_refill(play_state_t* state, DWORD size)
-{
-    LPVOID ptr1,ptr2;
-    DWORD len1,len2;
-    HRESULT rc;
-
-    if (size>state->wave_len-state->written)
-	size=state->wave_len-state->written;
-
-    rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
-			       &ptr1,&len1,&ptr2,&len2,0);
-    ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return -1;
-
-    memcpy(ptr1,state->wave+state->written,len1);
-    state->written+=len1;
-    if (ptr2!=NULL) {
-	memcpy(ptr2,state->wave+state->written,len2);
-	state->written+=len2;
-    }
-    state->offset=state->written % state->buffer_size;
-    rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
-    ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return -1;
-    return size;
-}
-
-static int buffer_silence(play_state_t* state, DWORD size)
-{
-    LPVOID ptr1,ptr2;
-    DWORD len1,len2;
-    HRESULT rc;
-    BYTE s;
-
-    rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
-			       &ptr1,&len1,&ptr2,&len2,0);
-    ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return -1;
-
-    s=(state->wfx->wBitsPerSample==8?0x80:0);
-    memset(ptr1,s,len1);
-    if (ptr2!=NULL) {
-	memset(ptr2,s,len2);
-    }
-    state->offset=(state->offset+size) % state->buffer_size;
-    rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
-    ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return -1;
-    return size;
-}
-
-static int buffer_service(play_state_t* state)
-{
-    DWORD play_pos,write_pos,buf_free;
-    HRESULT rc;
-
-    rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
-    ok(rc==DS_OK,"GetCurrentPosition: %lx\n",rc);
-    if (rc!=DS_OK) {
-	goto STOP;
-    }
-
-    /* Refill the buffer */
-    if (state->offset<=play_pos) {
-	buf_free=play_pos-state->offset;
-    } else {
-	buf_free=state->buffer_size-state->offset+play_pos;
-    }
-    if (winetest_debug > 1)
-	trace("buf pos=%ld free=%ld written=%ld / %ld\n",
-	      play_pos,buf_free,state->written,state->wave_len);
-    if (buf_free==0)
-	return 1;
-
-    if (state->written<state->wave_len) {
-	int w=buffer_refill(state,buf_free);
-	if (w==-1)
-	    goto STOP;
-	buf_free-=w;
-	if (state->written==state->wave_len) {
-	    state->last_pos=(state->offset<play_pos)?play_pos:0;
-	    if (winetest_debug > 1)
-		trace("last sound byte at %ld\n",
-		      (state->written % state->buffer_size));
-	}
-    } else {
-	if (state->last_pos!=0 && play_pos<state->last_pos) {
-	    /* We wrapped around the end of the buffer */
-	    state->last_pos=0;
-	}
-	if (state->last_pos==0 &&
-	    play_pos>(state->written % state->buffer_size)) {
-	    /* Now everything has been played */
-	    goto STOP;
-	}
-    }
-
-    if (buf_free>0) {
-	/* Fill with silence */
-	if (winetest_debug > 1)
-	    trace("writing %ld bytes of silence\n",buf_free);
-	if (buffer_silence(state,buf_free)==-1)
-	    goto STOP;
-    }
-    return 1;
-
-STOP:
-    if (winetest_debug > 1)
-	trace("stopping playback\n");
-    rc=IDirectSoundBuffer_Stop(state->dsbo);
-    ok(rc==DS_OK,"Stop failed: rc=%ld\n",rc);
-    return 0;
-}
-
-static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
-			int is_primary, BOOL set_volume, LONG volume,
-			BOOL set_pan, LONG pan, int play, int buffer3d, 
-			LPDIRECTSOUND3DLISTENER listener, 
-			int move_listener, int move_sound)
-{
-    HRESULT rc;
-    DSBCAPS dsbcaps;
-    WAVEFORMATEX wfx,wfx2;
-    DWORD size,status,freq;
-    int ref;
-
-    /* DSOUND: Error: Invalid caps pointer */
-    rc=IDirectSoundBuffer_GetCaps(dsbo,0);
-    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
-
-    ZeroMemory(&dsbcaps, sizeof(dsbcaps));
-
-    /* DSOUND: Error: Invalid caps pointer */
-    rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
-    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
-
-    dsbcaps.dwSize=sizeof(dsbcaps);
-    rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
-    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	trace("    Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
-	      dsbcaps.dwBufferBytes);
-    }
-
-    /* Query the format size. Note that it may not match sizeof(wfx) */
-    size=0;
-    rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
-    ok(rc==DS_OK && size!=0,
-       "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
-       rc,size);
-
-    rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
-    ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
-	      wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
-	      wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
-    }
-
-    /* DSOUND: Error: Invalid frequency buffer */
-    rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
-    ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
-	
-    /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
-    rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
-    ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
-		(rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
-	"GetFrequency failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	ok(freq==wfx.nSamplesPerSec,
-	   "The frequency returned by GetFrequency %ld does not match the format %ld\n",
-	   freq,wfx.nSamplesPerSec);
-    }
-
-    /* DSOUND: Error: Invalid status pointer */
-    rc=IDirectSoundBuffer_GetStatus(dsbo,0);
-    ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
-
-    rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
-    ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	trace("    status=0x%04lx\n",status);
-    }
-
-    if (is_primary) {
-	/* We must call SetCooperativeLevel to be allowed to call SetFormat */
-	/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
-	rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
-	ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-	if(rc!=DS_OK)
-	    return;
-
-	/* DSOUND: Error: Invalid format pointer */
-	rc=IDirectSoundBuffer_SetFormat(dsbo,0);
-	ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
-
-	init_format(&wfx2,11025,16,2);
-	rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
-	ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
-
-	/* There is no garantee that SetFormat will actually change the
-	 * format to what we asked for. It depends on what the soundcard
-	 * supports. So we must re-query the format.
-	 */
-	rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
-	ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
-	if (rc==DS_OK) {
-	    trace("    tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
-		  wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
-		  wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
-	}
-
-	/* Set the CooperativeLevel back to normal */
-	/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
-	rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
-	ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-    }
-
-    if (play) {
-	play_state_t state;
-
-	LPDIRECTSOUND3DBUFFER buffer=NULL;
-	DS3DBUFFER buffer_param;
-	DS3DLISTENER listener_param;
-	trace("    Playing 440Hz LA at %ldx%dx%d\n",
-	      wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
-
-	if (is_primary) {
-	    /* We must call SetCooperativeLevel to be allowed to call Lock */
-	    /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
-	    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
-	    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-	    if (rc!=DS_OK)
-		return;
-	}
-	if (buffer3d) {
-	    LPDIRECTSOUNDBUFFER temp_buffer;
-
-	    rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
-	    ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
-	    if(rc!=DS_OK)
-		return;
-
-	    /* check the COM interface */
-	    rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
-	    ok(rc==DS_OK&&temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
-	    ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
-	    ref=IDirectSoundBuffer_Release(temp_buffer);
-	    ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
-
-	    temp_buffer=NULL;
-	    rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
-	    ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
-	    ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
-	    ref=IDirectSoundBuffer_Release(temp_buffer);
-	    ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
-
-#if 0	    /* FIXME: this works on windows */
-	    ref=IDirectSoundBuffer_Release(dsbo);
-	    ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
-
-	    rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
-	    ok(rc==DS_OK&&dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
-#endif
+#include "dsound_test.h"
 
-	    /* DSOUND: Error: Invalid buffer */
-	    rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
-	    ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
-
-	    ZeroMemory(&buffer_param, sizeof(buffer_param));
-
-	    /* DSOUND: Error: Invalid buffer */
-	    rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
-	    ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
-
-	    buffer_param.dwSize=sizeof(buffer_param);
-	    rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
-	    ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
-	}
-	if (set_volume) {
-	    rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
-	    ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
-
-	    rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
-	    trace("    volume=%ld\n",volume);
-	} else {
-	    if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
-		rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
-		ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
-
-		rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
-		ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
-
-		rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
-		trace("    volume=%ld\n",volume);
-	    } else {
-		/* DSOUND: Error: Buffer does not have CTRLVOLUME */
-		rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
-		ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
-	    }
-	}
-
-	if (set_pan) {
-	    rc=IDirectSoundBuffer_SetPan(dsbo,pan);
-	    ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
-
-	    rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
-	    trace("    pan=%ld\n",pan);
-	} else {
-	    if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
-		rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
-		ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
-
-		rc=IDirectSoundBuffer_SetPan(dsbo,0);
-		ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
-
-		rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
-		trace("    pan=%ld\n",pan);
-	    } else {
-		/* DSOUND: Error: Buffer does not have CTRLPAN */
-		rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
-		ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
-	    }
-	}
-
-	state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
-
-	state.dsbo=dsbo;
-	state.wfx=&wfx;
-	state.buffer_size=dsbcaps.dwBufferBytes;
-	state.written=state.offset=0;
-	buffer_refill(&state,state.buffer_size);
-
-	rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
-	ok(rc==DS_OK,"Play: 0x%lx\n",rc);
-
-	rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
-	ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
-	ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
-	   "GetStatus: bad status: %lx\n",status);
-
-	if (listener) {
-	    ZeroMemory(&listener_param,sizeof(listener_param));
-	    listener_param.dwSize=sizeof(listener_param);
-	    rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
-	    ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
-	    if (move_listener)
-		listener_param.vPosition.x = -5.0;
-	    else
-		listener_param.vPosition.x = 0.0;
-	    listener_param.vPosition.y = 0.0;
-	    listener_param.vPosition.z = 0.0;
-	    rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
-	    ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
-	}
-	if (buffer3d) {
-	    if (move_sound)
-		buffer_param.vPosition.x = 5.0;
-	    else
-		buffer_param.vPosition.x = 0.0;
-	    buffer_param.vPosition.y = 0.0;
-	    buffer_param.vPosition.z = 0.0;
-	    rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
-	    ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
-	}
-
-	while (buffer_service(&state)) {
-	    WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
-	    if (listener&&move_listener) {
-		listener_param.vPosition.x += 0.5;
-		rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
-		ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
-	    }
-	    if (buffer3d&&move_sound) {
-		buffer_param.vPosition.x -= 0.5;
-		rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
-		ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
-	    }
-	}
-
-	if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
-	    rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
-	    ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
-	}
-
-	free(state.wave);
- 	if (is_primary) {
-	    /* Set the CooperativeLevel back to normal */
-	    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
-	    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
-	    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-	}
-	if (buffer3d) {
-	    ref=IDirectSound3DBuffer_Release(buffer);
-	    ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref); 
-	}
-    }
-}
-
-static HRESULT test_secondary(LPGUID lpGuid, int play, 
-			      int has_3d, int has_3dbuffer, 
-			      int has_listener, int has_duplicate, 
-			      int move_listener, int move_sound)
-{
-    HRESULT rc;
-    LPDIRECTSOUND dso=NULL;
-    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
-    LPDIRECTSOUND3DLISTENER listener=NULL;
-    DSBUFFERDESC bufdesc;
-    DSCAPS dscaps;
-    WAVEFORMATEX wfx;
-    int f,ref;
-
-    /* Create the DirectSound object */
-    rc=DirectSoundCreate(lpGuid,&dso,NULL);
-    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return rc;
-
-    /* Get the device capabilities */
-    ZeroMemory(&dscaps, sizeof(dscaps));
-    dscaps.dwSize=sizeof(dscaps);
-    rc=IDirectSound_GetCaps(dso,&dscaps);
-    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-        goto EXIT;
-
-	/* We must call SetCooperativeLevel before creating primary buffer */
-	/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
-	rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
-	ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-	if(rc!=DS_OK)
-	    goto EXIT;
-
-    ZeroMemory(&bufdesc, sizeof(bufdesc));
-    bufdesc.dwSize=sizeof(bufdesc);
-    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
-    if (has_3d)
-    	bufdesc.dwFlags|=DSBCAPS_CTRL3D;
-	else
-		bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
-    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
-    ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
-    if (rc==DS_OK&&primary!=NULL) {
-	if (has_listener) {
-	    rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
-	    ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
-	    ref=IDirectSoundBuffer_Release(primary);
-	    ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
-	    if(rc==DS_OK&&listener!=NULL) {
-		DS3DLISTENER listener_param;
-		ZeroMemory(&listener_param,sizeof(listener_param));
-		/* DSOUND: Error: Invalid buffer */
-		rc=IDirectSound3DListener_GetAllParameters(listener,0);
-		ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
-
-		/* DSOUND: Error: Invalid buffer */
-		rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
-		ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
-
-		listener_param.dwSize=sizeof(listener_param);
-		rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
-		ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
-	    } else
-		goto EXIT;
-	} 
-
-	for (f=0;f<NB_FORMATS;f++) {
-	    init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
-	    secondary=NULL;
-	    ZeroMemory(&bufdesc, sizeof(bufdesc));
-	    bufdesc.dwSize=sizeof(bufdesc);
-	    bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
-	    if (has_3d)
-	        bufdesc.dwFlags|=DSBCAPS_CTRL3D;
-		else
-			bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
-	    bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
-	    bufdesc.lpwfxFormat=&wfx;
-	    trace("  Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
-		has_3dbuffer?"3D ":"",
-		has_duplicate?"duplicated ":"",
-		listener!=NULL||move_sound?"with ":"",
-		move_listener?"moving ":"",
-		listener!=NULL?"listener ":"",
-		listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
-	    wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
-	    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
-	    ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
-	    if (rc==DS_OK&&secondary!=NULL) {
-		if (has_duplicate) {
-    		    LPDIRECTSOUNDBUFFER duplicated=NULL;
-
-		    /* DSOUND: Error: Invalid source buffer */
-		    rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
-		    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
-
-		    /* DSOUND: Error: Invalid dest buffer */
-		    rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
-		    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
-
-		    /* DSOUND: Error: Invalid source buffer */
-		    rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
-		    ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
-
-		    duplicated=NULL;
-		    rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
-		    ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
-
-		    if (rc==DS_OK&&duplicated!=NULL) {
-			ref=IDirectSoundBuffer_Release(secondary);
-			ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref); 
-			secondary=duplicated;
-		    } 
-		}
-
-		if (rc==DS_OK&&secondary!=NULL) {
-		    test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
-		    ref=IDirectSoundBuffer_Release(secondary);
-		    ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
-		}
-	    }
-	}
-	if (has_listener) {
-	    ref=IDirectSound3DListener_Release(listener);
-	    ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
-	} else {
-	    ref=IDirectSoundBuffer_Release(primary);
-	    ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
-	}
-    }
-	/* Set the CooperativeLevel back to normal */
-	/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
-	rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
-	ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
-
-EXIT:
-    ref=IDirectSound_Release(dso);
-    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
-    if (ref!=0)
-	return DSERR_GENERIC;
-
-    return rc;
-}
 
 static HRESULT test_dsound(LPGUID lpGuid)
 {
     HRESULT rc;
     LPDIRECTSOUND dso=NULL;
     DSCAPS dscaps;
-    DWORD speaker_config, new_speaker_config;
     int ref;
 
     /* DSOUND: Error: Invalid interface buffer */
@@ -700,7 +55,7 @@
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
     if (rc!=DS_OK)
-	return rc;
+        return rc;
 
     /* DSOUND: Error: Invalid caps buffer */
     rc=IDirectSound_GetCaps(dso,0);
@@ -718,61 +73,42 @@
     rc=IDirectSound_GetCaps(dso,&dscaps);
     ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
     if (rc==DS_OK) {
-	trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
-	      dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
-	      dscaps.dwMaxSecondarySampleRate);
-    }
-
-    rc=IDirectSound_GetSpeakerConfig(dso,0);
-    ok(rc==DSERR_INVALIDPARAM,"GetSpeakerConfig should have failed: 0x%lx\n",rc);
-
-    rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
-    ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	trace("  DirectSound SpeakerConfig: 0x%08lx\n", speaker_config);
-    }
- 
-    speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,DSSPEAKER_GEOMETRY_WIDE);
-    rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
-    ok(rc==DS_OK,"SetSpeakerConfig failed: 0x%lx\n",rc);
-    if (rc==DS_OK) {
-	rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
-	ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
-	if (rc==DS_OK)
-	    ok(speaker_config==new_speaker_config,"SetSpeakerConfig failed to set speaker config: expected 0x%08lx, got 0x%08lx\n",
-		speaker_config,new_speaker_config);
+        trace("  DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
+              dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
+              dscaps.dwMaxSecondarySampleRate);
     }
 
     /* Release the DirectSound object */
     ref=IDirectSound_Release(dso);
     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
     if (ref!=0)
-	return DSERR_GENERIC; 
+        return DSERR_GENERIC;
 
-#if 0	/* FIXME: this works on windows */ 
+#if 0
+    /* FIXME: this works on windows */
     /* Create a DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
     if (rc==DS_OK) {
-	LPDIRECTSOUND dso1=NULL;
+        LPDIRECTSOUND dso1=NULL;
 
-	/* Create a second DirectSound object */
-	rc=DirectSoundCreate(lpGuid,&dso1,NULL);
-	ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
-	if (rc==DS_OK) {
-	    /* Release the second DirectSound object */
-	    ref=IDirectSound_Release(dso1);
-	    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
-	    ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
-	}
-
-	/* Release the first DirectSound object */
-	ref=IDirectSound_Release(dso);
-	ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
-	if (ref!=0)
-	    return DSERR_GENERIC; 
+        /* Create a second DirectSound object */
+        rc=DirectSoundCreate(lpGuid,&dso1,NULL);
+        ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+        if (rc==DS_OK) {
+            /* Release the second DirectSound object */
+            ref=IDirectSound_Release(dso1);
+            ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+            ok(dso!=dso1,"DirectSound objects should be unique: dso=0x%08lx,dso1=0x%08lx\n",(DWORD)dso,(DWORD)dso1);
+        }
+
+        /* Release the first DirectSound object */
+        ref=IDirectSound_Release(dso);
+        ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+        if (ref!=0)
+            return DSERR_GENERIC;
     } else
-	return rc;
+        return rc;
 #endif
 
     return DS_OK;
@@ -785,13 +121,13 @@
     LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
     DSBUFFERDESC bufdesc;
     DSCAPS dscaps;
-    int ref, i;
+    int ref;
 
     /* Create the DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
     if (rc!=DS_OK)
-	return rc;
+        return rc;
 
     /* Get the device capabilities */
     ZeroMemory(&dscaps, sizeof(dscaps));
@@ -825,45 +161,39 @@
     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
     ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
     if (rc!=DS_OK)
-	goto EXIT;
+        goto EXIT;
 
     /* Testing the primary buffer */
     primary=NULL;
     ZeroMemory(&bufdesc, sizeof(bufdesc));
     bufdesc.dwSize=sizeof(bufdesc);
-    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
+    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
-    ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
-    if (rc==DS_OK&&primary!=NULL) {
-	/* Try to create a second primary buffer */
-	/* DSOUND: Error: The primary buffer already exists.  Any changes made to the buffer description will be ignored. */
-	rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
-	ok(rc==DS_OK&&second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
-	ref=IDirectSoundBuffer_Release(second);
-	ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref); 
-	/* Try to duplicate a primary buffer */
-	/* DSOUND: Error: Can't duplicate primary buffers */
-	rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
-	/* rc=0x88780032 */
-	ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
-	test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
-	test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
-	if (winetest_interactive) {
-	    LONG volume = DSBVOLUME_MAX;
-	    for (i = 0; i < 6; i++) {
-	    	test_buffer(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
-		volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
-	    }
-	    if (winetest_interactive) {
-		LONG pan = DSBPAN_LEFT;
-		for (i = 0; i < 7; i++) {
-	    	    test_buffer(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
-		    pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
-		}
-	    }
-	}
-	ref=IDirectSoundBuffer_Release(primary);
-	ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
+    if (rc==DS_OK && primary!=NULL) {
+        /* Try to create a second primary buffer */
+        /* DSOUND: Error: The primary buffer already exists.  Any changes made to the buffer description will be ignored. */
+        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
+        ok(rc==DS_OK && second==primary,"CreateSoundBuffer should have returned original primary buffer: 0x%lx\n",rc);
+        ref=IDirectSoundBuffer_Release(second);
+        ok(ref==1,"IDirectSoundBuffer_Release primary has %d references, should have 1\n",ref);
+
+        /* Try to duplicate a primary buffer */
+        /* DSOUND: Error: Can't duplicate primary buffers */
+        rc=IDirectSound_DuplicateSoundBuffer(dso,primary,&third);
+        /* rc=0x88780032 */
+        ok(rc!=DS_OK,"IDirectSound_DuplicateSoundBuffer primary buffer should have failed 0x%lx\n",rc);
+
+        if (winetest_interactive)
+        {
+            trace("Playing a 5 seconds reference tone.\n");
+            trace("All subsequent tones should be identical to this one.\n");
+            trace("Listen for stutter, changes in pitch, volume, etc.\n");
+        }
+        test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0);
+
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
     }
 
     /* Set the CooperativeLevel back to normal */
@@ -875,25 +205,26 @@
     ref=IDirectSound_Release(dso);
     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
     if (ref!=0)
-	return DSERR_GENERIC;
+        return DSERR_GENERIC;
 
     return rc;
 }
 
-static HRESULT test_primary_3d(LPGUID lpGuid)
+static HRESULT test_secondary(LPGUID lpGuid)
 {
     HRESULT rc;
     LPDIRECTSOUND dso=NULL;
-    LPDIRECTSOUNDBUFFER primary=NULL;
+    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
     DSBUFFERDESC bufdesc;
     DSCAPS dscaps;
-    int ref;
+    WAVEFORMATEX wfx;
+    int f,ref;
 
     /* Create the DirectSound object */
     rc=DirectSoundCreate(lpGuid,&dso,NULL);
     ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
     if (rc!=DS_OK)
-	return rc;
+        return rc;
 
     /* Get the device capabilities */
     ZeroMemory(&dscaps, sizeof(dscaps));
@@ -903,164 +234,68 @@
     if (rc!=DS_OK)
         goto EXIT;
 
-    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
+    /* We must call SetCooperativeLevel before creating primary buffer */
     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
-    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
     if (rc!=DS_OK)
-	goto EXIT;
+        goto EXIT;
 
-    primary=NULL;
     ZeroMemory(&bufdesc, sizeof(bufdesc));
     bufdesc.dwSize=sizeof(bufdesc);
     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+    bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
     rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
-    ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
-    if (rc==DS_OK&&primary!=NULL) {
-	ref=IDirectSoundBuffer_Release(primary);
-	ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
-        primary=NULL;
-        ZeroMemory(&bufdesc, sizeof(bufdesc));
-        bufdesc.dwSize=sizeof(bufdesc);
-        bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
-        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
-        ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
-        if (rc==DS_OK&&primary!=NULL) {
-	    test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
-	    ref=IDirectSoundBuffer_Release(primary);
-	    ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
-	}
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer 0x%lx\n", rc);
+
+    if (rc==DS_OK && primary!=NULL) {
+        for (f=0;f<NB_FORMATS;f++) {
+            init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1],formats[f][2]);
+            secondary=NULL;
+            ZeroMemory(&bufdesc, sizeof(bufdesc));
+            bufdesc.dwSize=sizeof(bufdesc);
+            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+            bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
+            bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
+            bufdesc.lpwfxFormat=&wfx;
+            trace("  Testing a secondary buffer at %ldx%dx%d\n",
+                  wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
+            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
+            ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n",rc);
+
+            if (rc==DS_OK && secondary!=NULL) {
+                test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,1.0,0,NULL,0,0);
+
+                ref=IDirectSoundBuffer_Release(secondary);
+                ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
+            }
+        }
+
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
     }
+
     /* Set the CooperativeLevel back to normal */
     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
     rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
-    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
 
 EXIT:
     ref=IDirectSound_Release(dso);
     ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
     if (ref!=0)
-	return DSERR_GENERIC;
-
-    return rc;
-}
-
-static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
-{
-    HRESULT rc;
-    LPDIRECTSOUND dso=NULL;
-    LPDIRECTSOUNDBUFFER primary=NULL;
-    DSBUFFERDESC bufdesc;
-    DSCAPS dscaps;
-    int ref;
-
-    /* Create the DirectSound object */
-    rc=DirectSoundCreate(lpGuid,&dso,NULL);
-    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	return rc;
-
-    /* Get the device capabilities */
-    ZeroMemory(&dscaps, sizeof(dscaps));
-    dscaps.dwSize=sizeof(dscaps);
-    rc=IDirectSound_GetCaps(dso,&dscaps);
-    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-        goto EXIT;
-
-    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
-    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
-    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
-    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
-    if (rc!=DS_OK)
-	goto EXIT;
-    primary=NULL;
-    ZeroMemory(&bufdesc, sizeof(bufdesc));
-    bufdesc.dwSize=sizeof(bufdesc);
-    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
-    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
-    ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
-    if (rc==DS_OK&&primary!=NULL) {
-	LPDIRECTSOUND3DLISTENER listener=NULL;
-	rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
-	ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
-	if (rc==DS_OK&&listener!=NULL) {
-	    LPDIRECTSOUNDBUFFER temp_buffer=NULL;
-
-	    /* Checking the COM interface */
-	    rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
-	    ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
-	    ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
-	    if(rc==DS_OK&&temp_buffer!=NULL) {
-		ref=IDirectSoundBuffer_Release(temp_buffer);
-		ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
-
-		temp_buffer=NULL;
-		rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
-		ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
-		ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
-		ref=IDirectSoundBuffer_Release(temp_buffer);
-		ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
-
-		/* Testing the buffer */
-		test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
-	    }
-
-	    /* Testing the reference counting */
-	    ref=IDirectSound3DListener_Release(listener);
-	    ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
-	}
-
-	/* Testing the reference counting */
-	ref=IDirectSoundBuffer_Release(primary);
-	ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref); 
-    }
-
-EXIT:
-    ref=IDirectSound_Release(dso);
-    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
-    if (ref!=0)
-	return DSERR_GENERIC;
+        return DSERR_GENERIC;
 
     return rc;
 }
 
 static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
-				   LPCSTR lpcstrModule, LPVOID lpContext)
+                                   LPCSTR lpcstrModule, LPVOID lpContext)
 {
-    HRESULT rc;
-
-    trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
-    rc=test_dsound(lpGuid);
-    ok(rc==DS_OK,"DirectSound test failed\n");
-   
-    trace("  Testing the primary buffer\n");
-    rc=test_primary(lpGuid);
-    ok(rc==DS_OK,"Primary Buffer test failed\n");
-
-    trace("  Testing 3D primary buffer\n");
-    rc=test_primary_3d(lpGuid);
-    ok(rc==DS_OK,"3D Primary Buffer test failed\n");
-
-    trace("  Testing 3D primary buffer with listener\n");
-    rc=test_primary_3d_with_listener(lpGuid);
-    ok(rc==DS_OK,"3D Primary Buffer with listener test failed\n");
-
-    /* Testing secondary buffers */
-    test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
-    test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
-
-    /* Testing 3D secondary buffers */
-    test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
-    test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
-    test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
+    trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
+    test_dsound(lpGuid);
+    test_primary(lpGuid);
+    test_secondary(lpGuid);
 
     return 1;
 }
--- /dev/null	2004-05-11 00:40:35.000000000 +0200
+++ dlls/dsound/tests/ds3d.c	2004-05-20 01:23:52.000000000 +0200
@@ -0,0 +1,978 @@
+/*
+ * Tests the panning and 3D functions of DirectSound
+ *
+ * Part of this test involves playing test tones. But this only makes
+ * sense if someone is going to carefully listen to it, and would only
+ * bother everyone else.
+ * So this is only done if the test is being run in interactive mode.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+#include <windows.h>
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "wine/test.h"
+#include "windef.h"
+#include "wingdi.h"
+#include "dsound.h"
+
+#include "dsound_test.h"
+
+const unsigned int formats[NB_FORMATS][3]={
+    { 8000,  8, 1},
+    { 8000,  8, 2},
+    { 8000, 16, 1},
+    { 8000, 16, 2},
+    {11025,  8, 1},
+    {11025,  8, 2},
+    {11025, 16, 1},
+    {11025, 16, 2},
+    {22050,  8, 1},
+    {22050,  8, 2},
+    {22050, 16, 1},
+    {22050, 16, 2},
+    {44100,  8, 1},
+    {44100,  8, 2},
+    {44100, 16, 1},
+    {44100, 16, 2},
+    {48000,  8, 1},
+    {48000,  8, 2},
+    {48000, 16, 1},
+    {48000, 16, 2},
+    {96000,  8, 1},
+    {96000,  8, 2},
+    {96000, 16, 1},
+    {96000, 16, 2}
+};
+
+
+#define PI 3.14159265358979323846
+char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
+{
+    int i,fade;
+    int nb_samples;
+    char* buf;
+    char* b;
+
+    fade=wfx->nSamplesPerSec/100;
+    nb_samples=(int)(duration*wfx->nSamplesPerSec);
+    *size=nb_samples*wfx->nBlockAlign;
+    b=buf=malloc(*size);
+    for (i=0;i<nb_samples;i++) {
+        double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
+        if (i<fade)
+            y=y*i/fade;
+        else if (nb_samples-i<fade)
+            y=y*(nb_samples-1-i)/fade;
+        if (wfx->wBitsPerSample==8) {
+            unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
+            *b++=sample;
+            if (wfx->nChannels==2)
+                *b++=sample;
+        } else {
+            signed short sample=(signed short)((double)32767.5*y-0.5);
+            b[0]=sample & 0xff;
+            b[1]=sample >> 8;
+            b+=2;
+            if (wfx->nChannels==2) {
+                b[0]=sample & 0xff;
+                b[1]=sample >> 8;
+                b+=2;
+            }
+        }
+    }
+    return buf;
+}
+
+HWND get_hwnd()
+{
+    HWND hwnd=GetForegroundWindow();
+    if (!hwnd)
+        hwnd=GetDesktopWindow();
+    return hwnd;
+}
+
+void init_format(WAVEFORMATEX* wfx, int format, int rate, int depth, int channels)
+{
+    wfx->wFormatTag=format;
+    wfx->nChannels=channels;
+    wfx->wBitsPerSample=depth;
+    wfx->nSamplesPerSec=rate;
+    wfx->nBlockAlign=wfx->nChannels*wfx->wBitsPerSample/8;
+    /* FIXME: Shouldn't this test be if (format!=WAVE_FORMAT_PCM) */
+    if (wfx->nBlockAlign==0)
+    {
+        /* align compressed formats to byte boundary */
+        wfx->nBlockAlign=1;
+    }
+    wfx->nAvgBytesPerSec=wfx->nSamplesPerSec*wfx->nBlockAlign;
+    wfx->cbSize=0;
+}
+
+typedef struct {
+    char* wave;
+    DWORD wave_len;
+
+    LPDIRECTSOUNDBUFFER dsbo;
+    LPWAVEFORMATEX wfx;
+    DWORD buffer_size;
+    DWORD written;
+    DWORD offset;
+
+    DWORD last_pos;
+} play_state_t;
+
+static int buffer_refill(play_state_t* state, DWORD size)
+{
+    LPVOID ptr1,ptr2;
+    DWORD len1,len2;
+    HRESULT rc;
+
+    if (size>state->wave_len-state->written)
+        size=state->wave_len-state->written;
+
+    rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
+                               &ptr1,&len1,&ptr2,&len2,0);
+    ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return -1;
+
+    memcpy(ptr1,state->wave+state->written,len1);
+    state->written+=len1;
+    if (ptr2!=NULL) {
+        memcpy(ptr2,state->wave+state->written,len2);
+        state->written+=len2;
+    }
+    state->offset=state->written % state->buffer_size;
+    rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
+    ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return -1;
+    return size;
+}
+
+static int buffer_silence(play_state_t* state, DWORD size)
+{
+    LPVOID ptr1,ptr2;
+    DWORD len1,len2;
+    HRESULT rc;
+    BYTE s;
+
+    rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
+                               &ptr1,&len1,&ptr2,&len2,0);
+    ok(rc==DS_OK,"Lock: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return -1;
+
+    s=(state->wfx->wBitsPerSample==8?0x80:0);
+    memset(ptr1,s,len1);
+    if (ptr2!=NULL) {
+        memset(ptr2,s,len2);
+    }
+    state->offset=(state->offset+size) % state->buffer_size;
+    rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
+    ok(rc==DS_OK,"Unlock: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return -1;
+    return size;
+}
+
+static int buffer_service(play_state_t* state)
+{
+    DWORD play_pos,write_pos,buf_free;
+    HRESULT rc;
+
+    rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
+    ok(rc==DS_OK,"GetCurrentPosition: %lx\n",rc);
+    if (rc!=DS_OK) {
+        goto STOP;
+    }
+
+    /* Refill the buffer */
+    if (state->offset<=play_pos) {
+        buf_free=play_pos-state->offset;
+    } else {
+        buf_free=state->buffer_size-state->offset+play_pos;
+    }
+    if (winetest_debug > 1)
+        trace("buf pos=%ld free=%ld written=%ld / %ld\n",
+              play_pos,buf_free,state->written,state->wave_len);
+    if (buf_free==0)
+        return 1;
+
+    if (state->written<state->wave_len) {
+        int w=buffer_refill(state,buf_free);
+        if (w==-1)
+            goto STOP;
+        buf_free-=w;
+        if (state->written==state->wave_len) {
+            state->last_pos=(state->offset<play_pos)?play_pos:0;
+            if (winetest_debug > 1)
+                trace("last sound byte at %ld\n",
+                      (state->written % state->buffer_size));
+        }
+    } else {
+        if (state->last_pos!=0 && play_pos<state->last_pos) {
+            /* We wrapped around the end of the buffer */
+            state->last_pos=0;
+        }
+        if (state->last_pos==0 &&
+            play_pos>(state->written % state->buffer_size)) {
+            /* Now everything has been played */
+            goto STOP;
+        }
+    }
+
+    if (buf_free>0) {
+        /* Fill with silence */
+        if (winetest_debug > 1)
+            trace("writing %ld bytes of silence\n",buf_free);
+        if (buffer_silence(state,buf_free)==-1)
+            goto STOP;
+    }
+    return 1;
+
+STOP:
+    if (winetest_debug > 1)
+        trace("stopping playback\n");
+    rc=IDirectSoundBuffer_Stop(state->dsbo);
+    ok(rc==DS_OK,"Stop failed: rc=%ld\n",rc);
+    return 0;
+}
+
+void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
+                 BOOL is_primary, BOOL set_volume, LONG volume,
+                 BOOL set_pan, LONG pan, BOOL play, double duration,
+                 BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
+                 BOOL move_listener, BOOL move_sound)
+{
+    HRESULT rc;
+    DSBCAPS dsbcaps;
+    WAVEFORMATEX wfx,wfx2;
+    DWORD size,status,freq;
+    int ref;
+
+    /* DSOUND: Error: Invalid caps pointer */
+    rc=IDirectSoundBuffer_GetCaps(dsbo,0);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
+
+    ZeroMemory(&dsbcaps, sizeof(dsbcaps));
+
+    /* DSOUND: Error: Invalid caps pointer */
+    rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
+    ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
+
+    dsbcaps.dwSize=sizeof(dsbcaps);
+    rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
+    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
+    if (rc==DS_OK) {
+        trace("    Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
+              dsbcaps.dwBufferBytes);
+    }
+
+    /* Query the format size. Note that it may not match sizeof(wfx) */
+    size=0;
+    rc=IDirectSoundBuffer_GetFormat(dsbo,NULL,0,&size);
+    ok(rc==DS_OK && size!=0,
+       "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n",
+       rc,size);
+
+    rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
+    ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
+    if (rc==DS_OK && is_primary) {
+        trace("Primary buffer default format: tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
+              wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
+              wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
+    }
+
+    /* DSOUND: Error: Invalid frequency buffer */
+    rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
+    ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
+
+    /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
+    rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
+    ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
+       (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
+       "GetFrequency failed: 0x%lx\n",rc);
+    if (rc==DS_OK) {
+        ok(freq==wfx.nSamplesPerSec,
+           "The frequency returned by GetFrequency %ld does not match the format %ld\n",
+           freq,wfx.nSamplesPerSec);
+    }
+
+    /* DSOUND: Error: Invalid status pointer */
+    rc=IDirectSoundBuffer_GetStatus(dsbo,0);
+    ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
+
+    rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
+    ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
+    ok(status==0,"status=0x%lx instead of 0\n",status);
+
+    if (is_primary) {
+        /* We must call SetCooperativeLevel to be allowed to call SetFormat */
+        /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
+        rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+        ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+        if (rc!=DS_OK)
+            return;
+
+        /* DSOUND: Error: Invalid format pointer */
+        rc=IDirectSoundBuffer_SetFormat(dsbo,0);
+        ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
+
+        init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
+        rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
+        ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
+
+        /* There is no garantee that SetFormat will actually change the
+	 * format to what we asked for. It depends on what the soundcard
+	 * supports. So we must re-query the format.
+	 */
+        rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
+        ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
+        if (rc==DS_OK &&
+            (wfx.wFormatTag!=wfx2.wFormatTag ||
+             wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
+             wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
+             wfx.nChannels!=wfx2.nChannels)) {
+            trace("Requested format tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
+                  wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
+                  wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
+            trace("Got tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
+                  wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
+                  wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
+        }
+
+        /* Set the CooperativeLevel back to normal */
+        /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
+        rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
+        ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+    }
+
+    if (play) {
+        play_state_t state;
+        DS3DLISTENER listener_param;
+        LPDIRECTSOUND3DBUFFER buffer=NULL;
+        DS3DBUFFER buffer_param;
+
+        trace("    Playing %g second 440Hz tone at %ldx%dx%d\n", duration,
+              wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
+
+        if (is_primary) {
+            /* We must call SetCooperativeLevel to be allowed to call Lock */
+            /* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
+            rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
+            ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+            if (rc!=DS_OK)
+                return;
+        }
+        if (buffer3d) {
+            LPDIRECTSOUNDBUFFER temp_buffer;
+
+            rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
+            ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
+            if (rc!=DS_OK)
+                return;
+
+            /* check the COM interface */
+            rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
+            ok(rc==DS_OK && temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
+            ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
+            ref=IDirectSoundBuffer_Release(temp_buffer);
+            ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
+
+            temp_buffer=NULL;
+            rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
+            ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
+            ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
+            ref=IDirectSoundBuffer_Release(temp_buffer);
+            ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
+
+#if 0
+            /* FIXME: this works on windows */
+            ref=IDirectSoundBuffer_Release(dsbo);
+            ok(ref==0,"IDirectSoundBuffer_Release has %d references, should have 0\n",ref);
+
+            rc=IDirectSound3DBuffer_QueryInterface(buffer, &IID_IDirectSoundBuffer,(LPVOID *)&dsbo);
+            ok(rc==DS_OK && dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
+#endif
+
+            /* DSOUND: Error: Invalid buffer */
+            rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
+            ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
+
+            ZeroMemory(&buffer_param, sizeof(buffer_param));
+
+            /* DSOUND: Error: Invalid buffer */
+            rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
+            ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
+
+            buffer_param.dwSize=sizeof(buffer_param);
+            rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
+            ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
+}
+        if (set_volume) {
+            if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
+                LONG val;
+                rc=IDirectSoundBuffer_GetVolume(dsbo,&val);
+                ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
+
+                rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
+                ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
+            } else {
+                /* DSOUND: Error: Buffer does not have CTRLVOLUME */
+                rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
+                ok(rc==DSERR_CONTROLUNAVAIL,"GetVolume should have failed: 0x%lx\n",rc);
+            }
+        }
+
+        if (set_pan) {
+            if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
+                LONG val;
+                rc=IDirectSoundBuffer_GetPan(dsbo,&val);
+                ok(rc==DS_OK,"GetPan failed: 0x%lx\n",rc);
+
+                rc=IDirectSoundBuffer_SetPan(dsbo,pan);
+                ok(rc==DS_OK,"SetPan failed: 0x%lx\n",rc);
+
+                rc=IDirectSoundBuffer_GetPan(dsbo,&val);
+                ok(val==pan,"volume=%ld instead of %ld\n",val,pan);
+            } else {
+                /* DSOUND: Error: Buffer does not have CTRLPAN */
+                rc=IDirectSoundBuffer_GetPan(dsbo,&pan);
+                ok(rc==DSERR_CONTROLUNAVAIL,"GetPan should have failed: 0x%lx\n",rc);
+            }
+        }
+
+        state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
+
+        state.dsbo=dsbo;
+        state.wfx=&wfx;
+        state.buffer_size=dsbcaps.dwBufferBytes;
+        state.written=state.offset=0;
+        buffer_refill(&state,state.buffer_size);
+
+        rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
+        ok(rc==DS_OK,"Play: 0x%lx\n",rc);
+
+        rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
+        ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
+        ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
+           "GetStatus: bad status: %lx\n",status);
+
+        if (listener) {
+            ZeroMemory(&listener_param,sizeof(listener_param));
+            listener_param.dwSize=sizeof(listener_param);
+            rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
+            ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
+            if (move_listener)
+                listener_param.vPosition.x = -5.0;
+            else
+                listener_param.vPosition.x = 0.0;
+            listener_param.vPosition.y = 0.0;
+            listener_param.vPosition.z = 0.0;
+            rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
+            ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
+        }
+        if (buffer3d) {
+            if (move_sound)
+                buffer_param.vPosition.x = 5.0;
+            else
+                buffer_param.vPosition.x = 0.0;
+            buffer_param.vPosition.y = 0.0;
+            buffer_param.vPosition.z = 0.0;
+            rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
+            ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
+        }
+
+        while (buffer_service(&state)) {
+            WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
+            if (listener && move_listener) {
+                listener_param.vPosition.x += 0.5;
+                rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.x,listener_param.vPosition.y,listener_param.vPosition.z,DS3D_IMMEDIATE);
+                ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
+            }
+            if (buffer3d && move_sound) {
+                buffer_param.vPosition.x -= 0.5;
+                rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.x,buffer_param.vPosition.y,buffer_param.vPosition.z,DS3D_IMMEDIATE);
+                ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
+            }
+        }
+
+        free(state.wave);
+        if (is_primary) {
+            /* Set the CooperativeLevel back to normal */
+            /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
+            rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
+            ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+        }
+        if (buffer3d) {
+            ref=IDirectSound3DBuffer_Release(buffer);
+            ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
+        }
+    }
+}
+
+static HRESULT test_secondary(LPGUID lpGuid, int play,
+                              int has_3d, int has_3dbuffer,
+                              int has_listener, int has_duplicate,
+                              int move_listener, int move_sound)
+{
+    HRESULT rc;
+    LPDIRECTSOUND dso=NULL;
+    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
+    LPDIRECTSOUND3DLISTENER listener=NULL;
+    DSBUFFERDESC bufdesc;
+    WAVEFORMATEX wfx;
+    int ref;
+
+    /* Create the DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return rc;
+
+    /* We must call SetCooperativeLevel before creating primary buffer */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    ZeroMemory(&bufdesc, sizeof(bufdesc));
+    bufdesc.dwSize=sizeof(bufdesc);
+    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+    if (has_3d)
+        bufdesc.dwFlags|=DSBCAPS_CTRL3D;
+    else
+        bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
+    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a %sprimary buffer 0x%lx\n",has_3d?"3D ":"", rc);
+
+    if (rc==DS_OK && primary!=NULL) {
+        if (has_listener) {
+            rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
+            ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
+            ref=IDirectSoundBuffer_Release(primary);
+            ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+            if (rc==DS_OK && listener!=NULL) {
+                DS3DLISTENER listener_param;
+                ZeroMemory(&listener_param,sizeof(listener_param));
+                /* DSOUND: Error: Invalid buffer */
+                rc=IDirectSound3DListener_GetAllParameters(listener,0);
+                ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
+
+                /* DSOUND: Error: Invalid buffer */
+                rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
+                ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
+
+                listener_param.dwSize=sizeof(listener_param);
+                rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
+                ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
+            }
+            else
+                goto EXIT;
+        }
+
+        init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
+        secondary=NULL;
+        ZeroMemory(&bufdesc, sizeof(bufdesc));
+        bufdesc.dwSize=sizeof(bufdesc);
+        bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+        if (has_3d)
+            bufdesc.dwFlags|=DSBCAPS_CTRL3D;
+        else
+            bufdesc.dwFlags|=(DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
+        bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
+        bufdesc.lpwfxFormat=&wfx;
+        trace("  Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
+              has_3dbuffer?"3D ":"",
+              has_duplicate?"duplicated ":"",
+              listener!=NULL||move_sound?"with ":"",
+              move_listener?"moving ":"",
+              listener!=NULL?"listener ":"",
+              listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
+              wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
+        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
+        ok(rc==DS_OK && secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
+        if (rc==DS_OK && secondary!=NULL) {
+            if (has_duplicate) {
+                LPDIRECTSOUNDBUFFER duplicated=NULL;
+
+                /* DSOUND: Error: Invalid source buffer */
+                rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
+                ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
+
+                /* DSOUND: Error: Invalid dest buffer */
+                rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
+                ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
+
+                /* DSOUND: Error: Invalid source buffer */
+                rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
+                ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
+
+                duplicated=NULL;
+                rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
+                ok(rc==DS_OK && duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
+
+                if (rc==DS_OK && duplicated!=NULL) {
+                    ref=IDirectSoundBuffer_Release(secondary);
+                    ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
+                    secondary=duplicated;
+                }
+            }
+
+            if (rc==DS_OK && secondary!=NULL) {
+                double duration;
+                duration=(move_listener || move_sound?4.0:1.0);
+                test_buffer(dso,secondary,0,FALSE,0,FALSE,0,winetest_interactive,duration,has_3dbuffer,listener,move_listener,move_sound);
+                ref=IDirectSoundBuffer_Release(secondary);
+                ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
+            }
+        }
+    }
+    if (has_listener) {
+        ref=IDirectSound3DListener_Release(listener);
+        ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
+    } else {
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+    }
+
+    /* Set the CooperativeLevel back to normal */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
+
+EXIT:
+    ref=IDirectSound_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+        return DSERR_GENERIC;
+
+    return rc;
+}
+
+static HRESULT test_dsound(LPGUID lpGuid)
+{
+    HRESULT rc;
+    LPDIRECTSOUND dso=NULL;
+    DWORD speaker_config, new_speaker_config;
+    int ref;
+
+    /* The basic DirectSound tests are performed in the playback test */
+
+    /* Create the DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return rc;
+
+    rc=IDirectSound_GetSpeakerConfig(dso,0);
+    ok(rc==DSERR_INVALIDPARAM,"GetSpeakerConfig should have failed: 0x%lx\n",rc);
+
+    rc=IDirectSound_GetSpeakerConfig(dso,&speaker_config);
+    ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
+    if (rc==DS_OK) {
+        trace("  DirectSound SpeakerConfig: 0x%08lx\n", speaker_config);
+    }
+
+    speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,DSSPEAKER_GEOMETRY_WIDE);
+    rc=IDirectSound_SetSpeakerConfig(dso,speaker_config);
+    ok(rc==DS_OK,"SetSpeakerConfig failed: 0x%lx\n",rc);
+    if (rc==DS_OK) {
+        rc=IDirectSound_GetSpeakerConfig(dso,&new_speaker_config);
+        ok(rc==DS_OK,"GetSpeakerConfig failed: 0x%lx\n",rc);
+        if (rc==DS_OK)
+            ok(speaker_config==new_speaker_config,"SetSpeakerConfig failed to set speaker config: expected 0x%08lx, got 0x%08lx\n",
+               speaker_config,new_speaker_config);
+    }
+
+    /* Release the DirectSound object */
+    ref=IDirectSound_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+        return DSERR_GENERIC;
+
+    return DS_OK;
+}
+
+static HRESULT test_primary(LPGUID lpGuid)
+{
+    HRESULT rc;
+    LPDIRECTSOUND dso=NULL;
+    LPDIRECTSOUNDBUFFER primary=NULL;
+    DSBUFFERDESC bufdesc;
+    DSCAPS dscaps;
+    int ref, i;
+
+    /* Create the DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return rc;
+
+    /* Get the device capabilities */
+    ZeroMemory(&dscaps, sizeof(dscaps));
+    dscaps.dwSize=sizeof(dscaps);
+    rc=IDirectSound_GetCaps(dso,&dscaps);
+    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    /* Testing the primary buffer */
+    primary=NULL;
+    ZeroMemory(&bufdesc, sizeof(bufdesc));
+    bufdesc.dwSize=sizeof(bufdesc);
+    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN;
+    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
+    if (rc==DS_OK && primary!=NULL) {
+        test_buffer(dso,primary,1,TRUE,0,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
+        if (winetest_interactive) {
+            LONG volume,pan;
+
+            volume = DSBVOLUME_MAX;
+            for (i = 0; i < 6; i++) {
+                test_buffer(dso,primary,1,TRUE,volume,TRUE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,NULL,0,0);
+                volume -= ((DSBVOLUME_MAX-DSBVOLUME_MIN) / 40);
+            }
+
+            pan = DSBPAN_LEFT;
+            for (i = 0; i < 7; i++) {
+                test_buffer(dso,primary,1,TRUE,0,TRUE,pan,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
+                pan += ((DSBPAN_RIGHT-DSBPAN_LEFT) / 6);
+            }
+        }
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+    }
+
+    /* Set the CooperativeLevel back to normal */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+
+EXIT:
+    ref=IDirectSound_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+        return DSERR_GENERIC;
+
+    return rc;
+}
+
+static HRESULT test_primary_3d(LPGUID lpGuid)
+{
+    HRESULT rc;
+    LPDIRECTSOUND dso=NULL;
+    LPDIRECTSOUNDBUFFER primary=NULL;
+    DSBUFFERDESC bufdesc;
+    DSCAPS dscaps;
+    int ref;
+
+    /* Create the DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return rc;
+
+    /* Get the device capabilities */
+    ZeroMemory(&dscaps, sizeof(dscaps));
+    dscaps.dwSize=sizeof(dscaps);
+    rc=IDirectSound_GetCaps(dso,&dscaps);
+    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    primary=NULL;
+    ZeroMemory(&bufdesc, sizeof(bufdesc));
+    bufdesc.dwSize=sizeof(bufdesc);
+    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
+    if (rc==DS_OK && primary!=NULL) {
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+        primary=NULL;
+        ZeroMemory(&bufdesc, sizeof(bufdesc));
+        bufdesc.dwSize=sizeof(bufdesc);
+        bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
+        rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+        ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
+        if (rc==DS_OK && primary!=NULL) {
+            test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,0,0,0);
+            ref=IDirectSoundBuffer_Release(primary);
+            ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+        }
+    }
+    /* Set the CooperativeLevel back to normal */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+
+EXIT:
+    ref=IDirectSound_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+        return DSERR_GENERIC;
+
+    return rc;
+}
+
+static HRESULT test_primary_3d_with_listener(LPGUID lpGuid)
+{
+    HRESULT rc;
+    LPDIRECTSOUND dso=NULL;
+    LPDIRECTSOUNDBUFFER primary=NULL;
+    DSBUFFERDESC bufdesc;
+    DSCAPS dscaps;
+    int ref;
+
+    /* Create the DirectSound object */
+    rc=DirectSoundCreate(lpGuid,&dso,NULL);
+    ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        return rc;
+
+    /* Get the device capabilities */
+    ZeroMemory(&dscaps, sizeof(dscaps));
+    dscaps.dwSize=sizeof(dscaps);
+    rc=IDirectSound_GetCaps(dso,&dscaps);
+    ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+
+    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
+    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
+    rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
+    ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
+    if (rc!=DS_OK)
+        goto EXIT;
+    primary=NULL;
+    ZeroMemory(&bufdesc, sizeof(bufdesc));
+    bufdesc.dwSize=sizeof(bufdesc);
+    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
+    rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
+    ok(rc==DS_OK && primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
+    if (rc==DS_OK && primary!=NULL) {
+        LPDIRECTSOUND3DLISTENER listener=NULL;
+        rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
+        ok(rc==DS_OK && listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
+        if (rc==DS_OK && listener!=NULL) {
+            LPDIRECTSOUNDBUFFER temp_buffer=NULL;
+
+            /* Checking the COM interface */
+            rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
+            ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
+            ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
+            if (rc==DS_OK && temp_buffer!=NULL) {
+                ref=IDirectSoundBuffer_Release(temp_buffer);
+                ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
+
+                temp_buffer=NULL;
+                rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
+                ok(rc==DS_OK && temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
+                ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
+                ref=IDirectSoundBuffer_Release(temp_buffer);
+                ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
+
+                /* Testing the buffer */
+                test_buffer(dso,primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),1.0,0,listener,0,0);
+            }
+
+            /* Testing the reference counting */
+            ref=IDirectSound3DListener_Release(listener);
+            ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
+        }
+
+        /* Testing the reference counting */
+        ref=IDirectSoundBuffer_Release(primary);
+        ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
+    }
+
+EXIT:
+    ref=IDirectSound_Release(dso);
+    ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
+    if (ref!=0)
+return DSERR_GENERIC;
+
+    return rc;
+}
+
+static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
+                                   LPCSTR lpcstrModule, LPVOID lpContext)
+{
+    trace("*** Testing %s - %s\n",lpcstrDescription,lpcstrModule);
+    test_dsound(lpGuid);
+
+    trace("  Testing the primary buffer\n");
+    test_primary(lpGuid);
+
+    trace("  Testing 3D primary buffer\n");
+    test_primary_3d(lpGuid);
+
+    trace("  Testing 3D primary buffer with listener\n");
+    test_primary_3d_with_listener(lpGuid);
+
+    /* Testing secondary buffers */
+    test_secondary(lpGuid,winetest_interactive,0,0,0,0,0,0);
+    test_secondary(lpGuid,winetest_interactive,0,0,0,1,0,0);
+
+    /* Testing 3D secondary buffers */
+    test_secondary(lpGuid,winetest_interactive,1,0,0,0,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,0,0,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,0,1,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,0,1,0,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,0,1,1,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,1,1,0,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,0);
+    test_secondary(lpGuid,winetest_interactive,1,1,1,0,0,1);
+    test_secondary(lpGuid,winetest_interactive,1,1,1,0,1,1);
+
+    return 1;
+}
+
+static void ds3d_tests()
+{
+    HRESULT rc;
+    rc=DirectSoundEnumerateA(&dsenum_callback,NULL);
+    ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc);
+}
+
+START_TEST(ds3d)
+{
+    ds3d_tests();
+}
--- /dev/null	2004-05-11 00:40:35.000000000 +0200
+++ dlls/dsound/tests/dsound_test.h	2004-05-20 00:38:17.000000000 +0200
@@ -0,0 +1,34 @@
+/*
+ * Unit tests for dsound functions
+ *
+ * Copyright (c) 2002 Francois Gouget
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define NB_FORMATS 24
+extern const unsigned int formats[NB_FORMATS][3];
+
+/* The time slice determines how often we will service the buffer */
+#define TIME_SLICE    100
+#define BUFFER_LEN    (4*TIME_SLICE)
+
+
+extern char* wave_generate_la(WAVEFORMATEX*,double,DWORD*);
+extern HWND get_hwnd();
+extern void init_format(WAVEFORMATEX*,int,int,int,int);
+extern void test_buffer(LPDIRECTSOUND,LPDIRECTSOUNDBUFFER,
+                        BOOL,BOOL,LONG,BOOL,LONG,BOOL,double,BOOL,
+                        LPDIRECTSOUND3DLISTENER,BOOL,BOOL);


More information about the wine-patches mailing list