[PATCH v2 2/3] dsound: Use frame rather than byte counts to clarify the mixing.
Andrew Eikum
aeikum at codeweavers.com
Wed Mar 1 10:37:38 CST 2017
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Wed, Mar 01, 2017 at 04:00:59PM +0000, Huw Davies wrote:
> 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