[PATCH v2 2/3] dsound: Use frame rather than byte counts to clarify the mixing.
Huw Davies
huw at codeweavers.com
Wed Mar 1 10:00:59 CST 2017
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
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 63d1226..b15189e 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 174d56c..049a345 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 87b7e8e..6eb5a98 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.10.2
More information about the wine-patches
mailing list