[PATCH] dsound: Add support for 24/32 bits input sound buffers

Maarten Lankhorst maarten at codeweavers.com
Sat Oct 13 13:00:58 CDT 2007


This makes cp_fields simpler and more generic
---
 dlls/dsound/Makefile.in      |    1 +
 dlls/dsound/dsound_convert.c |  172 ++++++++++++++++++++++++++++++++++++++++++
 dlls/dsound/dsound_private.h |    6 +-
 dlls/dsound/mixer.c          |   84 +++++---------------
 4 files changed, 199 insertions(+), 64 deletions(-)
 create mode 100644 dlls/dsound/dsound_convert.c

diff --git a/dlls/dsound/Makefile.in b/dlls/dsound/Makefile.in
index 12f3fe7..c7e8345 100644
--- a/dlls/dsound/Makefile.in
+++ b/dlls/dsound/Makefile.in
@@ -11,6 +11,7 @@ C_SRCS = \
 	buffer.c \
 	capture.c \
 	dsound.c \
+	dsound_convert.c \
 	dsound_main.c \
 	duplex.c \
 	mixer.c \
diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c
new file mode 100644
index 0000000..ab7e288
--- /dev/null
+++ b/dlls/dsound/dsound_convert.c
@@ -0,0 +1,172 @@
+/* DirectSound format conversion and mixing routines
+ *
+ * Copyright 2007 Maarten Lankhorst
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* 8 bits is unsigned, the rest is signed.
+ * First I tried to reuse existing stuff from alsa-lib, after that
+ * didn't work, I gave up and just went for individual hacks.
+ *
+ * 24 bit is expensive to do, due to unaligned access.
+ * In dlls/winex11.drv/dib_convert.c convert_888_to_0888_asis there is a way
+ * around it, but I'm happy current code works, maybe something for later.
+ *
+ * The ^ 0x80 flips the signed bit, this is the conversion from
+ * signed (-128.. 0.. 127) to unsigned (0...255)
+ * This is only temporary: All 8 bit data should be converted to signed.
+ * then when fed to the sound card, it should be converted to unsigned again.
+ */
+
+#include "config.h"
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdarg.h>
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+#include "windef.h"
+#include "winbase.h"
+#include "mmsystem.h"
+#include "winternl.h"
+#include "wine/debug.h"
+#include "dsound.h"
+#include "dsdriver.h"
+#include "dsound_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dsound);
+
+typedef struct {
+    uint8_t byte[3];
+} int24_struct;
+
+static void convert_8_to_8 (const void *src, void *dst)
+{
+    uint8_t *dest = dst;
+    *dest = *(uint8_t*)src;
+}
+
+static void convert_8_to_16 (const void *src, void *dst)
+{
+    uint16_t dest = *(uint8_t*)src, *dest16 = dst;
+    *dest16 = dest + (dest << 8) - (1 << 15);
+}
+
+static void convert_8_to_24 (const void *src, void *dst)
+{
+    uint8_t dest = *(uint8_t*)src ^ 0x80;
+    int24_struct *dest24 = dst;
+    dest24->byte[0] = dest;
+    dest24->byte[1] = dest;
+    dest24->byte[2] = dest;
+}
+
+static void convert_8_to_32 (const void *src, void *dst)
+{
+    uint32_t dest = *(uint8_t*)src, *dest32 = dst;
+    *dest32 = dest + (dest << 8) + (dest << 16) + (dest << 24) - (1 << 31);
+}
+
+static void convert_16_to_8 (const void *src, void *dst)
+{
+    uint8_t *dst8 = dst;
+    *dst8 = ((*(uint16_t*)src) >> 8)^(uint8_t)0x80;
+}
+
+static void convert_16_to_16 (const void *src, void *dst)
+{
+    uint16_t *dest = dst;
+    *dest = *(uint16_t*)src;
+}
+
+static void convert_16_to_24 (const void *src, void *dst)
+{
+    uint16_t dest = *(uint16_t*)src;
+    int24_struct *dest24 = dst;
+
+    dest24->byte[0] = dest >> 8;
+    dest24->byte[1] = dest;
+    dest24->byte[2] = dest >> 8;
+}
+
+static void convert_16_to_32 (const void *src, void *dst)
+{
+    uint32_t dest = *(uint16_t*)src, *dest32 = dst;
+    *dest32 = dest + (dest << 16);
+}
+
+static void convert_24_to_8 (const void *src, void *dst)
+{
+    uint8_t *dst8 = dst;
+    *dst8 = ((int24_struct*)src)->byte[2];
+}
+
+static void convert_24_to_16 (const void *src, void *dst)
+{
+    uint16_t *dest16 = dst;
+    const int24_struct *source = src;
+    *dest16 = (source->byte[2] << 8) + source->byte[1];
+}
+
+static void convert_24_to_24 (const void *src, void *dst)
+{
+    int24_struct *dest24 = dst;
+    const int24_struct *src24 = src;
+    *dest24 = *src24;
+}
+
+static void convert_24_to_32 (const void *src, void *dst)
+{
+    uint32_t *dest32 = dst;
+    const int24_struct *source = src;
+    *dest32 = (source->byte[2] << 24) + (source->byte[1] << 16) + (source->byte[0] << 8) + source->byte[2];
+}
+
+static void convert_32_to_8 (const void *src, void *dst)
+{
+    uint8_t *dst8 = dst;
+    *dst8 = ((*(uint32_t*)src) >> 24)^(uint8_t)0x80;
+}
+
+static void convert_32_to_16 (const void *src, void *dst)
+{
+    uint16_t *dest16 = dst;
+    *dest16 = (*(uint32_t*)src) >> 16;
+}
+
+static void convert_32_to_24 (const void *src, void *dst)
+{
+    uint32_t dest = *(uint32_t*)dst;
+    int24_struct *dest24 = dst;
+
+    dest24->byte[0] = dest >> 8;
+    dest24->byte[1] = dest >> 16;
+    dest24->byte[2] = dest >> 24;
+}
+
+static void convert_32_to_32 (const void *src, void *dst)
+{
+    uint32_t *dest = dst;
+    *dest = *(uint32_t*)src;
+}
+
+bitsconvertfunc convertbpp[4][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 },
+};
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 33f9265..92133c2 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -69,6 +69,10 @@ typedef struct SecondaryBufferImpl           SecondaryBufferImpl;
 typedef struct DirectSoundDevice             DirectSoundDevice;
 typedef struct DirectSoundCaptureDevice      DirectSoundCaptureDevice;
 
+/* dsound_convert.h */
+typedef void (*bitsconvertfunc)(const void *, void *);
+extern bitsconvertfunc convertbpp[4][4];
+
 /*****************************************************************************
  * IDirectSoundDevice implementation structure
  */
@@ -188,7 +192,7 @@ struct IDirectSoundBufferImpl
 
     /* IKsPropertySet fields */
     IKsBufferPropertySetImpl*   iks;
-
+    bitsconvertfunc convert;
     struct list entry;
 };
 
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index daa4e97..975bffd 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -29,7 +29,6 @@
 #define NONAMELESSUNION
 #include "windef.h"
 #include "winbase.h"
-#include "winuser.h"
 #include "mmsystem.h"
 #include "winternl.h"
 #include "wine/debug.h"
@@ -179,6 +178,8 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
 	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 (needremix)
 	{
 		if (needresample)
@@ -246,74 +247,31 @@ void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len
 	}
 }
 
-/* WAV format info can be found at:
- *
- *    http://www.cwi.nl/ftp/audio/AudioFormats.part2
- *    ftp://ftp.cwi.nl/pub/audio/RIFF-format
- *
- * Import points to remember:
- *    8-bit WAV is unsigned
- *    16-bit WAV is signed
- */
- /* Use the same formulas as pcmconverter.c */
-static inline INT16 cvtU8toS16(BYTE b)
-{
-    return (short)((b+(b << 8))-32768);
-}
-
-static inline BYTE cvtS16toU8(INT16 s)
-{
-    return (s >> 8) ^ (unsigned char)0x80;
-}
-
 /**
  * Copy a single frame from the given input buffer to the given output buffer.
  * Translate 8 <-> 16 bits and mono <-> stereo
  */
 static inline void cp_fields(const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf )
 {
-	DirectSoundDevice * device = dsb->device;
-        INT fl,fr;
-
-        if (dsb->pwfx->wBitsPerSample == 8)  {
-                if (device->pwfx->wBitsPerSample == 8 &&
-                    device->pwfx->nChannels == dsb->pwfx->nChannels) {
-                        /* avoid needless 8->16->8 conversion */
-                        *obuf=*ibuf;
-                        if (dsb->pwfx->nChannels==2)
-                                *(obuf+1)=*(ibuf+1);
-                        return;
-                }
-                fl = cvtU8toS16(*ibuf);
-                fr = (dsb->pwfx->nChannels==2 ? cvtU8toS16(*(ibuf + 1)) : fl);
-        } else {
-                fl = *((const INT16 *)ibuf);
-                fr = (dsb->pwfx->nChannels==2 ? *(((const INT16 *)ibuf) + 1)  : fl);
-        }
-
-        if (device->pwfx->nChannels == 2) {
-                if (device->pwfx->wBitsPerSample == 8) {
-                        *obuf = cvtS16toU8(fl);
-                        *(obuf + 1) = cvtS16toU8(fr);
-                        return;
-                }
-                if (device->pwfx->wBitsPerSample == 16) {
-                        *((INT16 *)obuf) = fl;
-                        *(((INT16 *)obuf) + 1) = fr;
-                        return;
-                }
-        }
-        if (device->pwfx->nChannels == 1) {
-                fl = (fl + fr) >> 1;
-                if (device->pwfx->wBitsPerSample == 8) {
-                        *obuf = cvtS16toU8(fl);
-                        return;
-                }
-                if (device->pwfx->wBitsPerSample == 16) {
-                        *((INT16 *)obuf) = fl;
-                        return;
-                }
-        }
+    DirectSoundDevice *device = dsb->device;
+    INT istep = dsb->pwfx->wBitsPerSample / 8, ostep = device->pwfx->wBitsPerSample / 8;
+
+    if (device->pwfx->nChannels == dsb->pwfx->nChannels) {
+        dsb->convert(ibuf, obuf);
+        if (device->pwfx->nChannels == 2)
+            dsb->convert(ibuf + istep, obuf + ostep);
+    }
+
+    if (device->pwfx->nChannels == 1 && dsb->pwfx->nChannels == 2)
+    {
+        dsb->convert(ibuf, obuf);
+    }
+
+    if (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 1)
+    {
+        dsb->convert(ibuf, obuf);
+        dsb->convert(ibuf, obuf + ostep);
+    }
 }
 
 /**
-- 
1.5.2.5


--------------050107040208010609050901--



More information about the wine-patches mailing list