winealsa.drv/dsound: Handle underruns better.
This commit is contained in:
parent
09874bf78a
commit
6e90756307
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue