[PATCH] winealsa.drv/dsound: Handle underruns better

Maarten Lankhorst m.b.lankhorst at gmail.com
Thu Sep 4 05:07:37 CDT 2008


---
 dlls/dsound/mixer.c          |   50 +++++++++++++++++++++--------------------
 dlls/winealsa.drv/dsoutput.c |    4 +++
 dlls/winealsa.drv/waveout.c  |    3 --
 3 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 7fe9423..3c13e8f 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -826,8 +826,32 @@ static void DSOUND_PerformMix(DirectSoundDevice *device)
 
 		mixplaypos = DSOUND_bufpos_to_mixpos(device, device->playpos);
 		mixplaypos2 = DSOUND_bufpos_to_mixpos(device, playpos);
-		/* wipe out just-played sound data */
-		if (playpos < device->playpos) {
+
+		/* calc maximum prebuff */
+		prebuff_max = (device->prebuf * device->fraglen);
+		if (!device->hwbuf && playpos + prebuff_max >= device->helfrags * device->fraglen)
+			prebuff_max += device->buflen - device->helfrags * device->fraglen;
+
+		/* check how close we are to an underrun. It occurs when the writepos overtakes the mixpos */
+		prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
+		writelead = DSOUND_BufPtrDiff(device->buflen, writepos, playpos);
+
+		/* check for underrun. underrun occurs when the write position passes the mix position
+		 * also wipe out just-played sound data */
+		if((prebuff_left > prebuff_max) || (device->state == STATE_STOPPED) || (device->state == STATE_STARTING)){
+			if (device->state == STATE_STOPPING || device->state == STATE_PLAYING)
+				WARN("Probable buffer underrun\n");
+			else TRACE("Buffer starting or buffer underrun\n");
+
+			/* recover mixing for all buffers */
+			recover = TRUE;
+
+			/* reset mix position to write position */
+			device->mixpos = writepos;
+
+			ZeroMemory(device->mix_buffer, device->mix_buffer_len);
+			ZeroMemory(device->buffer, device->buflen);
+		} else if (playpos < device->playpos) {
 			buf1 = device->buffer + device->playpos;
 			buf2 = device->buffer;
 			size1 = device->buflen - device->playpos;
@@ -861,34 +885,12 @@ static void DSOUND_PerformMix(DirectSoundDevice *device)
 		}
 		device->playpos = playpos;
 
-		/* calc maximum prebuff */
-		prebuff_max = (device->prebuf * device->fraglen);
-		if (!device->hwbuf && playpos + prebuff_max >= device->helfrags * device->fraglen)
-			prebuff_max += device->buflen - device->helfrags * device->fraglen;
-
-		/* check how close we are to an underrun. It occurs when the writepos overtakes the mixpos */
-		prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos);
-		writelead = DSOUND_BufPtrDiff(device->buflen, writepos, playpos);
-
 		/* find the maximum we can prebuffer from current write position */
 		maxq = (writelead < prebuff_max) ? (prebuff_max - writelead) : 0;
 
 		TRACE("prebuff_left = %d, prebuff_max = %dx%d=%d, writelead=%d\n",
 			prebuff_left, device->prebuf, device->fraglen, prebuff_max, writelead);
 
-		/* check for underrun. underrun occurs when the write position passes the mix position */
-		if((prebuff_left > prebuff_max) || (device->state == STATE_STOPPED) || (device->state == STATE_STARTING)){
-			if (device->state == STATE_STOPPING || device->state == STATE_PLAYING)
-				WARN("Probable buffer underrun\n");
-			else TRACE("Buffer starting or buffer underrun\n");
-
-			/* recover mixing for all buffers */
-			recover = TRUE;
-
-			/* reset mix position to write position */
-			device->mixpos = writepos;
-		}
-
 		/* Do we risk an 'underrun' if we don't advance pointer? */
 		if (writelead/device->fraglen <= ds_snd_queue_min || recover)
 			mustlock = TRUE;
diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c
index 4043ccf..15cff5f 100644
--- a/dlls/winealsa.drv/dsoutput.c
+++ b/dlls/winealsa.drv/dsoutput.c
@@ -329,6 +329,8 @@ static HRESULT WINAPI IDsDriverBufferImpl_Lock(PIDSDRIVERBUFFER iface,
         TRACE("Hit mmap_pos, locking data!\n");
         snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin);
     }
+    else
+        WARN("mmap_pos (%lu) != writepos (%lu) not locking data!\n", This->mmap_pos, writepos);
 
     LeaveCriticalSection(&This->pcm_crst);
     /* **** */
@@ -551,7 +553,9 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,
 
         if (used < 0)
         {
+            This->mmap_pos += -used;
             snd_pcm_forward(This->pcm, -used);
+            This->mmap_pos %= This->mmap_buflen_frames;
             used = 0;
         }
 
diff --git a/dlls/winealsa.drv/waveout.c b/dlls/winealsa.drv/waveout.c
index 9dae6f4..8149a4a 100644
--- a/dlls/winealsa.drv/waveout.c
+++ b/dlls/winealsa.drv/waveout.c
@@ -575,7 +575,6 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
     unsigned int                period_time = 20000;
     snd_pcm_uframes_t           buffer_size;
     snd_pcm_uframes_t           period_size;
-    snd_pcm_uframes_t           boundary;
     int                         flags;
     int                         err=0;
     int                         dir=0;
@@ -758,13 +757,11 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
     err = snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
 
     snd_pcm_sw_params_current(pcm, sw_params);
-    snd_pcm_sw_params_get_boundary(sw_params, &boundary);
 
     EXIT_ON_ERROR( snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 1), MMSYSERR_ERROR, "unable to set start threshold");
     EXIT_ON_ERROR( snd_pcm_sw_params_set_silence_size(pcm, sw_params, 0), MMSYSERR_ERROR, "unable to set silence size");
     EXIT_ON_ERROR( snd_pcm_sw_params_set_avail_min(pcm, sw_params, period_size), MMSYSERR_ERROR, "unable to set avail min");
     EXIT_ON_ERROR( snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, 0), MMSYSERR_ERROR, "unable to set silence threshold");
-    EXIT_ON_ERROR( snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, boundary), MMSYSERR_ERROR, "unable to set stop threshold");
     EXIT_ON_ERROR( snd_pcm_sw_params(pcm, sw_params), MMSYSERR_ERROR, "unable to set sw params for playback");
 #undef EXIT_ON_ERROR
 
-- 
1.5.6.5


--------------040608090104020704000606--



More information about the wine-patches mailing list