Marton Balint : dsound: Convert freqAdjust and freqAcc to integers.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Dec 29 15:42:43 CST 2014


Module: wine
Branch: master
Commit: 6d009b988b22212fabcc34711c40ec776fecaec5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6d009b988b22212fabcc34711c40ec776fecaec5

Author: Marton Balint <cus at 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;
 		}
 	}
 




More information about the wine-cvs mailing list