~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/dsound/tests/ds3d8.c

Version: ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Tests the panning and 3D functions of DirectSound
  3  *
  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.
  8  *
  9  * Copyright (c) 2002-2004 Francois Gouget
 10  *
 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.
 15  *
 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.
 20  *
 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 24  */
 25 
 26 #include <windows.h>
 27 
 28 #include <math.h>
 29 
 30 #include "wine/test.h"
 31 #include "dsound.h"
 32 #include "mmreg.h"
 33 #include "dsound_test.h"
 34 
 35 static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
 36 static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;
 37 
 38 typedef struct {
 39     char* wave;
 40     DWORD wave_len;
 41 
 42     LPDIRECTSOUNDBUFFER dsbo;
 43     LPWAVEFORMATEX wfx;
 44     DWORD buffer_size;
 45     DWORD written;
 46     DWORD played;
 47     DWORD offset;
 48 } play_state_t;
 49 
 50 static int buffer_refill8(play_state_t* state, DWORD size)
 51 {
 52     LPVOID ptr1,ptr2;
 53     DWORD len1,len2;
 54     HRESULT rc;
 55 
 56     if (size>state->wave_len-state->written)
 57         size=state->wave_len-state->written;
 58 
 59     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
 60                                &ptr1,&len1,&ptr2,&len2,0);
 61     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
 62     if (rc!=DS_OK)
 63         return -1;
 64 
 65     memcpy(ptr1,state->wave+state->written,len1);
 66     state->written+=len1;
 67     if (ptr2!=NULL) {
 68         memcpy(ptr2,state->wave+state->written,len2);
 69         state->written+=len2;
 70     }
 71     state->offset=state->written % state->buffer_size;
 72     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
 73     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
 74     if (rc!=DS_OK)
 75         return -1;
 76     return size;
 77 }
 78 
 79 static int buffer_silence8(play_state_t* state, DWORD size)
 80 {
 81     LPVOID ptr1,ptr2;
 82     DWORD len1,len2;
 83     HRESULT rc;
 84     BYTE s;
 85 
 86     rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
 87                                &ptr1,&len1,&ptr2,&len2,0);
 88     ok(rc==DS_OK,"IDirectSoundBuffer_Lock() failed: %08x\n", rc);
 89     if (rc!=DS_OK)
 90         return -1;
 91 
 92     s=(state->wfx->wBitsPerSample==8?0x80:0);
 93     memset(ptr1,s,len1);
 94     if (ptr2!=NULL) {
 95         memset(ptr2,s,len2);
 96     }
 97     state->offset=(state->offset+size) % state->buffer_size;
 98     rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
 99     ok(rc==DS_OK,"IDirectSoundBuffer_Unlock() failed: %08x\n", rc);
100     if (rc!=DS_OK)
101         return -1;
102     return size;
103 }
104 
105 static int buffer_service8(play_state_t* state)
106 {
107     DWORD last_play_pos,play_pos,buf_free;
108     HRESULT rc;
109 
110     rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,NULL);
111     ok(rc==DS_OK,"IDirectSoundBuffer_GetCurrentPosition() failed: %08x\n", rc);
112     if (rc!=DS_OK) {
113         goto STOP;
114     }
115 
116     /* Update the amount played */
117     last_play_pos=state->played % state->buffer_size;
118     if (play_pos<last_play_pos)
119         state->played+=state->buffer_size-last_play_pos+play_pos;
120     else
121         state->played+=play_pos-last_play_pos;
122 
123     if (winetest_debug > 1)
124         trace("buf size=%d last_play_pos=%d play_pos=%d played=%d / %d\n",
125               state->buffer_size,last_play_pos,play_pos,state->played,
126               state->wave_len);
127 
128     if (state->played>state->wave_len)
129     {
130         /* Everything has been played */
131         goto STOP;
132     }
133 
134     /* Refill the buffer */
135     if (state->offset<=play_pos)
136         buf_free=play_pos-state->offset;
137     else
138         buf_free=state->buffer_size-state->offset+play_pos;
139 
140     if (winetest_debug > 1)
141         trace("offset=%d free=%d written=%d / %d\n",
142               state->offset,buf_free,state->written,state->wave_len);
143     if (buf_free==0)
144         return 1;
145 
146     if (state->written<state->wave_len)
147     {
148         int w=buffer_refill8(state,buf_free);
149         if (w==-1)
150             goto STOP;
151         buf_free-=w;
152         if (state->written==state->wave_len && winetest_debug > 1)
153             trace("last sound byte at %d\n",
154                   (state->written % state->buffer_size));
155     }
156 
157     if (buf_free>0) {
158         /* Fill with silence */
159         if (winetest_debug > 1)
160             trace("writing %d bytes of silence\n",buf_free);
161         if (buffer_silence8(state,buf_free)==-1)
162             goto STOP;
163     }
164     return 1;
165 
166 STOP:
167     if (winetest_debug > 1)
168         trace("stopping playback\n");
169     rc=IDirectSoundBuffer_Stop(state->dsbo);
170     ok(rc==DS_OK,"IDirectSoundBuffer_Stop() failed: %08x\n", rc);
171     return 0;
172 }
173 
174 void test_buffer8(LPDIRECTSOUND8 dso, LPDIRECTSOUNDBUFFER * dsbo,
175                   BOOL is_primary, BOOL set_volume, LONG volume,
176                   BOOL set_pan, LONG pan, BOOL play, double duration,
177                   BOOL buffer3d, LPDIRECTSOUND3DLISTENER listener,
178                   BOOL move_listener, BOOL move_sound)
179 {
180     HRESULT rc;
181     DSBCAPS dsbcaps;
182     WAVEFORMATEX wfx,wfx2;
183     DWORD size,status,freq;
184     int ref;
185 
186     /* DSOUND: Error: Invalid caps pointer */
187     rc=IDirectSoundBuffer_GetCaps(*dsbo,0);
188     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
189        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
190 
191     ZeroMemory(&dsbcaps, sizeof(dsbcaps));
192 
193     /* DSOUND: Error: Invalid caps pointer */
194     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
195     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetCaps() should have "
196        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
197 
198     dsbcaps.dwSize=sizeof(dsbcaps);
199     rc=IDirectSoundBuffer_GetCaps(*dsbo,&dsbcaps);
200     ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
201     if (rc==DS_OK && winetest_debug > 1) {
202         trace("    Caps: flags=0x%08x size=%d\n",dsbcaps.dwFlags,
203               dsbcaps.dwBufferBytes);
204     }
205 
206     /* Query the format size. */
207     size=0;
208     rc=IDirectSoundBuffer_GetFormat(*dsbo,NULL,0,&size);
209     ok(rc==DS_OK && size!=0,"IDirectSoundBuffer_GetFormat() should have "
210        "returned the needed size: rc=%08x size=%d\n",rc,size);
211 
212     ok(size == sizeof(WAVEFORMATEX) || size == sizeof(WAVEFORMATEXTENSIBLE),
213        "Expected a correct structure size, got %d\n", size);
214 
215     if (size == sizeof(WAVEFORMATEX)) {
216         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,size,NULL);
217     } else if (size == sizeof(WAVEFORMATEXTENSIBLE)) {
218         WAVEFORMATEXTENSIBLE wfxe;
219         rc=IDirectSoundBuffer_GetFormat(*dsbo,(WAVEFORMATEX*)&wfxe,size,NULL);
220         wfx = wfxe.Format;
221     }
222     ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
223     if (rc==DS_OK && winetest_debug > 1) {
224         trace("    Format: %s tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
225               is_primary ? "Primary" : "Secondary",
226               wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
227               wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
228     }
229 
230     /* DSOUND: Error: Invalid frequency buffer */
231     rc=IDirectSoundBuffer_GetFrequency(*dsbo,0);
232     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetFrequency() should have "
233        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
234 
235     /* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
236     rc=IDirectSoundBuffer_GetFrequency(*dsbo,&freq);
237     ok((rc==DS_OK && !is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary) ||
238        (rc==DSERR_CONTROLUNAVAIL&&!(dsbcaps.dwFlags&DSBCAPS_CTRLFREQUENCY)),
239        "IDirectSoundBuffer_GetFrequency() failed: %08x\n",rc);
240     if (rc==DS_OK) {
241         ok(freq==wfx.nSamplesPerSec,"The frequency returned by GetFrequency "
242            "%d does not match the format %d\n",freq,wfx.nSamplesPerSec);
243     }
244 
245     /* DSOUND: Error: Invalid status pointer */
246     rc=IDirectSoundBuffer_GetStatus(*dsbo,0);
247     ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_GetStatus() should have "
248        "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
249 
250     rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
251     ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
252     ok(status==0,"status=0x%x instead of 0\n",status);
253 
254     if (is_primary) {
255         DSBCAPS new_dsbcaps;
256         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
257         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
258         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
259         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) "
260            "failed: %08x\n",rc);
261         if (rc!=DS_OK)
262             return;
263 
264         /* DSOUND: Error: Invalid format pointer */
265         rc=IDirectSoundBuffer_SetFormat(*dsbo,0);
266         ok(rc==DSERR_INVALIDPARAM,"IDirectSoundBuffer_SetFormat() should have "
267            "returned DSERR_INVALIDPARAM, returned: %08x\n",rc);
268 
269         init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);
270         rc=IDirectSoundBuffer_SetFormat(*dsbo,&wfx2);
271         ok(rc==DS_OK,"IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
272            format_string(&wfx2), rc);
273 
274         /* There is no guarantee that SetFormat will actually change the
275          * format to what we asked for. It depends on what the soundcard
276          * supports. So we must re-query the format.
277          */
278         rc=IDirectSoundBuffer_GetFormat(*dsbo,&wfx,sizeof(wfx),NULL);
279         ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
280         if (rc==DS_OK &&
281             (wfx.wFormatTag!=wfx2.wFormatTag ||
282              wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
283              wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
284              wfx.nChannels!=wfx2.nChannels)) {
285             trace("Requested format tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
286                   wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
287                   wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
288             trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
289                   wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
290                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
291         }
292 
293         ZeroMemory(&new_dsbcaps, sizeof(new_dsbcaps));
294         new_dsbcaps.dwSize = sizeof(new_dsbcaps);
295         rc=IDirectSoundBuffer_GetCaps(*dsbo,&new_dsbcaps);
296         ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %08x\n", rc);
297         if (rc==DS_OK && winetest_debug > 1) {
298             trace("    new Caps: flags=0x%08x size=%d\n",new_dsbcaps.dwFlags,
299                   new_dsbcaps.dwBufferBytes);
300         }
301 
302         /* Check for primary buffer size change */
303         ok(new_dsbcaps.dwBufferBytes == dsbcaps.dwBufferBytes,
304            "    buffer size changed after SetFormat() - "
305            "previous size was %u, current size is %u\n",
306            dsbcaps.dwBufferBytes, new_dsbcaps.dwBufferBytes);
307         dsbcaps.dwBufferBytes = new_dsbcaps.dwBufferBytes;
308 
309         /* Check for primary buffer flags change */
310         ok(new_dsbcaps.dwFlags == dsbcaps.dwFlags,
311            "    flags changed after SetFormat() - "
312            "previous flags were %08x, current flags are %08x\n",
313            dsbcaps.dwFlags, new_dsbcaps.dwFlags);
314 
315         /* Set the CooperativeLevel back to normal */
316         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
317         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
318         ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
319            "failed: %08x\n",rc);
320     }
321 
322     if (play) {
323         play_state_t state;
324         DS3DLISTENER listener_param;
325         LPDIRECTSOUND3DBUFFER buffer=NULL;
326         DS3DBUFFER buffer_param;
327         DWORD start_time,now;
328         LPVOID buffer1;
329         DWORD length1;
330 
331         if (winetest_interactive) {
332             trace("    Playing %g second 440Hz tone at %dx%dx%d\n", duration,
333                   wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
334         }
335 
336         if (is_primary) {
337             /* We must call SetCooperativeLevel to be allowed to call Lock */
338             /* DSOUND: Setting DirectSound cooperative level to
339              * DSSCL_WRITEPRIMARY */
340             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),
341                                                  DSSCL_WRITEPRIMARY);
342             ok(rc==DS_OK,
343                "IDirectSound8_SetCooperativeLevel(DSSCL_WRITEPRIMARY) failed: %08x\n",rc);
344             if (rc!=DS_OK)
345                 return;
346         }
347         if (buffer3d) {
348             LPDIRECTSOUNDBUFFER temp_buffer;
349 
350             rc=IDirectSoundBuffer_QueryInterface(*dsbo,&IID_IDirectSound3DBuffer,
351                                                  (LPVOID *)&buffer);
352             ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
353             if (rc!=DS_OK)
354                 return;
355 
356             /* check the COM interface */
357             rc=IDirectSoundBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
358                                                  (LPVOID *)&temp_buffer);
359             ok(rc==DS_OK && temp_buffer!=NULL,
360                "IDirectSoundBuffer_QueryInterface() failed: %08x\n", rc);
361             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
362                temp_buffer,*dsbo);
363             ref=IDirectSoundBuffer_Release(temp_buffer);
364             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
365                "should have 1\n",ref);
366 
367             temp_buffer=NULL;
368             rc=IDirectSound3DBuffer_QueryInterface(*dsbo, &IID_IDirectSoundBuffer,
369                                                    (LPVOID *)&temp_buffer);
370             ok(rc==DS_OK && temp_buffer!=NULL,
371                "IDirectSound3DBuffer_QueryInterface() failed: %08x\n", rc);
372             ok(temp_buffer==*dsbo,"COM interface broken: %p != %p\n",
373                temp_buffer,*dsbo);
374             ref=IDirectSoundBuffer_Release(temp_buffer);
375             ok(ref==1,"IDirectSoundBuffer_Release() has %d references, "
376                "should have 1\n",ref);
377 
378             ref=IDirectSoundBuffer_Release(*dsbo);
379             ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
380                "should have 0\n",ref);
381 
382             rc=IDirectSound3DBuffer_QueryInterface(buffer,
383                                                    &IID_IDirectSoundBuffer,
384                                                    (LPVOID *)dsbo);
385             ok(rc==DS_OK && *dsbo!=NULL,"IDirectSound3DBuffer_QueryInterface() "
386                "failed: %08x\n",rc);
387 
388             /* DSOUND: Error: Invalid buffer */
389             rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
390             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
391                "failed: %08x\n",rc);
392 
393             ZeroMemory(&buffer_param, sizeof(buffer_param));
394 
395             /* DSOUND: Error: Invalid buffer */
396             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
397             ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters() "
398                "failed: %08x\n",rc);
399 
400             buffer_param.dwSize=sizeof(buffer_param);
401             rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
402             ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters() failed: %08x\n", rc);
403         }
404         if (set_volume) {
405             if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
406                 LONG val;
407                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&val);
408                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
409 
410                 rc=IDirectSoundBuffer_SetVolume(*dsbo,volume);
411                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume() failed: %08x\n", rc);
412             } else {
413                 /* DSOUND: Error: Buffer does not have CTRLVOLUME */
414                 rc=IDirectSoundBuffer_GetVolume(*dsbo,&volume);
415                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetVolume() "
416                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
417             }
418         }
419 
420         if (set_pan) {
421             if (dsbcaps.dwFlags & DSBCAPS_CTRLPAN) {
422                 LONG val;
423                 rc=IDirectSoundBuffer_GetPan(*dsbo,&val);
424                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan() failed: %08x\n", rc);
425 
426                 rc=IDirectSoundBuffer_SetPan(*dsbo,pan);
427                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan() failed: %08x\n", rc);
428             } else {
429                 /* DSOUND: Error: Buffer does not have CTRLPAN */
430                 rc=IDirectSoundBuffer_GetPan(*dsbo,&pan);
431                 ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer_GetPan() "
432                    "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);
433             }
434         }
435 
436         /* try an offset past the end of the buffer */
437         rc = IDirectSoundBuffer_Lock(*dsbo, dsbcaps.dwBufferBytes, 0, &buffer1,
438                                       &length1, NULL, NULL,
439                                       DSBLOCK_ENTIREBUFFER);
440         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
441            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
442 
443         /* try a size larger than the buffer */
444         rc = IDirectSoundBuffer_Lock(*dsbo, 0, dsbcaps.dwBufferBytes + 1,
445                                      &buffer1, &length1, NULL, NULL,
446                                      DSBLOCK_FROMWRITECURSOR);
447         ok(rc==DSERR_INVALIDPARAM, "IDirectSoundBuffer_Lock() should have "
448            "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
449 
450         state.wave=wave_generate_la(&wfx,duration,&state.wave_len);
451 
452         state.dsbo=*dsbo;
453         state.wfx=&wfx;
454         state.buffer_size=dsbcaps.dwBufferBytes;
455         state.played=state.written=state.offset=0;
456         buffer_refill8(&state,state.buffer_size);
457 
458         rc=IDirectSoundBuffer_Play(*dsbo,0,0,DSBPLAY_LOOPING);
459         ok(rc==DS_OK,"IDirectSoundBuffer_Play() failed: %08x\n", rc);
460 
461         rc=IDirectSoundBuffer_GetStatus(*dsbo,&status);
462         ok(rc==DS_OK,"IDirectSoundBuffer_GetStatus() failed: %08x\n", rc);
463         ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
464            "GetStatus: bad status: %x\n",status);
465 
466         if (listener) {
467             ZeroMemory(&listener_param,sizeof(listener_param));
468             listener_param.dwSize=sizeof(listener_param);
469             rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
470             ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
471                "failed: %08x\n",rc);
472             if (move_listener) {
473                 listener_param.vPosition.x = -5.0f;
474                 listener_param.vVelocity.x = (float)(10.0/duration);
475             }
476             rc=IDirectSound3DListener_SetAllParameters(listener,
477                                                        &listener_param,
478                                                        DS3D_IMMEDIATE);
479             ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n", rc);
480         }
481         if (buffer3d) {
482             if (move_sound) {
483                 buffer_param.vPosition.x = 100.0f;
484                 buffer_param.vVelocity.x = (float)(-200.0/duration);
485             }
486             buffer_param.flMinDistance = 10;
487             rc=IDirectSound3DBuffer_SetAllParameters(buffer,&buffer_param,
488                                                      DS3D_IMMEDIATE);
489             ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
490         }
491 
492         start_time=GetTickCount();
493         while (buffer_service8(&state)) {
494             WaitForSingleObject(GetCurrentProcess(),TIME_SLICE);
495             now=GetTickCount();
496             if (listener && move_listener) {
497                 listener_param.vPosition.x = (float)(-5.0+10.0*(now-start_time)/1000/duration);
498                 if (winetest_debug>2)
499                     trace("listener position=%g\n",listener_param.vPosition.x);
500                 rc=IDirectSound3DListener_SetPosition(listener,
501                     listener_param.vPosition.x,listener_param.vPosition.y,
502                     listener_param.vPosition.z,DS3D_IMMEDIATE);
503                 ok(rc==DS_OK,"IDirectSound3dListener_SetPosition() failed: %08x\n",rc);
504             }
505             if (buffer3d && move_sound) {
506                 buffer_param.vPosition.x = (float)(100-200.0*(now-start_time)/1000/duration);
507                 if (winetest_debug>2)
508                     trace("sound position=%g\n",buffer_param.vPosition.x);
509                 rc=IDirectSound3DBuffer_SetPosition(buffer,
510                     buffer_param.vPosition.x,buffer_param.vPosition.y,
511                     buffer_param.vPosition.z,DS3D_IMMEDIATE);
512                 ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition() failed: %08x\n", rc);
513             }
514         }
515         /* Check the sound duration was within 10% of the expected value */
516         now=GetTickCount();
517         ok(fabs(1000*duration-now+start_time)<=100*duration,
518            "The sound played for %d ms instead of %g ms\n",
519            now-start_time,1000*duration);
520 
521         free(state.wave);
522         if (is_primary) {
523             /* Set the CooperativeLevel back to normal */
524             /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
525             rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
526             ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) "
527                "failed: %08x\n",rc);
528         }
529         if (buffer3d) {
530             ref=IDirectSound3DBuffer_Release(buffer);
531             ok(ref==0,"IDirectSound3DBuffer_Release() has %d references, "
532                "should have 0\n",ref);
533         }
534     }
535 }
536 
537 static HRESULT test_secondary8(LPGUID lpGuid, int play,
538                                int has_3d, int has_3dbuffer,
539                                int has_listener, int has_duplicate,
540                                int move_listener, int move_sound)
541 {
542     HRESULT rc;
543     LPDIRECTSOUND8 dso=NULL;
544     LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
545     LPDIRECTSOUND3DLISTENER listener=NULL;
546     DSBUFFERDESC bufdesc;
547     WAVEFORMATEX wfx, wfx1;
548     int ref;
549 
550     /* Create the DirectSound object */
551     rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
552     ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n", rc);
553     if (rc!=DS_OK)
554         return rc;
555 
556     /* We must call SetCooperativeLevel before creating primary buffer */
557     /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
558     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
559     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_PRIORITY) failed: %08x\n",rc);
560     if (rc!=DS_OK)
561         goto EXIT;
562 
563     ZeroMemory(&bufdesc, sizeof(bufdesc));
564     bufdesc.dwSize=sizeof(bufdesc);
565     bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
566     if (has_3d)
567         bufdesc.dwFlags|=DSBCAPS_CTRL3D;
568     else
569         bufdesc.dwFlags|=(DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
570     rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
571     ok((rc==DS_OK && primary!=NULL) || (rc == DSERR_CONTROLUNAVAIL),
572        "IDirectSound8_CreateSoundBuffer() failed to create a %sprimary buffer: %08x\n",has_3d?"3D ":"", rc);
573     if (rc == DSERR_CONTROLUNAVAIL)
574         trace("  No Primary\n");
575     else if (rc==DS_OK && primary!=NULL) {
576         rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
577         ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
578         if (rc!=DS_OK)
579             goto EXIT1;
580 
581         if (has_listener) {
582             rc=IDirectSoundBuffer_QueryInterface(primary,
583                                                  &IID_IDirectSound3DListener,
584                                                  (void **)&listener);
585             ok(rc==DS_OK && listener!=NULL,
586                "IDirectSoundBuffer_QueryInterface() failed to get a 3D "
587                "listener %08x\n",rc);
588             ref=IDirectSoundBuffer_Release(primary);
589             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
590                "should have 0\n",ref);
591             if (rc==DS_OK && listener!=NULL) {
592                 DS3DLISTENER listener_param;
593                 ZeroMemory(&listener_param,sizeof(listener_param));
594                 /* DSOUND: Error: Invalid buffer */
595                 rc=IDirectSound3DListener_GetAllParameters(listener,0);
596                 ok(rc==DSERR_INVALIDPARAM,
597                    "IDirectSound3dListener_GetAllParameters() should have "
598                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
599 
600                 /* DSOUND: Error: Invalid buffer */
601                 rc=IDirectSound3DListener_GetAllParameters(listener,
602                                                            &listener_param);
603                 ok(rc==DSERR_INVALIDPARAM,
604                    "IDirectSound3dListener_GetAllParameters() should have "
605                    "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
606 
607                 listener_param.dwSize=sizeof(listener_param);
608                 rc=IDirectSound3DListener_GetAllParameters(listener,
609                                                            &listener_param);
610                 ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters() "
611                    "failed: %08x\n",rc);
612             } else {
613                 ok(listener==NULL, "IDirectSoundBuffer_QueryInterface() "
614                    "failed but returned a listener anyway\n");
615                 ok(rc!=DS_OK, "IDirectSoundBuffer_QueryInterface() succeeded "
616                    "but returned a NULL listener\n");
617                 if (listener) {
618                     ref=IDirectSound3DListener_Release(listener);
619                     ok(ref==0,"IDirectSound3dListener_Release() listener has "
620                        "%d references, should have 0\n",ref);
621                 }
622                 goto EXIT2;
623             }
624         }
625 
626         init_format(&wfx,WAVE_FORMAT_PCM,22050,16,2);
627         secondary=NULL;
628         ZeroMemory(&bufdesc, sizeof(bufdesc));
629         bufdesc.dwSize=sizeof(bufdesc);
630         bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
631         if (has_3d)
632             bufdesc.dwFlags|=DSBCAPS_CTRL3D;
633         else
634             bufdesc.dwFlags|=
635                 (DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN);
636         bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
637                                     wfx.nBlockAlign);
638         bufdesc.lpwfxFormat=&wfx;
639         if (has_3d) {
640             /* a stereo 3D buffer should fail */
641             rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
642             ok(rc==DSERR_INVALIDPARAM,
643                "IDirectSound8_CreateSoundBuffer(secondary) should have "
644                "returned DSERR_INVALIDPARAM, returned %08x\n", rc);
645             if (secondary)
646                 ref=IDirectSoundBuffer_Release(secondary);
647             init_format(&wfx,WAVE_FORMAT_PCM,22050,16,1);
648         }
649 
650         if (winetest_interactive) {
651             trace("  Testing a %s%ssecondary buffer %s%s%s%sat %dx%dx%d "
652                   "with a primary buffer at %dx%dx%d\n",
653                   has_3dbuffer?"3D ":"",
654                   has_duplicate?"duplicated ":"",
655                   listener!=NULL||move_sound?"with ":"",
656                   move_listener?"moving ":"",
657                   listener!=NULL?"listener ":"",
658                   listener&&move_sound?"and moving sound ":move_sound?
659                   "moving sound ":"",
660                   wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
661                   wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
662         }
663         rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
664         ok(rc==DS_OK && secondary!=NULL,"IDirectSound8_CreateSoundBuffer() "
665            "failed to create a %s%ssecondary buffer %s%s%s%sat %dx%dx%d (%s): %08x\n",
666            has_3dbuffer?"3D ":"", has_duplicate?"duplicated ":"",
667            listener!=NULL||move_sound?"with ":"", move_listener?"moving ":"",
668            listener!=NULL?"listener ":"",
669            listener&&move_sound?"and moving sound ":move_sound?
670            "moving sound ":"",
671            wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,
672            getDSBCAPS(bufdesc.dwFlags),rc);
673         if (rc==DS_OK && secondary!=NULL) {
674             if (!has_3d) {
675                 LONG refvol,vol,refpan,pan;
676 
677                 /* Check the initial secondary buffer's volume and pan */
678                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
679                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(secondary) failed: %08x\n",rc);
680                 ok(vol==0,"wrong volume for a new secondary buffer: %d\n",vol);
681                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
682                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(secondary) failed: %08x\n",rc);
683                 ok(pan==0,"wrong pan for a new secondary buffer: %d\n",pan);
684 
685                 /* Check that changing the secondary buffer's volume and pan
686                  * does not impact the primary buffer's volume and pan
687                  */
688                 rc=IDirectSoundBuffer_GetVolume(primary,&refvol);
689                 ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume(primary) failed: %08x\n",rc);
690                 rc=IDirectSoundBuffer_GetPan(primary,&refpan);
691                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
692 
693                 rc=IDirectSoundBuffer_SetVolume(secondary,-1000);
694                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
695                 rc=IDirectSoundBuffer_GetVolume(secondary,&vol);
696                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
697                 ok(vol==-1000,"secondary: wrong volume %d instead of -1000\n",
698                    vol);
699                 rc=IDirectSoundBuffer_SetPan(secondary,-1000);
700                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
701                 rc=IDirectSoundBuffer_GetPan(secondary,&pan);
702                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
703                 ok(pan==-1000,"secondary: wrong pan %d instead of -1000\n",
704                    pan);
705 
706                 rc=IDirectSoundBuffer_GetVolume(primary,&vol);
707                 ok(rc==DS_OK,"IDirectSoundBuffer_`GetVolume(primary) failed: i%08x\n",rc);
708                 ok(vol==refvol,"The primary volume changed from %d to %d\n",
709                    refvol,vol);
710                 rc=IDirectSoundBuffer_GetPan(primary,&pan);
711                 ok(rc==DS_OK,"IDirectSoundBuffer_GetPan(primary) failed: %08x\n",rc);
712                 ok(pan==refpan,"The primary pan changed from %d to %d\n",
713                    refpan,pan);
714 
715                 rc=IDirectSoundBuffer_SetVolume(secondary,0);
716                 ok(rc==DS_OK,"IDirectSoundBuffer_SetVolume(secondary) failed: %08x\n",rc);
717                 rc=IDirectSoundBuffer_SetPan(secondary,0);
718                 ok(rc==DS_OK,"IDirectSoundBuffer_SetPan(secondary) failed: %08x\n",rc);
719             }
720             if (has_duplicate) {
721                 LPDIRECTSOUNDBUFFER duplicated=NULL;
722 
723                 /* DSOUND: Error: Invalid source buffer */
724                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,0);
725                 ok(rc==DSERR_INVALIDPARAM,
726                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
727                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
728 
729                 /* DSOUND: Error: Invalid dest buffer */
730                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,0);
731                 ok(rc==DSERR_INVALIDPARAM,
732                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
733                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
734 
735                 /* DSOUND: Error: Invalid source buffer */
736                 rc=IDirectSound8_DuplicateSoundBuffer(dso,0,&duplicated);
737                 ok(rc==DSERR_INVALIDPARAM,
738                    "IDirectSound8_DuplicateSoundBuffer() should have returned "
739                    "DSERR_INVALIDPARAM, returned: %08x\n",rc);
740 
741                 duplicated=NULL;
742                 rc=IDirectSound8_DuplicateSoundBuffer(dso,secondary,
743                                                       &duplicated);
744                 ok(rc==DS_OK && duplicated!=NULL,
745                    "IDirectSound8_DuplicateSoundBuffer() failed to duplicate "
746                    "a secondary buffer: %08x\n",rc);
747 
748                 if (rc==DS_OK && duplicated!=NULL) {
749                     ref=IDirectSoundBuffer_Release(secondary);
750                     ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d "
751                        "references, should have 0\n",ref);
752                     secondary=duplicated;
753                 }
754             }
755 
756             if (rc==DS_OK && secondary!=NULL) {
757                 double duration;
758                 duration=(move_listener || move_sound?4.0:1.0);
759                 test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0,
760                              winetest_interactive,duration,has_3dbuffer,
761                              listener,move_listener,move_sound);
762                 ref=IDirectSoundBuffer_Release(secondary);
763                 ok(ref==0,"IDirectSoundBuffer_Release() %s has %d references, "
764                    "should have 0\n",has_duplicate?"duplicated":"secondary",
765                    ref);
766             }
767         }
768 EXIT1:
769         if (has_listener) {
770             ref=IDirectSound3DListener_Release(listener);
771             ok(ref==0,"IDirectSound3dListener_Release() listener has %d "
772                "references, should have 0\n",ref);
773         } else {
774             ref=IDirectSoundBuffer_Release(primary);
775             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
776                "should have 0\n",ref);
777         }
778     } else {
779         ok(primary==NULL,"IDirectSound8_CreateSoundBuffer(primary) failed "
780            "but primary created anyway\n");
781         ok(rc!=DS_OK,"IDirectSound8_CreateSoundBuffer(primary) succeeded "
782            "but primary not created\n");
783         if (primary) {
784             ref=IDirectSoundBuffer_Release(primary);
785             ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
786                "should have 0\n",ref);
787         }
788     }
789 EXIT2:
790     /* Set the CooperativeLevel back to normal */
791     /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
792     rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
793     ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel(DSSCL_NORMAL) failed: %08x\n",rc);
794 
795 EXIT:
796     ref=IDirectSound8_Release(dso);
797     ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
798     if (ref!=0)
799         return DSERR_GENERIC;
800 
801     return rc;
802 }
803 
804 static HRESULT test_for_driver8(LPGUID lpGuid)
805 {
806     HRESULT rc;
807     LPDIRECTSOUND8 dso=NULL;
808     int ref;
80