From 134b684fd90423490e7eb2395db88df683d8fdc1 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Wed, 1 Mar 2017 16:00:59 +0000 Subject: [PATCH] dsound: Use frame rather than byte counts to clarify the mixing. Signed-off-by: Huw Davies Signed-off-by: Andrew Eikum Signed-off-by: Alexandre Julliard --- dlls/dsound/dsound_private.h | 2 +- dlls/dsound/mixer.c | 93 ++++++++++++++++++++------------------------ dlls/dsound/primary.c | 8 ++-- 3 files changed, 47 insertions(+), 56 deletions(-) diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 63d12262752..b15189ed2df 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -77,7 +77,7 @@ struct DirectSoundDevice DWORD priolevel, sleeptime; PWAVEFORMATEX pwfx, primary_pwfx; LPBYTE buffer; - DWORD writelead, buflen, aclen, fraglen, playpos, pad, stopped; + DWORD writelead, buflen, ac_frames, frag_frames, playpos, pad, stopped; int nrofbuffers; IDirectSoundBufferImpl** buffers; RTL_RWLOCK buffer_list_lock; diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 174d56caa4a..049a345eedd 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -489,21 +489,13 @@ static void DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT frames) * dsb = the secondary buffer to mix from * fraglen = number of bytes to mix */ -static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, float *mix_buffer, DWORD fraglen) +static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, float *mix_buffer, DWORD frames) { - INT len = fraglen; float *ibuf; DWORD oldpos; - UINT frames = fraglen / dsb->device->pwfx->nBlockAlign; TRACE("sec_mixpos=%d/%d\n", dsb->sec_mixpos, dsb->buflen); - TRACE("(%p,%d)\n",dsb,fraglen); - - if (len % dsb->device->pwfx->nBlockAlign) { - INT nBlockAlign = dsb->device->pwfx->nBlockAlign; - ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign); - len -= len % nBlockAlign; /* data alignment */ - } + TRACE("(%p, frames=%d)\n",dsb,frames); /* Resample buffer to temporary buffer specifically allocated for this purpose, if needed */ oldpos = dsb->sec_mixpos; @@ -522,7 +514,7 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, float *mix_buffer, DSOUND_CheckEvent(dsb, oldpos, ilen); } - return len; + return frames; } /** @@ -531,37 +523,37 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, float *mix_buffer, * * dsb = the secondary buffer * playpos = the current play position in the device buffer (primary buffer) - * mixlen = the maximum number of bytes in the primary buffer to mix, from the + * frames = the maximum number of frames in the primary buffer to mix, from the * current writepos. * - * Returns: the number of bytes beyond the writepos that were mixed. + * Returns: the number of frames beyond the writepos that were mixed. */ -static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, float *mix_buffer, DWORD mixlen) +static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, float *mix_buffer, DWORD frames) { DWORD primary_done = 0; - TRACE("(%p,%d)\n",dsb,mixlen); + TRACE("(%p, frames=%d)\n",dsb,frames); TRACE("looping=%d, leadin=%d\n", dsb->playflags, dsb->leadin); /* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */ /* FIXME: Is this needed? */ if (dsb->leadin && dsb->state == STATE_STARTING) { - if (mixlen > 2 * dsb->device->fraglen) { - primary_done = mixlen - 2 * dsb->device->fraglen; - mixlen = 2 * dsb->device->fraglen; - dsb->sec_mixpos += (primary_done / dsb->device->pwfx->nBlockAlign) * + if (frames > 2 * dsb->device->frag_frames) { + primary_done = frames - 2 * dsb->device->frag_frames; + frames = 2 * dsb->device->frag_frames; + dsb->sec_mixpos += primary_done * dsb->pwfx->nBlockAlign * dsb->freqAdjustNum / dsb->freqAdjustDen; } } dsb->leadin = FALSE; - TRACE("mixlen (primary) = %i\n", mixlen); + TRACE("frames (primary) = %i\n", frames); /* First try to mix to the end of the buffer if possible * Theoretically it would allow for better optimization */ - primary_done += DSOUND_MixInBuffer(dsb, mix_buffer, mixlen); + primary_done += DSOUND_MixInBuffer(dsb, mix_buffer, frames); TRACE("total mixed data=%d\n", primary_done); @@ -573,14 +565,13 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, float *mix_buffer, DWORD * For a DirectSoundDevice, go through all the currently playing buffers and * mix them in to the device buffer. * - * mixlen = the maximum amount to mix into the primary buffer - * (beyond the current writepos) + * frames = the maximum amount to mix into the primary buffer * all_stopped = reports back if all buffers have stopped * * Returns: the length beyond the writepos that was mixed to. */ -static void DSOUND_MixToPrimary(const DirectSoundDevice *device, float *mix_buffer, DWORD mixlen, BOOL *all_stopped) +static void DSOUND_MixToPrimary(const DirectSoundDevice *device, float *mix_buffer, DWORD frames, BOOL *all_stopped) { INT i; IDirectSoundBufferImpl *dsb; @@ -588,14 +579,14 @@ static void DSOUND_MixToPrimary(const DirectSoundDevice *device, float *mix_buff /* unless we find a running buffer, all have stopped */ *all_stopped = TRUE; - TRACE("(%d)\n", mixlen); + TRACE("(frames %d)\n", frames); for (i = 0; i < device->nrofbuffers; i++) { dsb = device->buffers[i]; TRACE("MixToPrimary for %p, state=%d\n", dsb, dsb->state); if (dsb->buflen && dsb->state) { - TRACE("Checking %p, mixlen=%d\n", dsb, mixlen); + TRACE("Checking %p, frames=%d\n", dsb, frames); RtlAcquireResourceShared(&dsb->lock, TRUE); /* if buffer is stopping it is stopped now */ if (dsb->state == STATE_STOPPING) { @@ -608,7 +599,7 @@ static void DSOUND_MixToPrimary(const DirectSoundDevice *device, float *mix_buff dsb->state = STATE_PLAYING; /* mix next buffer into the main buffer */ - DSOUND_MixOne(dsb, mix_buffer, mixlen); + DSOUND_MixOne(dsb, mix_buffer, frames); *all_stopped = FALSE; } @@ -666,8 +657,7 @@ static void DSOUND_WaveQueue(DirectSoundDevice *device, LPBYTE pos, DWORD bytes) */ static void DSOUND_PerformMix(DirectSoundDevice *device) { - UINT32 pad, maxq; - DWORD block; + DWORD block, pad_frames, pad_bytes, frames; HRESULT hr; TRACE("(%p)\n", device); @@ -675,26 +665,26 @@ static void DSOUND_PerformMix(DirectSoundDevice *device) /* **** */ EnterCriticalSection(&device->mixlock); - hr = IAudioClient_GetCurrentPadding(device->client, &pad); + hr = IAudioClient_GetCurrentPadding(device->client, &pad_frames); if(FAILED(hr)){ WARN("GetCurrentPadding failed: %08x\n", hr); LeaveCriticalSection(&device->mixlock); return; } block = device->pwfx->nBlockAlign; - pad *= block; - device->playpos += device->pad - pad; + pad_bytes = pad_frames * block; + device->playpos += device->pad - pad_bytes; device->playpos %= device->buflen; - device->pad = pad; + device->pad = pad_bytes; - maxq = device->aclen - pad; - if(!maxq){ + frames = device->ac_frames - pad_frames; + if(!frames){ /* nothing to do! */ LeaveCriticalSection(&device->mixlock); return; } - if (maxq > device->fraglen * 3) - maxq = device->fraglen * 3; + if (frames > device->frag_frames * 3) + frames = device->frag_frames * 3; if (device->priolevel != DSSCL_WRITEPRIMARY) { BOOL all_stopped = FALSE; @@ -706,44 +696,45 @@ static void DSOUND_PerformMix(DirectSoundDevice *device) /* check for underrun. underrun occurs when the write position passes the mix position * also wipe out just-played sound data */ - if (!pad) + if (!pad_frames) WARN("Probable buffer underrun\n"); - hr = IAudioRenderClient_GetBuffer(device->render, maxq / block, (void*)&buffer); + hr = IAudioRenderClient_GetBuffer(device->render, frames, (void*)&buffer); if(FAILED(hr)){ WARN("GetBuffer failed: %08x\n", hr); LeaveCriticalSection(&device->mixlock); return; } - memset(buffer, nfiller, maxq); + memset(buffer, nfiller, frames * block); if (!device->normfunction) - DSOUND_MixToPrimary(device, buffer, maxq, &all_stopped); + DSOUND_MixToPrimary(device, buffer, frames, &all_stopped); else { memset(device->buffer, nfiller, device->buflen); /* do the mixing */ - DSOUND_MixToPrimary(device, (float*)device->buffer, maxq, &all_stopped); + DSOUND_MixToPrimary(device, (float*)device->buffer, frames, &all_stopped); - device->normfunction(device->buffer, buffer, maxq); + device->normfunction(device->buffer, buffer, frames * block); } - hr = IAudioRenderClient_ReleaseBuffer(device->render, maxq / block, 0); + hr = IAudioRenderClient_ReleaseBuffer(device->render, frames, 0); if(FAILED(hr)) ERR("ReleaseBuffer failed: %08x\n", hr); - device->pad += maxq; + device->pad += frames * block; } else if (!device->stopped) { - DWORD writepos = (device->playpos + pad) % device->buflen; + DWORD writepos = (device->playpos + pad_bytes) % device->buflen; + DWORD bytes = frames * block; - if (maxq > device->buflen) - maxq = device->buflen; - if (writepos + maxq > device->buflen) { + if (bytes > device->buflen) + bytes = device->buflen; + if (writepos + bytes > device->buflen) { DSOUND_WaveQueue(device, device->buffer + writepos, device->buflen - writepos); - DSOUND_WaveQueue(device, device->buffer, writepos + maxq - device->buflen); + DSOUND_WaveQueue(device, device->buffer, writepos + bytes - device->buflen); } else - DSOUND_WaveQueue(device, device->buffer + writepos, maxq); + DSOUND_WaveQueue(device, device->buffer + writepos, bytes); } LeaveCriticalSection(&(device->mixlock)); diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 87b7e8eac8a..6eb5a98b620 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -264,7 +264,7 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device, WAVEFORMATEX *wfx, device->writelead = (wfx->nSamplesPerSec / 100) * wfx->nBlockAlign; - TRACE("buflen: %u, fraglen: %u\n", device->buflen, device->fraglen); + TRACE("buflen: %u, frames %u\n", device->buflen, frames); if (!mixfloat) device->normfunction = normfunctions[wfx->wBitsPerSample/8 - 1]; @@ -351,7 +351,7 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) aclen_frames = min(acbuf_frames, 3 * frag_frames); - TRACE("period %u ms fraglen %u buflen %u\n", period_ms, frag_frames * wfx->nBlockAlign, aclen_frames * wfx->nBlockAlign); + TRACE("period %u ms frag_frames %u buf_frames %u\n", period_ms, frag_frames, aclen_frames); hres = DSOUND_PrimaryOpen(device, wfx, aclen_frames, forcewave); if(FAILED(hres)) @@ -361,8 +361,8 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) device->client = client; device->render = render; device->volume = volume; - device->fraglen = frag_frames * wfx->nBlockAlign; - device->aclen = aclen_frames * wfx->nBlockAlign; + device->frag_frames = frag_frames; + device->ac_frames = aclen_frames; if (period_ms < 3) device->sleeptime = 5; -- 2.11.4.GIT