[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