Commit d6f3ca95 authored by Owen Rudge's avatar Owen Rudge Committed by Alexandre Julliard

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

parent 7571fb54
...@@ -1591,14 +1591,14 @@ HRESULT DirectSoundDevice_CreateSoundBuffer( ...@@ -1591,14 +1591,14 @@ HRESULT DirectSoundDevice_CreateSoundBuffer(
/* cbSize should be 22 bytes, with one possible exception */ /* cbSize should be 22 bytes, with one possible exception */
if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX)) && 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))) pwfxe->Format.cbSize == sizeof(WAVEFORMATEXTENSIBLE)))
{ {
WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize); WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize);
return DSERR_CONTROLUNAVAIL; 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)) if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL))
FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat)); FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat));
......
/* DirectSound format conversion and mixing routines /* DirectSound format conversion and mixing routines
* *
* Copyright 2007 Maarten Lankhorst * Copyright 2007 Maarten Lankhorst
* Copyright 2011 Owen Rudge for CodeWeavers
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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, ...@@ -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_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_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_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_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) static void mix8(signed char *src, INT *dst, unsigned len)
......
...@@ -65,7 +65,7 @@ typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice; ...@@ -65,7 +65,7 @@ typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice;
/* dsound_convert.h */ /* dsound_convert.h */
typedef void (*bitsconvertfunc)(const void *, void *, UINT, UINT, INT, UINT, UINT); 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); typedef void (*mixfunc)(const void *, void *, unsigned);
extern const mixfunc mixfunctions[4]; extern const mixfunc mixfunctions[4];
typedef void (*normfunc)(const void *, void *, unsigned); typedef void (*normfunc)(const void *, void *, unsigned);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* Copyright 2000-2002 TransGaming Technologies, Inc. * Copyright 2000-2002 TransGaming Technologies, Inc.
* Copyright 2007 Peter Dons Tychsen * Copyright 2007 Peter Dons Tychsen
* Copyright 2007 Maarten Lankhorst * Copyright 2007 Maarten Lankhorst
* Copyright 2011 Owen Rudge for CodeWeavers
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -30,9 +31,13 @@ ...@@ -30,9 +31,13 @@
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "mmsystem.h" #include "mmsystem.h"
#include "wingdi.h"
#include "mmreg.h"
#include "winternl.h" #include "winternl.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "dsound.h" #include "dsound.h"
#include "ks.h"
#include "ksmedia.h"
#include "dsdriver.h" #include "dsdriver.h"
#include "dsound_private.h" #include "dsound_private.h"
...@@ -177,21 +182,32 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) ...@@ -177,21 +182,32 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
{ {
BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec); BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec);
DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign; DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign;
WAVEFORMATEXTENSIBLE *pwfxe;
BOOL ieee = FALSE;
TRACE("(%p)\n",dsb); 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 */ /* calculate the 10ms write lead */
dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign; dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign;
if ((dsb->pwfx->wBitsPerSample == dsb->device->pwfx->wBitsPerSample) && 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; needremix = FALSE;
HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer); HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer);
dsb->tmp_buffer = NULL; dsb->tmp_buffer = NULL;
dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0; dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0;
dsb->freqneeded = needresample; 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; dsb->resampleinmixer = FALSE;
......
...@@ -74,6 +74,7 @@ typedef struct _WAVEFORMATEX { ...@@ -74,6 +74,7 @@ typedef struct _WAVEFORMATEX {
/* WAVE form wFormatTag IDs */ /* WAVE form wFormatTag IDs */
#define WAVE_FORMAT_UNKNOWN 0x0000 /* Microsoft Corporation */ #define WAVE_FORMAT_UNKNOWN 0x0000 /* Microsoft Corporation */
#define WAVE_FORMAT_ADPCM 0x0002 /* 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_IBM_CVSD 0x0005 /* IBM Corporation */
#define WAVE_FORMAT_ALAW 0x0006 /* Microsoft Corporation */ #define WAVE_FORMAT_ALAW 0x0006 /* Microsoft Corporation */
#define WAVE_FORMAT_MULAW 0x0007 /* Microsoft Corporation */ #define WAVE_FORMAT_MULAW 0x0007 /* Microsoft Corporation */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment