[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