Maarten Lankhorst : winealsa.drv/dsound: Handle underruns better.
Alexandre Julliard
julliard at winehq.org
Thu Sep 4 08:27:14 CDT 2008
Module: wine
Branch: master
Commit: 6e90756307bfd5aa6ce2207f9419dabd26f46ec6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=6e90756307bfd5aa6ce2207f9419dabd26f46ec6
Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Thu Sep 4 12:07:37 2008 +0200
winealsa.drv/dsound: Handle underruns better.
---
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
More information about the wine-cvs
mailing list