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(
/* 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));
......
/* 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)
......
......@@ -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);
......
......@@ -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,20 +182,31 @@ 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;
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;
......
......@@ -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 */
......
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