Commit 865cf375 authored by Ove Kaaven's avatar Ove Kaaven Committed by Alexandre Julliard

Bugfix for sound dropping out, and workaround for Half-Life's

braindead secondary sound buffer management.
parent dea3d786
...@@ -1496,6 +1496,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock( ...@@ -1496,6 +1496,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
assert(audiobytes1!=audiobytes2); assert(audiobytes1!=audiobytes2);
assert(lplpaudioptr1!=lplpaudioptr2); assert(lplpaudioptr1!=lplpaudioptr2);
if ((writebytes == This->buflen) &&
((This->state == STATE_STARTING) ||
(This->state == STATE_PLAYING)))
/* some games, like Half-Life, tries to be clever (not) and
* keeps one secondary buffer, and mixes sounds into it itself,
* locking the entire buffer every time... so we can just forget
* about tracking the last-written-to-position... */
This->probably_valid_to = (DWORD)-1;
else
This->probably_valid_to = writecursor; This->probably_valid_to = writecursor;
if (This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) if (This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER)
...@@ -1600,7 +1609,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( ...@@ -1600,7 +1609,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2 LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
) { ) {
ICOM_THIS(IDirectSoundBufferImpl,iface); ICOM_THIS(IDirectSoundBufferImpl,iface);
DWORD capf; DWORD capf, probably_valid_to;
TRACE("(%p,%p,%ld,%p,%ld):stub\n", This,p1,x1,p2,x2); TRACE("(%p,%p,%ld,%p,%ld):stub\n", This,p1,x1,p2,x2);
...@@ -1620,10 +1629,16 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( ...@@ -1620,10 +1629,16 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2); IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
} }
if (p2) This->probably_valid_to = (((LPBYTE)p2)-This->buffer) + x2; if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer) + x2;
else This->probably_valid_to = (((LPBYTE)p1)-This->buffer) + x1; else probably_valid_to = (((LPBYTE)p1)-This->buffer) + x1;
while (This->probably_valid_to >= This->buflen) while (probably_valid_to >= This->buflen)
This->probably_valid_to -= This->buflen; probably_valid_to -= This->buflen;
if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) &&
((This->state == STATE_STARTING) ||
(This->state == STATE_PLAYING)))
/* see IDirectSoundBufferImpl_Lock */
probably_valid_to = (DWORD)-1;
This->probably_valid_to = probably_valid_to;
return DS_OK; return DS_OK;
} }
...@@ -2796,9 +2811,9 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri ...@@ -2796,9 +2811,9 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD wri
} }
TRACE("new primary_mixpos=%ld, primary_advbase=%ld\n", dsb->primary_mixpos, primarybuf->buf_mixpos); TRACE("new primary_mixpos=%ld, primary_advbase=%ld\n", dsb->primary_mixpos, primarybuf->buf_mixpos);
TRACE("mixed data len=%ld, still_behind=%d\n", mixlen-len, still_behind); TRACE("mixed data len=%ld, still_behind=%d\n", mixlen-len, still_behind);
if (still_behind) return 0;
/* return how far we think the primary buffer can /* return how far we think the primary buffer can
* advance its underrun detector...*/ * advance its underrun detector...*/
if (still_behind) return 0;
if ((mixlen - len) < primary_done) return 0; if ((mixlen - len) < primary_done) return 0;
slen = ((dsb->primary_mixpos < primarybuf->buf_mixpos) ? slen = ((dsb->primary_mixpos < primarybuf->buf_mixpos) ?
primarybuf->buflen : 0) + dsb->primary_mixpos - primarybuf->buflen : 0) + dsb->primary_mixpos -
...@@ -2962,7 +2977,7 @@ static void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw ...@@ -2962,7 +2977,7 @@ static void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw
while (primarybuf->buf_mixpos >= primarybuf->buflen) while (primarybuf->buf_mixpos >= primarybuf->buflen)
primarybuf->buf_mixpos -= primarybuf->buflen; primarybuf->buf_mixpos -= primarybuf->buflen;
if (inq) { if (frag) {
/* buffers have been filled, restart playback */ /* buffers have been filled, restart playback */
if (primarybuf->state == STATE_STARTING) { if (primarybuf->state == STATE_STARTING) {
IDsDriverBuffer_Play(primarybuf->hwbuf, 0, 0, DSBPLAY_LOOPING); IDsDriverBuffer_Play(primarybuf->hwbuf, 0, 0, DSBPLAY_LOOPING);
...@@ -3066,6 +3081,7 @@ static void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw ...@@ -3066,6 +3081,7 @@ static void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw
} }
LeaveCriticalSection(&(primarybuf->lock)); LeaveCriticalSection(&(primarybuf->lock));
} }
TRACE("completed processing\n");
LeaveCriticalSection(&(dsound->lock)); LeaveCriticalSection(&(dsound->lock));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment