Owen Rudge : dsound: Add support for 32-bit IEEE float buffers.

Alexandre Julliard julliard at winehq.org
Thu Jan 20 12:41:24 CST 2011


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

Author: Owen Rudge <orudge at codeweavers.com>
Date:   Thu Jan 20 15:41:04 2011 +0000

dsound: Add support for 32-bit IEEE float buffers.

---

 dlls/dsound/dsound.c         |    4 +-
 dlls/dsound/dsound_convert.c |  113 +++++++++++++++++++++++++++++++++++++++++-
 dlls/dsound/dsound_private.h |    2 +-
 dlls/dsound/mixer.c          |   20 +++++++-
 include/mmreg.h              |    1 +
 5 files changed, 134 insertions(+), 6 deletions(-)

diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 83636c2..8c1b812 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -1591,14 +1591,14 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
 
             /* cbSize should be 22 bytes, with one possible exception */
             if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) &&
-                !(IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) &&
+                !((IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM) || IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) &&
                 pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
             {
                 WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
                 return DSERR_CONTROLUNAVAIL;
             }
 
-            if (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
+            if ((!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) && (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
             {
                 if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
                     FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c
index 0a6e474..057ae16 100644
--- a/dlls/dsound/dsound_convert.c
+++ b/dlls/dsound/dsound_convert.c
@@ -1,6 +1,7 @@
 /* DirectSound format conversion and mixing routines
  *
  * Copyright 2007 Maarten Lankhorst
+ * Copyright 2011 Owen Rudge for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -295,11 +296,121 @@ static void convert_32_to_32 (const void *src, void *dst, UINT src_stride,
     }
 }
 
-const bitsconvertfunc convertbpp[4][4] = {
+static void convert_ieee_32_to_8 (const void *src, void *dst, UINT src_stride,
+        UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+    while (count > 0)
+    {
+        DWORD src_le = le32(*(DWORD *) src);
+        float v = *((float *) &src_le);
+        INT8 d = 0;
+
+        if (v < -1.0f)
+            d = -128;
+        else if (v >  1.0f)
+            d = 127;
+        else
+            d = v * 127.5f - 0.5f;
+
+        *(BYTE *) dst = d ^ 0x80;
+
+        dst = (char *)dst + dst_stride;
+        src_advance(&src, src_stride, &count, &freqAcc, adj);
+    }
+}
+
+static void convert_ieee_32_to_16 (const void *src, void *dst, UINT src_stride,
+        UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+    while (count > 0)
+    {
+        DWORD src_le = le32(*(DWORD *) src);
+        float v = *((float *) &src_le);
+
+        INT16 *d = (INT16 *) dst;
+
+        if (v < -1.0f)
+            *d = -32768;
+        else if (v >  1.0f)
+            *d = 32767;
+        else
+            *d = v * 32767.5f - 0.5f;
+
+        *d = le16(*d);
+
+        dst = (char *)dst + dst_stride;
+        src_advance(&src, src_stride, &count, &freqAcc, adj);
+    }
+}
+
+static void convert_ieee_32_to_24 (const void *src, void *dst, UINT src_stride,
+        UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+    while (count > 0)
+    {
+        DWORD src_le = le32(*(DWORD *) src);
+        float v = *((float *) &src_le);
+        BYTE *dest24 = dst;
+
+        if (v < -1.0f)
+        {
+            dest24[0] = 0;
+            dest24[1] = 0;
+            dest24[2] = 0x80;
+        }
+        else if (v > 1.0f)
+        {
+            dest24[0] = 0xff;
+            dest24[1] = 0xff;
+            dest24[2] = 0x7f;
+        }
+        else if (v < 0.0f)
+        {
+            dest24[0] = v * 8388608.0f;
+            dest24[1] = v * 32768.0f;
+            dest24[2] = v * 128.0f;
+        }
+        else if (v >= 0.0f)
+        {
+            dest24[0] = v * 8388608.0f;
+            dest24[1] = v * 32768.0f;
+            dest24[2] = v * 127.0f;
+        }
+
+        dst = (char *)dst + dst_stride;
+        src_advance(&src, src_stride, &count, &freqAcc, adj);
+    }
+}
+
+static void convert_ieee_32_to_32 (const void *src, void *dst, UINT src_stride,
+        UINT dst_stride, INT count, UINT freqAcc, UINT adj)
+{
+    while (count > 0)
+    {
+        DWORD src_le = le32(*(DWORD *) src);
+        float v = *((float *) &src_le);
+        INT32 *d = (INT32 *) dst;
+
+        if (v < -1.0f)
+            *d = -2147483647 - 1; /* silence warning */
+        else if (v >  1.0f)
+            *d = 2147483647;
+        else
+            *d = v * 2147483647.5f - 0.5f;
+
+        *d = le32(*d);
+
+        dst = (char *)dst + dst_stride;
+        src_advance(&src, src_stride, &count, &freqAcc, adj);
+    }
+}
+
+const bitsconvertfunc convertbpp[5][4] = {
     { convert_8_to_8, convert_8_to_16, convert_8_to_24, convert_8_to_32 },
     { convert_16_to_8, convert_16_to_16, convert_16_to_24, convert_16_to_32 },
     { convert_24_to_8, convert_24_to_16, convert_24_to_24, convert_24_to_32 },
     { convert_32_to_8, convert_32_to_16, convert_32_to_24, convert_32_to_32 },
+    { convert_ieee_32_to_8, convert_ieee_32_to_16, convert_ieee_32_to_24, convert_ieee_32_to_32 },
 };
 
 static void mix8(signed char *src, INT *dst, unsigned len)
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 1b25ddd..542b997 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -65,7 +65,7 @@ typedef struct DirectSoundCaptureDevice      DirectSoundCaptureDevice;
 
 /* dsound_convert.h */
 typedef void (*bitsconvertfunc)(const void *, void *, UINT, UINT, INT, UINT, UINT);
-extern const bitsconvertfunc convertbpp[4][4];
+extern const bitsconvertfunc convertbpp[5][4];
 typedef void (*mixfunc)(const void *, void *, unsigned);
 extern const mixfunc mixfunctions[4];
 typedef void (*normfunc)(const void *, void *, unsigned);
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 185df6e..e08cbca 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -5,6 +5,7 @@
  * Copyright 2000-2002 TransGaming Technologies, Inc.
  * Copyright 2007 Peter Dons Tychsen
  * Copyright 2007 Maarten Lankhorst
+ * Copyright 2011 Owen Rudge for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,9 +31,13 @@
 #include "windef.h"
 #include "winbase.h"
 #include "mmsystem.h"
+#include "wingdi.h"
+#include "mmreg.h"
 #include "winternl.h"
 #include "wine/debug.h"
 #include "dsound.h"
+#include "ks.h"
+#include "ksmedia.h"
 #include "dsdriver.h"
 #include "dsound_private.h"
 
@@ -177,21 +182,32 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
 {
 	BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec);
 	DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign;
+	WAVEFORMATEXTENSIBLE *pwfxe;
+	BOOL ieee = FALSE;
 
 	TRACE("(%p)\n",dsb);
 
+	pwfxe = (WAVEFORMATEXTENSIBLE *) dsb->pwfx;
+
+	if ((pwfxe->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) || ((pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+	    && (IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))))
+		ieee = TRUE;
+
 	/* calculate the 10ms write lead */
 	dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign;
 
 	if ((dsb->pwfx->wBitsPerSample == dsb->device->pwfx->wBitsPerSample) &&
-	    (dsb->pwfx->nChannels == dsb->device->pwfx->nChannels) && !needresample)
+	    (dsb->pwfx->nChannels == dsb->device->pwfx->nChannels) && !needresample && !ieee)
 		needremix = FALSE;
 	HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer);
 	dsb->tmp_buffer = NULL;
 	dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0;
 	dsb->freqneeded = needresample;
 
-	dsb->convert = convertbpp[dsb->pwfx->wBitsPerSample/8 - 1][dsb->device->pwfx->wBitsPerSample/8 - 1];
+	if (ieee)
+		dsb->convert = convertbpp[4][dsb->device->pwfx->wBitsPerSample/8 - 1];
+	else
+		dsb->convert = convertbpp[dsb->pwfx->wBitsPerSample/8 - 1][dsb->device->pwfx->wBitsPerSample/8 - 1];
 
 	dsb->resampleinmixer = FALSE;
 
diff --git a/include/mmreg.h b/include/mmreg.h
index dca8b58..64a3991 100644
--- a/include/mmreg.h
+++ b/include/mmreg.h
@@ -74,6 +74,7 @@ typedef struct _WAVEFORMATEX {
 /* WAVE form wFormatTag IDs */
 #define  WAVE_FORMAT_UNKNOWN			0x0000	/*  Microsoft Corporation  */
 #define  WAVE_FORMAT_ADPCM			0x0002	/*  Microsoft Corporation  */
+#define  WAVE_FORMAT_IEEE_FLOAT			0x0003	/*  Microsoft Corporation  */
 #define  WAVE_FORMAT_IBM_CVSD			0x0005	/*  IBM Corporation  */
 #define  WAVE_FORMAT_ALAW			0x0006	/*  Microsoft Corporation  */
 #define  WAVE_FORMAT_MULAW			0x0007	/*  Microsoft Corporation  */




More information about the wine-cvs mailing list