DSOUND: another buffer underrun patch

Jerry Jenkins Jerry_J_Jenkins at hotmail.com
Sat Apr 5 08:57:58 CST 2003


Align data to IDirectSoundBufferImpl.wfx.nBlockAlign instead of 4 bytes. 
If the size of primary buffer is 22050 bytes, the last two bytes won't 
be mixed, because 22050 % 4 != 0.

With this patch, another problem of winealsa appears. WINAMP halts when 
it try to play another file when a file is played or on demand. The 
reason is that WINAMP creates the dsound buffer and setups the callback 
function in a thread, but plays the buffer in another one. Although I am 
not sure if it is a bug of WINE or ALSA, we can work around it by moving 
the code that adds the callback from DSDB_CreateMMAP to 
IDsDriverBufferImpl_Play.

Since the winealsa implement a fake HAL support - a callback will 
transfer data from primary buffer to sound driver every time it is 
called, expect incorrect results in some cases.

ChangeLog:
	*dlls/dsound/mixer.c
	- Align data to proper size.
-------------- next part --------------
Index: dlls/dsound/mixer.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/mixer.c,v
retrieving revision 1.10
diff -u -r1.10 mixer.c
--- dlls/dsound/mixer.c	17 Mar 2003 21:23:12 -0000	1.10
+++ dlls/dsound/mixer.c	5 Apr 2003 14:29:36 -0000
@@ -316,7 +316,7 @@
 
 static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
 {
-	INT	i, len, ilen, temp, field;
+	INT	i, len, ilen, temp, field, nBlockAlign;
 	INT	advance = dsb->dsound->wfx.wBitsPerSample >> 3;
 	BYTE	*buf, *ibuf, *obuf;
 	INT16	*ibufs, *obufs;
@@ -329,10 +329,11 @@
 			dsb->nAvgBytesPerSec);
 		len = (len > temp) ? temp : len;
 	}
-	len &= ~3;				/* 4 byte alignment */
+	nBlockAlign = dsb->dsound->wfx.nBlockAlign;
+	len = len / nBlockAlign * nBlockAlign;	/* data alignment */
 
 	if (len == 0) {
-		/* This should only happen if we aren't looping and temp < 4 */
+		/* This should only happen if we aren't looping and temp < nBlockAlign */
 		return 0;
 	}
 
@@ -399,12 +400,13 @@
 
 static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len)
 {
-	INT     i, ilen, field;
+	INT     i, ilen, field, nBlockAlign;
 	INT     advance = dsb->dsound->wfx.wBitsPerSample >> 3;
 	BYTE	*buf, *ibuf, *obuf;
 	INT16	*ibufs, *obufs;
 
-	len &= ~3;				/* 4 byte alignment */
+	nBlockAlign = dsb->dsound->wfx.nBlockAlign;
+	len = len / nBlockAlign * nBlockAlign;  /* data alignment */
 
 	TRACE("allocating buffer (size = %ld)\n", len);
 	if ((buf = ibuf = (BYTE *) DSOUND_tmpbuffer(len)) == NULL)


More information about the wine-patches mailing list