Signed-off-by: Florian Will florian.will@gmail.com --- dlls/dsound/buffer.c | 15 +++++++++++++++ dlls/dsound/dsound_private.h | 1 + 2 files changed, 16 insertions(+)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index c595b19dd63..3d848053842 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -1197,6 +1197,21 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *This) TRACE("(%p) released\n", This); }
+/* Check if anything is audible. Even if this returns false, the lVolume of this buffer might not + * actually be DSBVOLUME_MIN. Setting the volume close to DSBVOLUME_MIN will lead to a + * dwTotalAmpFactor of 0, too. This function will return false in these cases because the effect is + * the same as setting the volume to DSBVOLUME_MIN, i.e. this buffer is not audible. */ +BOOL secondarybuffer_is_audible(IDirectSoundBufferImpl *This) +{ + UINT i; + for (i = 0; i < This->device->pwfx->nChannels; i++) { + if (This->volpan.dwTotalAmpFactor[i] != 0) + return TRUE; + } + + return FALSE; +} + HRESULT IDirectSoundBufferImpl_Duplicate( DirectSoundDevice *device, IDirectSoundBufferImpl **ppdsb, diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 9ec96504a50..18dc369db5c 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -193,6 +193,7 @@ HRESULT IDirectSoundBufferImpl_Duplicate( IDirectSoundBufferImpl **ppdsb, IDirectSoundBufferImpl *pdsb) DECLSPEC_HIDDEN; void secondarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN; +BOOL secondarybuffer_is_audible(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN; extern const IDirectSound3DListenerVtbl ds3dlvt DECLSPEC_HIDDEN; extern const IDirectSound3DBufferVtbl ds3dbvt DECLSPEC_HIDDEN; extern const IKsPropertySetVtbl iksbvt DECLSPEC_HIDDEN;
In some situations, "ZUSI 3" has a lot of secondary buffers in the PLAYING state, but most of these buffers have a really low volume, so these buffers are multiplied by 0 before mixing (and possibly after resampling). There can be hundreds of inaudible buffers at the same time.
In these situations, the dsound mixthread is unable to mix fast enough, resulting in sound stuttering and generally poor performance.
To resolve this performance issue, skip the mixing (and possibly resampling) step for all inaudible secondary buffers.
Signed-off-by: Florian Will florian.will@gmail.com --- There is space indentation at the top of the patch and tab indentation at the bottom, but that matches surrounding code. --- dlls/dsound/mixer.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index e9d8a6e3cdd..d28cc8dc5aa 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -290,6 +290,9 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count) UINT committed_samples = 0; DWORD channel, i;
+ if (!secondarybuffer_is_audible(dsb)) + return count; + if(dsb->use_committed) { committed_samples = (dsb->writelead - dsb->committed_mixpos) / istride; committed_samples = committed_samples <= count ? committed_samples : count; @@ -329,6 +332,11 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * len += fir_cachesize; len *= sizeof(float);
+ *freqAccNum = freqAcc_end % dsb->freqAdjustDen; + + if (!secondarybuffer_is_audible(dsb)) + return max_ipos; + if (!dsb->device->cp_buffer) { dsb->device->cp_buffer = HeapAlloc(GetProcessHeap(), 0, len); dsb->device->cp_buffer_len = len; @@ -386,8 +394,6 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * } }
- *freqAccNum = freqAcc_end % dsb->freqAdjustDen; - return max_ipos; }
@@ -535,10 +541,12 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, float *mix_buffer, DSOUND_MixToTemporary(dsb, frames); ibuf = dsb->device->tmp_buffer;
- /* Apply volume if needed */ - DSOUND_MixerVol(dsb, frames); + if (secondarybuffer_is_audible(dsb)) { + /* Apply volume if needed */ + DSOUND_MixerVol(dsb, frames);
- mixieee32(ibuf, mix_buffer, frames * dsb->device->pwfx->nChannels); + mixieee32(ibuf, mix_buffer, frames * dsb->device->pwfx->nChannels); + }
/* check for notification positions */ if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY &&