configurable dsound + small optimization

Joris Beugnies joris.beugnies at pandora.be
Fri May 10 12:36:58 CDT 2002


Since multiple games need different compile flags (eg DS_EMULDRIVER) in 
order to get sound and because diffrent distributions even use diffrent 
default values. I thought making these configurable would make life 
easier (especialy for those using binary distributions)
it alows for a section in the config file

[dsound] or [AppDefaults\\stupidgame.exe\\dsound]
"EmulDriver" = "1"
"HELmargin" = "5"
"HELqueue" = "5"
"SndQueueMax" = "28"
"SndQueueMin" = "12"

also get_field and set_field were merged and slightly optimized
-------------- next part --------------
--- wine/dlls/dsound/dsound_main.orig	Thu May  9 14:42:03 2002
+++ wine/dlls/dsound/dsound_main.c	Fri May 10 19:23:10 2002
@@ -51,12 +51,15 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
+#include "winuser.h"
 #include "wingdi.h"
 #include "winuser.h"
 #include "winerror.h"
 #include "mmsystem.h"
 #include "mmddk.h"
 #include "wine/windef16.h"
+#include "wine/winbase16.h"
 #include "wine/debug.h"
 #include "dsound.h"
 #include "dsdriver.h"
@@ -93,6 +96,7 @@
 typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
 typedef struct IKsPropertySetImpl IKsPropertySetImpl;
 
+
 /*****************************************************************************
  * IDirectSound implementation structure
  */
@@ -278,6 +282,98 @@
 	}
 }
 
+static int	ds_emuldriver = DS_EMULDRIVER;
+static int	ds_hel_margin = DS_HEL_MARGIN;
+static int	ds_hel_queue = DS_HEL_QUEUE;
+static int	ds_snd_queue_max = DS_SND_QUEUE_MAX;
+static int	ds_snd_queue_min = DS_SND_QUEUE_MIN;
+
+/*
+ * Get a config key from either the app-specific or the default config
+ */
+
+inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
+                                    char *buffer, DWORD size )
+{
+    if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0;
+    return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
+}
+
+
+/*
+ * Setup the dsound options.
+ */
+
+inline static void setup_dsound_options(void)
+{
+    char buffer[MAX_PATH+1];
+    HKEY hkey, appkey = 0;
+    
+    buffer[MAX_PATH]='\0';
+    
+    if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\dsound", 0, NULL,
+                         REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
+    {
+        ERR("Cannot create config registry key\n" );
+        ExitProcess(1);
+    }
+
+    if (GetModuleFileName16( GetCurrentTask(), buffer, MAX_PATH ) ||
+        GetModuleFileNameA( 0, buffer, MAX_PATH ))
+    {
+        HKEY tmpkey;
+
+        if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey ))
+        {
+	    char appname[MAX_PATH+16];
+	    char *p = strrchr( buffer, '\\' );
+	    if (p!=NULL) {
+	    	    appname[MAX_PATH]='\0';
+	    	    strncpy(appname,p+1,MAX_PATH);
+		    strcat(appname,"\\dsound");
+		    TRACE("appname = [%s] \n",appname);
+		    if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
+            		RegCloseKey( tmpkey );
+	    }
+        }
+    }
+
+    /* get options */
+
+    if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH )) 
+        ds_emuldriver = atoi(buffer);
+ 
+    if (!get_config_key( hkey, appkey, "HELmargin", buffer, MAX_PATH )) 
+        ds_hel_margin = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "HELqueue", buffer, MAX_PATH ))
+        ds_hel_queue = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
+        ds_snd_queue_max = atoi(buffer);
+
+    if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
+        ds_snd_queue_min = atoi(buffer);
+
+    if (appkey) RegCloseKey( appkey );
+    RegCloseKey( hkey );
+
+    if (ds_emuldriver != DS_EMULDRIVER )
+	WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER);
+    if (ds_hel_margin != DS_HEL_MARGIN ) 
+	WARN("ds_hel_margin = %d (default=%d)\n",ds_hel_margin, DS_HEL_MARGIN );
+    if (ds_hel_queue != DS_HEL_QUEUE )
+    	WARN("ds_hel_queue = %d (default=%d)\n",ds_hel_queue, DS_HEL_QUEUE );          
+    if (ds_snd_queue_max != DS_SND_QUEUE_MAX)
+	WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX);
+    if (ds_snd_queue_min != DS_SND_QUEUE_MIN)
+	WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN);
+
+}
+
+
+
+
 /***************************************************************************
  * DirectSoundEnumerateA [DSOUND.2]  
  *
@@ -1508,7 +1604,7 @@
 	/* detect buffer underrun */
 	if (pwrite < pplay) pwrite += primarybuf->buflen; /* wraparound */
 	pwrite -= pplay;
-	if (pmix > (DS_SND_QUEUE_MAX * primarybuf->dsound->fraglen + pwrite + primarybuf->writelead)) {
+	if (pmix > (ds_snd_queue_max * primarybuf->dsound->fraglen + pwrite + primarybuf->writelead)) {
 		WARN("detected an underrun: primary queue was %ld\n",pmix);
 		pmix = 0;
 	}
@@ -1555,7 +1651,7 @@
 		if (writepos) {
 			/* the writepos should only be used by apps with WRITEPRIMARY priority,
 			 * in which case our software mixer is disabled anyway */
-			*writepos = (This->dsound->pwplay + DS_HEL_MARGIN) * This->dsound->fraglen;
+			*writepos = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
 			while (*writepos >= This->buflen)
 				*writepos -= This->buflen;
 		}
@@ -1593,7 +1689,7 @@
 				 * behind write cursor, hmm... */
 				/* let's just do what might work for Half-Life */
 				DWORD wp;
-				wp = (This->dsound->pwplay + DS_HEL_MARGIN) * This->dsound->fraglen;
+				wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
 				while (wp >= primarybuf->buflen)
 					wp -= primarybuf->buflen;
 				*playpos = DSOUND_CalcPlayPosition(This, pstate, wp, pwrite, lplay, splay);
@@ -2602,75 +2698,66 @@
 }
 
 
-/* We should be able to optimize these two inline functions */
-/* so that we aren't doing 8->16->8 conversions when it is */
-/* not necessary. But this is still a WIP. Optimize later. */
-static inline void get_fields(const IDirectSoundBufferImpl *dsb, BYTE *buf, INT *fl, INT *fr)
-{
-	INT16	*bufs = (INT16 *) buf;
-
-	/* TRACE("(%p)\n", buf); */
-	if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 2) {
-		*fl = cvtU8toS16(*buf);
-		*fr = cvtU8toS16(*(buf + 1));
-		return;
-	}
-
-	if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 2) {
-		*fl = *bufs;
-		*fr = *(bufs + 1);
-		return;
-	}
-
-	if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 1) {
-		*fl = cvtU8toS16(*buf);
-		*fr = *fl;
-		return;
-	}
-
-	if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 1) {
-		*fl = *bufs;
-		*fr = *bufs;
-		return;
-	}
-
-	FIXME("get_fields found an unsupported configuration\n");
-	return;
-}
-
-static inline void set_fields(BYTE *buf, INT fl, INT fr)
+static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf )
 {
-	INT16 *bufs = (INT16 *) buf;
-
-	if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 2)) {
-		*buf = cvtS16toU8(fl);
-		*(buf + 1) = cvtS16toU8(fr);
-		return;
-	}
-
-	if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 2)) {
-		*bufs = fl;
-		*(bufs + 1) = fr;
-		return;
-	}
-
-	if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 1)) {
-		*buf = cvtS16toU8((fl + fr) >> 1);
-		return;
+	INT 	fl,fr;
+	if (dsb->wfx.nChannels == 2) {
+		if (dsb->wfx.wBitsPerSample == 8)  {
+			/* avoid needless 8->16->8 conversion */
+			if ( (primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 2) ) {
+				*obuf=*ibuf;
+				*(obuf+1)=*(ibuf+1);
+				return;
+			}
+			fl = cvtU8toS16(*ibuf);
+			fr = cvtU8toS16(*(ibuf + 1));
+		} else if (dsb->wfx.wBitsPerSample == 16) {
+			fl = *((INT16 *)ibuf);
+			fr = *(((INT16 *)ibuf) + 1);
+		}
+	} else if (dsb->wfx.nChannels == 1) {
+		if (dsb->wfx.wBitsPerSample == 8) {
+			/* avoid needless 8->16->8 conversion */
+			if ( (primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 1) ) {
+				*obuf=*ibuf;
+				return;
+			}
+			fl = cvtU8toS16(*ibuf);
+			fr = fl;
+		} else if (dsb->wfx.wBitsPerSample == 16) {
+			fl = *((INT16 *)ibuf);
+			fr = fl;
+		}
 	}
-
-	if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 1)) {
-		*bufs = (fl + fr) >> 1;
-		return;
+	if (primarybuf->wfx.nChannels == 2) {
+		if (primarybuf->wfx.wBitsPerSample == 8) {
+			*obuf = cvtS16toU8(fl);
+			*(obuf + 1) = cvtS16toU8(fr);
+			return;
+		}
+		if (primarybuf->wfx.wBitsPerSample == 16) {
+			*((INT16 *)obuf) = fl;
+			*(((INT16 *)obuf) + 1) = fr;
+			return;
+		}
+	}	
+	if (primarybuf->wfx.nChannels == 1) {
+		fl = (fl + fr) >> 1;
+		if (primarybuf->wfx.wBitsPerSample == 8) {
+			*obuf = cvtS16toU8(fl);
+			return;
+		}
+		if (primarybuf->wfx.wBitsPerSample == 16) {
+			*((INT16 *)obuf) = fl;
+			return;
+		}
 	}
-	FIXME("set_fields found an unsupported configuration\n");
-	return;
 }
 
 /* Now with PerfectPitch (tm) technology */
 static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
 {
-	INT	i, size, ipos, ilen, fieldL, fieldR;
+	INT	i, size, ipos, ilen;
 	BYTE	*ibp, *obp;
 	INT	iAdvance = dsb->wfx.nBlockAlign;
 	INT	oAdvance = primarybuf->wfx.nBlockAlign;
@@ -2700,10 +2787,9 @@
 			dsb->freq, primarybuf->wfx.nSamplesPerSec);
 		ilen = 0;
 		for (i = 0; i < len; i += oAdvance) {
-			get_fields(dsb, ibp, &fieldL, &fieldR);
+			cp_fields(dsb, ibp, obp );
 			ibp += iAdvance;
 			ilen += iAdvance;
-			set_fields(obp, fieldL, fieldR);
 			obp += oAdvance;
 			if (ibp >= (BYTE *)(dsb->buffer + dsb->buflen))
 				ibp = dsb->buffer;	/* wrap */
@@ -2719,17 +2805,15 @@
 	/* Patent enhancements (c) 2000 Ove Kåven,
 	 * TransGaming Technologies Inc. */
 
-	FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n",
+/*	FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n",
 		dsb, dsb->freq, primarybuf->wfx.nSamplesPerSec);
-
+*/
 	size = len / oAdvance;
 	ilen = 0;
 	ipos = dsb->buf_mixpos;
 	for (i = 0; i < size; i++) {
-		get_fields(dsb, (dsb->buffer + ipos), &fieldL, &fieldR);
-		set_fields(obp, fieldL, fieldR);
+		cp_fields(dsb, (dsb->buffer + ipos), obp);
 		obp += oAdvance;
-
 		dsb->freqAcc += dsb->freqAdjust;
 		if (dsb->freqAcc >= (1<<DSOUND_FREQSHIFT)) {
 			ULONG adv = (dsb->freqAcc>>DSOUND_FREQSHIFT) * iAdvance;
@@ -3260,16 +3344,16 @@
 		DSOUND_MixReset(writepos);
 		primarybuf->need_remix = FALSE;
 		/* maximize Half-Life performance */
-		dsound->prebuf = DS_SND_QUEUE_MIN;
+		dsound->prebuf = ds_snd_queue_min;
 	} else {
-		/* if (dsound->prebuf < DS_SND_QUEUE_MAX) dsound->prebuf++; */
+		/* if (dsound->prebuf < ds_snd_queue_max) dsound->prebuf++; */
 	}
 	TRACE("premix adjust: %d\n", dsound->prebuf);
 }
 
 static void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq)
 {
-	if (mixq + dsound->pwqueue > DS_HEL_QUEUE) mixq = DS_HEL_QUEUE - dsound->pwqueue;
+	if (mixq + dsound->pwqueue > ds_hel_queue) mixq = ds_hel_queue - dsound->pwqueue;
 	TRACE("queueing %ld buffers, starting at %d\n", mixq, dsound->pwwrite);
 	for (; mixq; mixq--) {
 		waveOutWrite(dsound->hwo, dsound->pwave[dsound->pwwrite], sizeof(WAVEHDR));
@@ -3325,7 +3409,7 @@
  			playpos = dsound->pwplay * dsound->fraglen;
  			writepos = playpos;
  			if (!paused) {
-	 			writepos += DS_HEL_MARGIN * dsound->fraglen;
+	 			writepos += ds_hel_margin * dsound->fraglen;
 	 			while (writepos >= primarybuf->buflen)
  					writepos -= primarybuf->buflen;
 	 		}
@@ -3515,7 +3599,7 @@
 	PIDSDRIVER drv = NULL;
 	WAVEOUTCAPSA wcaps;
 	unsigned wod, wodn;
-	HRESULT err = DS_OK;
+	HRESULT err = DS_OK;	
 
 	if (lpGUID)
 		TRACE("(%p,%p,%p)\n",lpGUID,ippDS,pUnkOuter);
@@ -3531,6 +3615,9 @@
 		return DS_OK;
 	}
 
+	/* get dsound configuration */
+	setup_dsound_options();
+
 	/* Enumerate WINMM audio devices and find the one we want */
 	wodn = waveOutGetNumDevs();
 	if (!wodn) return DSERR_NODRIVER;
@@ -3559,7 +3646,7 @@
 	(*ippDS)->primary	= NULL; 
 	(*ippDS)->listener	= NULL; 
 
-	(*ippDS)->prebuf	= DS_SND_QUEUE_MAX;
+	(*ippDS)->prebuf	= ds_snd_queue_max;
 
 	/* Get driver description */
 	if (drv) {
@@ -3619,10 +3706,11 @@
 	} else {
 		unsigned c;
 
+
 		/* FIXME: look at wcaps */
 		(*ippDS)->drvcaps.dwFlags =
 			DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO;
-		if (DS_EMULDRIVER)
+		if (ds_emuldriver)
 		    (*ippDS)->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
 
 		/* Allocate memory for HEL buffer headers */


More information about the wine-patches mailing list