Robert Reif wrote:


Only the primary buffer supports hardware acceleration.  The secondary
buffer(s) are implemented in software and mixed into the primary buffer.
The formats (mono/stereo, 8/16 bit samples, and sample rate) of the
primary and secondary buffers are totally independent and can be anything.

One of the dsound tests keeps the primary buffer format constant and
iterates through all secondary buffer formats and another keeps the
secondary buffer format constant and iterates through all possible
primary formats.

This is probably what you are seeing.  The secondary buffer format
has nothing to do with what is sent to the hardware.


The first test that fails with the ALSA driver is the so-called "reference" tone, which, as far as I could see, is played with a primary buffer, and no secondary buffer. The reference tone uses the hardware position directly, which wraps around at a buffer size that changes unexpectedly when switching playback formats. I have prepared a patch that "fixes" this, by re-querying the buffer size in the case of a primary buffer, and displaying a warning if it detects a buffer size change. However, I don't know if the buffer size is supposed to remain constant across buffer format changes. If it does, then the patch would need to be modified to mark this as a TODO.

Changelog:
* Re-query buffer capabilities after format change, and display warning if buffer size changed after format change. Fixes reference playback with ALSA.

diff -uN wine-20050725-cvs/dlls/dsound/tests/ds3d8.c wine-20050725-cvs-patch/dlls/dsound/tests/ds3d8.c
--- wine-20050725-cvs/dlls/dsound/tests/ds3d8.c	2005-06-20 09:18:04.000000000 -0500
+++ wine-20050725-cvs-patch/dlls/dsound/tests/ds3d8.c	2005-08-13 11:35:55.000000000 -0500
@@ -254,6 +254,8 @@
     ok(status==0,"status=0x%lx instead of 0\n",status);
 
     if (is_primary) {
+        DWORD previous_buffer_size;
+    
         /* We must call SetCooperativeLevel to be allowed to call SetFormat */
         /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
@@ -292,6 +294,29 @@
                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
         }
 
+        /* Not all sound implementations guarantee that the buffer size will remain 
+           unchanged after a successful SetFormat() call. For example, ALSA is known
+           to change buffer sizes when requested to change sound format. So the 
+           buffer capabilities are re-queried in order to play the samples correctly.
+           
+           TODO: is this a Windows DirectSound requirement? (bufsize constant across
+           format changes)
+         */
+        previous_buffer_size = dsbcaps.dwBufferBytes;
+        dsbcaps.dwSize=sizeof(dsbcaps);
+        rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
+        ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %s\n",
+           DXGetErrorString8(rc));
+        if (rc==DS_OK && winetest_debug > 1) {
+            trace("    Caps (again): flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
+                  dsbcaps.dwBufferBytes);
+        }
+        /* should the following check be marked as a TODO? */
+        if (previous_buffer_size != dsbcaps.dwBufferBytes) {
+            trace("    buffer size changed after SetFormat() - previous size is %lu, current size is %lu\n",
+                previous_buffer_size, dsbcaps.dwBufferBytes);
+        }
+
         /* Set the CooperativeLevel back to normal */
         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
         rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
diff -uN wine-20050725-cvs/dlls/dsound/tests/ds3d.c wine-20050725-cvs-patch/dlls/dsound/tests/ds3d.c
--- wine-20050725-cvs/dlls/dsound/tests/ds3d.c	2005-07-15 13:36:52.000000000 -0500
+++ wine-20050725-cvs-patch/dlls/dsound/tests/ds3d.c	2005-08-12 20:53:54.000000000 -0500
@@ -362,6 +362,8 @@
     ok(status==0,"status=0x%lx instead of 0\n",status);
 
     if (is_primary) {
+        DWORD previous_buffer_size;
+    
         /* 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);
@@ -400,6 +402,29 @@
                   wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
         }
 
+        /* Not all sound implementations guarantee that the buffer size will remain 
+           unchanged after a successful SetFormat() call. For example, ALSA is known
+           to change buffer sizes when requested to change sound format. So the 
+           buffer capabilities are re-queried in order to play the samples correctly.
+           
+           TODO: is this a Windows DirectSound requirement? (bufsize constant across
+           format changes)
+         */
+        previous_buffer_size = dsbcaps.dwBufferBytes;
+        dsbcaps.dwSize=sizeof(dsbcaps);
+        rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
+        ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() failed: %s\n",
+           DXGetErrorString8(rc));
+        if (rc==DS_OK && winetest_debug > 1) {
+            trace("    Caps (again): flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
+                  dsbcaps.dwBufferBytes);
+        }
+        /* should the following check be marked as a TODO? */
+        if (previous_buffer_size != dsbcaps.dwBufferBytes) {
+            trace("    buffer size changed after SetFormat() - previous size is %lu, current size is %lu\n",
+                previous_buffer_size, dsbcaps.dwBufferBytes);
+        }
+        
         /* Set the CooperativeLevel back to normal */
         /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
         rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);

Reply via email to