dsound mixer speedup

Robert Reif reif at earthlink.net
Wed Aug 11 23:24:20 CDT 2004


Speed up mixing and unmixing by moving sample size and buffer
wrap tests to outside the loop.  The code is not as compact or pretty
but it should be faster.
-------------- next part --------------
Index: dlls/dsound/mixer.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/mixer.c,v
retrieving revision 1.22
diff -u -r1.22 mixer.c
--- dlls/dsound/mixer.c	2 Aug 2004 18:47:09 -0000	1.22
+++ dlls/dsound/mixer.c	12 Aug 2004 04:18:15 -0000
@@ -387,10 +387,8 @@
 
 static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen)
 {
-	INT	i, len, ilen, temp, field, nBlockAlign;
-	INT	advance = dsb->dsound->wfx.wBitsPerSample >> 3;
-	BYTE	*buf, *ibuf, *obuf;
-	INT16	*ibufs, *obufs;
+	INT	i, len, ilen, temp, field, nBlockAlign, todo;
+	BYTE	*buf, *ibuf;
 
 	TRACE("(%p,%ld,%ld)\n",dsb,writepos,fraglen);
 
@@ -423,31 +421,70 @@
 	    (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
 		DSOUND_MixerVol(dsb, ibuf, len);
 
-	obuf = dsb->dsound->buffer + writepos;
-	for (i = 0; i < len; i += advance) {
-		obufs = (INT16 *) obuf;
-		ibufs = (INT16 *) ibuf;
-		if (dsb->dsound->wfx.wBitsPerSample == 8) {
+	if (dsb->dsound->wfx.wBitsPerSample == 8) {
+		BYTE	*obuf = dsb->dsound->buffer + writepos;
+
+		if ((writepos + len) <= dsb->dsound->buflen)
+			todo = len;
+		else
+			todo = dsb->dsound->buflen - writepos;
+
+		for (i = 0; i < todo; i++) {
 			/* 8-bit WAV is unsigned */
-			field = (*ibuf - 128);
+			field = (*ibuf++ - 128);
 			field += (*obuf - 128);
-			field = field > 127 ? 127 : field;
-			field = field < -128 ? -128 : field;
-			*obuf = field + 128;
-		} else {
+			if (field > 127) field = 127;
+			else if (field < -128) field = -128;
+			*obuf++ = field + 128;
+		}
+ 
+		if (todo < len) {
+			todo = len - todo;
+			obuf = dsb->dsound->buffer;
+
+			for (i = 0; i < todo; i++) {
+				/* 8-bit WAV is unsigned */
+				field = (*ibuf++ - 128);
+				field += (*obuf - 128);
+				if (field > 127) field = 127;
+				else if (field < -128) field = -128;
+				*obuf++ = field + 128;
+			}
+		}
+        } else {
+		INT16	*ibufs, *obufs;
+
+		ibufs = (INT16 *) ibuf;
+		obufs = (INT16 *)(dsb->dsound->buffer + writepos);
+
+		if ((writepos + len) <= dsb->dsound->buflen)
+			todo = len / 2;
+		else
+			todo = (dsb->dsound->buflen - writepos) / 2;
+
+		for (i = 0; i < todo; i++) {
 			/* 16-bit WAV is signed */
-			field = *ibufs;
+			field = *ibufs++;
 			field += *obufs;
-			field = field > 32767 ? 32767 : field;
-			field = field < -32768 ? -32768 : field;
-			*obufs = field;
-		}
-		ibuf += advance;
-		obuf += advance;
-		if (obuf >= (BYTE *)(dsb->dsound->buffer + dsb->dsound->buflen))
-			obuf = dsb->dsound->buffer;
-	}
-	/* free(buf); */
+			if (field > 32767) field = 32767;
+			else if (field < -32768) field = -32768;
+			*obufs++ = field;
+		}
+
+		if (todo < (len / 2)) {
+			todo = (len / 2) - todo;
+			obufs = (INT16 *)dsb->dsound->buffer;
+
+			for (i = 0; i < todo; i++) {
+				/* 16-bit WAV is signed */
+				field = *ibufs++;
+				field += *obufs;
+				if (field > 32767) field = 32767;
+				else if (field < -32768) field = -32768;
+				*obufs++ = field;
+			}
+		}
+        }
 
 	if (dsb->leadin && (dsb->startpos > dsb->buf_mixpos) && (dsb->startpos <= dsb->buf_mixpos + ilen)) {
 		/* HACK... leadin should be reset when the PLAY position reaches the startpos,
@@ -474,10 +511,9 @@
 
 static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len)
 {
-	INT     i, ilen, field, nBlockAlign;
-	INT     advance = dsb->dsound->wfx.wBitsPerSample >> 3;
-	BYTE	*buf, *ibuf, *obuf;
-	INT16	*ibufs, *obufs;
+	INT     i, ilen, field, nBlockAlign, todo;
+	BYTE	*buf, *ibuf;
+
 	TRACE("(%p,%ld,%ld)\n",dsb,writepos,len);
 
 	nBlockAlign = dsb->dsound->wfx.nBlockAlign;
@@ -496,31 +532,70 @@
 		DSOUND_MixerVol(dsb, ibuf, len);
 
 	/* subtract instead of add, to phase out premixed data */
-	obuf = dsb->dsound->buffer + writepos;
-	for (i = 0; i < len; i += advance) {
-		obufs = (INT16 *) obuf;
-		ibufs = (INT16 *) ibuf;
-		if (dsb->dsound->wfx.wBitsPerSample == 8) {
+	if (dsb->dsound->wfx.wBitsPerSample == 8) {
+		BYTE	*obuf = dsb->dsound->buffer + writepos;
+
+		if ((writepos + len) <= dsb->dsound->buflen)
+			todo = len;
+		else
+			todo = dsb->dsound->buflen - writepos;
+
+		for (i = 0; i < todo; i++) {
 			/* 8-bit WAV is unsigned */
-			field = (*ibuf - 128);
+			field = (*ibuf++ - 128);
 			field -= (*obuf - 128);
-			field = field > 127 ? 127 : field;
-			field = field < -128 ? -128 : field;
-			*obuf = field + 128;
-		} else {
+			if (field > 127) field = 127;
+			else if (field < -128) field = -128;
+			*obuf++ = field + 128;
+		}
+ 
+		if (todo < len) {
+			todo = len - todo;
+			obuf = dsb->dsound->buffer;
+
+			for (i = 0; i < todo; i++) {
+				/* 8-bit WAV is unsigned */
+				field = (*ibuf++ - 128);
+				field -= (*obuf - 128);
+				if (field > 127) field = 127;
+				else if (field < -128) field = -128;
+				*obuf++ = field + 128;
+			}
+		}
+        } else {
+		INT16	*ibufs, *obufs;
+
+		ibufs = (INT16 *) ibuf;
+		obufs = (INT16 *)(dsb->dsound->buffer + writepos);
+
+		if ((writepos + len) <= dsb->dsound->buflen)
+			todo = len / 2;
+		else
+			todo = (dsb->dsound->buflen - writepos) / 2;
+
+		for (i = 0; i < todo; i++) {
 			/* 16-bit WAV is signed */
-			field = *ibufs;
+			field = *ibufs++;
 			field -= *obufs;
-			field = field > 32767 ? 32767 : field;
-			field = field < -32768 ? -32768 : field;
-			*obufs = field;
-		}
-		ibuf += advance;
-		obuf += advance;
-		if (obuf >= (BYTE *)(dsb->dsound->buffer + dsb->dsound->buflen))
-			obuf = dsb->dsound->buffer;
-	}
-	/* free(buf); */
+			if (field > 32767) field = 32767;
+			else if (field < -32768) field = -32768;
+			*obufs++ = field;
+		}
+
+		if (todo < (len / 2)) {
+			todo = (len / 2) - todo;
+			obufs = (INT16 *)dsb->dsound->buffer;
+
+			for (i = 0; i < todo; i++) {
+				/* 16-bit WAV is signed */
+				field = *ibufs++;
+				field -= *obufs;
+				if (field > 32767) field = 32767;
+				else if (field < -32768) field = -32768;
+				*obufs++ = field;
+			}
+		}
+        }
 }
 
 static void DSOUND_MixCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, BOOL cancel)


More information about the wine-patches mailing list