Module: wine Branch: master Commit: 6d009b988b22212fabcc34711c40ec776fecaec5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6d009b988b22212fabcc34711c...
Author: Marton Balint cus@passwd.hu Date: Sat Dec 27 23:41:07 2014 +0100
dsound: Convert freqAdjust and freqAcc to integers.
Fixes resampling errors caused by truncating floating point numbers.
---
dlls/dsound/buffer.c | 6 ++++-- dlls/dsound/dsound_private.h | 4 +++- dlls/dsound/mixer.c | 37 ++++++++++++++++++------------------- 3 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 9794b84..36ec132 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -274,7 +274,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *i oldFreq = This->freq; This->freq = freq; if (freq != oldFreq) { - This->freqAdjust = This->freq / (float)This->device->pwfx->nSamplesPerSec; + This->freqAdjustNum = This->freq; + This->freqAdjustDen = This->device->pwfx->nSamplesPerSec; This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign; DSOUND_RecalcFormat(This); } @@ -935,7 +936,8 @@ HRESULT IDirectSoundBufferImpl_Create( dsb->sec_mixpos = 0; dsb->state = STATE_STOPPED;
- dsb->freqAdjust = dsb->freq / (float)device->pwfx->nSamplesPerSec; + dsb->freqAdjustNum = dsb->freq; + dsb->freqAdjustDen = device->pwfx->nSamplesPerSec; dsb->nAvgBytesPerSec = dsb->freq * dsbd->lpwfxFormat->nBlockAlign;
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 95b2279..66af81a 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -152,7 +152,9 @@ struct IDirectSoundBufferImpl /* used for frequency conversion (PerfectPitch) */ ULONG freqneeded; DWORD firstep; - float freqAcc, freqAdjust, firgain; + float firgain; + LONG64 freqAdjustNum,freqAdjustDen; + LONG64 freqAccNum; /* used for mixing */ DWORD sec_mixpos;
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index bc38319..f6c2661 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -104,7 +104,8 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) TRACE("(%p)\n",dsb);
pwfxe = (WAVEFORMATEXTENSIBLE *) dsb->pwfx; - dsb->freqAdjust = (float)dsb->freq / dsb->device->pwfx->nSamplesPerSec; + dsb->freqAdjustNum = dsb->freq; + dsb->freqAdjustDen = dsb->device->pwfx->nSamplesPerSec;
if ((pwfxe->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) || ((pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) && (IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))) @@ -117,12 +118,12 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) * sample in the secondary buffer. firgain specifies what * to multiply the FIR output by in order to attenuate it correctly. */ - if (dsb->freqAdjust > 1.0f) { + if (dsb->freqAdjustNum / dsb->freqAdjustDen > 0) { /** * Yes, round it a bit to make sure that the * linear interpolation factor never changes. */ - dsb->firstep = ceil(fir_step / dsb->freqAdjust); + dsb->firstep = fir_step * dsb->freqAdjustDen / dsb->freqAdjustNum; } else { dsb->firstep = fir_step; } @@ -131,7 +132,7 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) /* calculate the 10ms write lead */ dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign;
- dsb->freqAcc = 0; + dsb->freqAccNum = 0;
dsb->get_aux = ieee ? getbpp[4] : getbpp[dsb->pwfx->wBitsPerSample/8 - 1]; dsb->put_aux = putieee32; @@ -262,18 +263,17 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count) return count; }
-static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, float *freqAcc) +static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum) { UINT i, channel; UINT istride = dsb->pwfx->nBlockAlign; UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
- float freqAdjust = dsb->freqAdjust; - float freqAcc_start = *freqAcc; - float freqAcc_end = freqAcc_start + count * freqAdjust; + LONG64 freqAcc_start = *freqAccNum; + LONG64 freqAcc_end = freqAcc_start + count * dsb->freqAdjustNum; UINT dsbfirstep = dsb->firstep; UINT channels = dsb->mix_channels; - UINT max_ipos = freqAcc_start + count * freqAdjust; + UINT max_ipos = (freqAcc_start + count * dsb->freqAdjustNum) / dsb->freqAdjustDen;
UINT fir_cachesize = (fir_len + dsbfirstep - 2) / dsbfirstep; UINT required_input = max_ipos + fir_cachesize; @@ -295,8 +295,8 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, float *f dsb->sec_mixpos + i * istride, channel);
for(i = 0; i < count; ++i) { - float total_fir_steps = (freqAcc_start + i * freqAdjust) * dsbfirstep; - UINT int_fir_steps = total_fir_steps; + UINT int_fir_steps = (freqAcc_start + i * dsb->freqAdjustNum) * dsbfirstep / dsb->freqAdjustDen; + float total_fir_steps = (freqAcc_start + i * dsb->freqAdjustNum) * dsbfirstep / (float)dsb->freqAdjustDen; UINT ipos = int_fir_steps / dsbfirstep;
UINT idx = (ipos + 1) * dsbfirstep - int_fir_steps - 1; @@ -321,8 +321,7 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, float *f } }
- freqAcc_end -= (int)freqAcc_end; - *freqAcc = freqAcc_end; + *freqAccNum = freqAcc_end % dsb->freqAdjustDen;
HeapFree(GetProcessHeap(), 0, fir_copy); HeapFree(GetProcessHeap(), 0, intermediate); @@ -330,14 +329,14 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, float *f return max_ipos; }
-static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, float *freqAcc) +static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum) { DWORD ipos, adv;
- if (dsb->freqAdjust == 1.0) - adv = cp_fields_noresample(dsb, count); /* *freqAcc is unmodified */ + if (dsb->freqAdjustNum == dsb->freqAdjustDen) + adv = cp_fields_noresample(dsb, count); /* *freqAccNum is unmodified */ else - adv = cp_fields_resample(dsb, count, freqAcc); + adv = cp_fields_resample(dsb, count, freqAccNum);
ipos = dsb->sec_mixpos + adv * dsb->pwfx->nBlockAlign; if (ipos >= dsb->buflen) { @@ -393,7 +392,7 @@ static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames) dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes); }
- cp_fields(dsb, frames, &dsb->freqAcc); + cp_fields(dsb, frames, &dsb->freqAccNum); }
static void DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT frames) @@ -505,7 +504,7 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mi mixlen = 2 * dsb->device->fraglen; writepos += primary_done; dsb->sec_mixpos += (primary_done / dsb->device->pwfx->nBlockAlign) * - dsb->pwfx->nBlockAlign * dsb->freqAdjust; + dsb->pwfx->nBlockAlign * dsb->freqAdjustNum / dsb->freqAdjustDen; } }