Module: wine Branch: master Commit: d6f3ca958901d4caff78fd19517ed69cc3ad1c3c URL: http://source.winehq.org/git/wine.git/?a=commit;h=d6f3ca958901d4caff78fd1951...
Author: Owen Rudge orudge@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 */