Merge pull request #311 from maharmstone/master

Adds support for Environmental Audio Extensions (EAX).
This commit is contained in:
Sebastian Lackner 2015-03-28 21:17:21 +01:00
commit cd5078fa95
21 changed files with 2625 additions and 15 deletions

View File

@ -38,13 +38,14 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [5]:**
**Bugfixes and features included in the next upcoming release [6]:**
* Add stubs for Power[Set|Clear]Request
* Avoid spam of FIXME messages for PsLookupProcessByProcessId stub ([Wine Bug #36821](https://bugs.winehq.org/show_bug.cgi?id=36821))
* Fix compatibility of Uplay with gnutls28 ([Wine Bug #38134](https://bugs.winehq.org/show_bug.cgi?id=38134))
* Fix handling of ANSI NTLM credentials ([Wine Bug #37063](https://bugs.winehq.org/show_bug.cgi?id=37063))
* Implement empty enumerator for IWiaDevMgr::EnumDeviceInfo ([Wine Bug #27775](https://bugs.winehq.org/show_bug.cgi?id=27775))
* Software support for Environmental Audio Extensions (EAX)
**Bugs fixed in Wine Staging 1.7.39 [205]:**

1
debian/changelog vendored
View File

@ -5,6 +5,7 @@ wine-staging (1.7.40) UNRELEASED; urgency=low
* Added patch to implement empty enumerator for IWiaDevMgr::EnumDeviceInfo.
* Added patch to fix handling of ANSI NTLM credentials.
* Added patch to fix compatibility of Uplay with gnutls28.
* Added patches for Environmental Audio Extensions (EAX), pull request #311 from Mark Harmstone.
* Removed patch to fix regression causing black screen on startup (accepted upstream).
* Removed patch to fix edge cases in TOOLTIPS_GetTipText (fixed upstream).
* Removed patch for IConnectionPoint/INetworkListManagerEvents stub interface (accepted upstream).

View File

@ -0,0 +1,229 @@
From dd8497b40ae145da74ca9aeb8aab274572328bbd Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 28 Mar 2015 08:18:10 +0100
Subject: dsound: Apply filters before sound is multiplied to speakers.
Based on a patch by Mark Harmstone.
---
dlls/dsound/dsound.c | 1 +
dlls/dsound/dsound_private.h | 4 +-
dlls/dsound/mixer.c | 104 ++++++++++++++++++++++++++++++-------------
3 files changed, 77 insertions(+), 32 deletions(-)
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
index 065c377..ed0bbba 100644
--- a/dlls/dsound/dsound.c
+++ b/dlls/dsound/dsound.c
@@ -238,6 +238,7 @@ static ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
if(device->volume)
IAudioStreamVolume_Release(device->volume);
+ HeapFree(GetProcessHeap(), 0, device->dsp_buffer);
HeapFree(GetProcessHeap(), 0, device->tmp_buffer);
HeapFree(GetProcessHeap(), 0, device->mix_buffer);
HeapFree(GetProcessHeap(), 0, device->buffer);
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 726452c..ed645db 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -91,8 +91,8 @@ struct DirectSoundDevice
int speaker_num[DS_MAX_CHANNELS];
int num_speakers;
int lfe_channel;
- float *mix_buffer, *tmp_buffer;
- DWORD tmp_buffer_len, mix_buffer_len;
+ float *mix_buffer, *tmp_buffer, *dsp_buffer;
+ DWORD mix_buffer_len, tmp_buffer_len, dsp_buffer_len;
DSVOLUMEPAN volpan;
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 4f22f85..ff92cc1 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -266,23 +266,22 @@ static inline float get_current_sample(const IDirectSoundBufferImpl *dsb,
return dsb->get(dsb, mixpos % dsb->buflen, channel);
}
-static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count)
+static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, bitsputfunc put, UINT ostride, UINT count)
{
UINT istride = dsb->pwfx->nBlockAlign;
- UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
DWORD channel, i;
for (i = 0; i < count; i++)
for (channel = 0; channel < dsb->mix_channels; channel++)
- dsb->put(dsb, i * ostride, channel, get_current_sample(dsb,
- dsb->sec_mixpos + i * istride, channel));
+ put(dsb, i * ostride, channel, get_current_sample(dsb,
+ dsb->sec_mixpos + i * istride, channel));
return count;
}
-static UINT cp_fields_resample_lq(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
+static UINT cp_fields_resample_lq(IDirectSoundBufferImpl *dsb, bitsputfunc put,
+ UINT ostride, UINT count, LONG64 *freqAccNum)
{
UINT i, channel;
UINT istride = dsb->pwfx->nBlockAlign;
- UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
UINT channels = dsb->mix_channels;
LONG64 freqAcc_start = *freqAccNum;
@@ -310,7 +309,7 @@ static UINT cp_fields_resample_lq(IDirectSoundBufferImpl *dsb, UINT count, LONG6
float s1 = get_current_sample(dsb, idx, channel);
float s2 = get_current_sample(dsb, idx + istride, channel);
float result = s1 * cur_freqAcc2 + s2 * cur_freqAcc;
- dsb->put(dsb, i * ostride, channel, result);
+ put(dsb, i * ostride, channel, result);
}
}
@@ -318,11 +317,11 @@ static UINT cp_fields_resample_lq(IDirectSoundBufferImpl *dsb, UINT count, LONG6
return max_ipos;
}
-static UINT cp_fields_resample_hq(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
+static UINT cp_fields_resample_hq(IDirectSoundBufferImpl *dsb, bitsputfunc put,
+ UINT ostride, UINT count, LONG64 *freqAccNum)
{
UINT i, channel;
UINT istride = dsb->pwfx->nBlockAlign;
- UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
LONG64 freqAcc_start = *freqAccNum;
LONG64 freqAcc_end = freqAcc_start + count * dsb->freqAdjustNum;
@@ -372,7 +371,7 @@ static UINT cp_fields_resample_hq(IDirectSoundBufferImpl *dsb, UINT count, LONG6
float* cache = &intermediate[channel * required_input + ipos];
for (j = 0; j < fir_used; j++)
sum += fir_copy[j] * cache[j];
- dsb->put(dsb, i * ostride, channel, sum * dsb->firgain);
+ put(dsb, i * ostride, channel, sum * dsb->firgain);
}
}
@@ -384,16 +383,17 @@ static UINT cp_fields_resample_hq(IDirectSoundBufferImpl *dsb, UINT count, LONG6
return max_ipos;
}
-static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
+static void cp_fields(IDirectSoundBufferImpl *dsb, bitsputfunc put,
+ UINT ostride, UINT count, LONG64 *freqAccNum)
{
DWORD ipos, adv;
if (dsb->freqAdjustNum == dsb->freqAdjustDen)
- adv = cp_fields_noresample(dsb, count); /* *freqAcc is unmodified */
+ adv = cp_fields_noresample(dsb, put, ostride, count); /* *freqAcc is unmodified */
else if (dsb->device->nrofbuffers > ds_hq_buffers_max)
- adv = cp_fields_resample_lq(dsb, count, freqAccNum);
+ adv = cp_fields_resample_lq(dsb, put, ostride, count, freqAccNum);
else
- adv = cp_fields_resample_hq(dsb, count, freqAccNum);
+ adv = cp_fields_resample_hq(dsb, put, ostride, count, freqAccNum);
ipos = dsb->sec_mixpos + adv * dsb->pwfx->nBlockAlign;
if (ipos >= dsb->buflen) {
@@ -423,6 +423,21 @@ static inline DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
return buflen + ptr1 - ptr2;
}
}
+
+static float getieee32_dsp(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel)
+{
+ const BYTE *buf = (BYTE *)dsb->device->dsp_buffer;
+ const float *fbuf = (const float*)(buf + pos + sizeof(float) * channel);
+ return *fbuf;
+}
+
+static void putieee32_dsp(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value)
+{
+ BYTE *buf = (BYTE *)dsb->device->dsp_buffer;
+ float *fbuf = (float*)(buf + pos + sizeof(float) * channel);
+ *fbuf = value;
+}
+
/**
* Mix at most the given amount of data into the allocated temporary buffer
* of the given secondary buffer, starting from the dsb's first currently
@@ -438,32 +453,61 @@ static inline DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2)
*/
static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames)
{
- UINT size_bytes = frames * sizeof(float) * dsb->device->pwfx->nChannels;
+ BOOL using_filters = dsb->num_filters > 0;
+ UINT istride, ostride, size_bytes;
+ DWORD channel, i;
+ bitsputfunc put;
HRESULT hr;
- int i;
- if (dsb->device->tmp_buffer_len < size_bytes || !dsb->device->tmp_buffer)
- {
- dsb->device->tmp_buffer_len = size_bytes;
+ put = dsb->put;
+ ostride = dsb->device->pwfx->nChannels * sizeof(float);
+ size_bytes = frames * ostride;
+
+ if (dsb->device->tmp_buffer_len < size_bytes || !dsb->device->tmp_buffer) {
if (dsb->device->tmp_buffer)
dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, size_bytes);
else
dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes);
+ dsb->device->tmp_buffer_len = size_bytes;
}
- cp_fields(dsb, frames, &dsb->freqAccNum);
+ if (using_filters) {
+ put = putieee32_dsp;
+ ostride = dsb->mix_channels * sizeof(float);
+ size_bytes = frames * ostride;
+
+ if (dsb->device->dsp_buffer_len < size_bytes || !dsb->device->dsp_buffer) {
+ if (dsb->device->dsp_buffer)
+ dsb->device->dsp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->dsp_buffer, size_bytes);
+ else
+ dsb->device->dsp_buffer = HeapAlloc(GetProcessHeap(), 0, size_bytes);
+ dsb->device->dsp_buffer_len = size_bytes;
+ }
+ }
- if (size_bytes > 0) {
- for (i = 0; i < dsb->num_filters; i++) {
- if (dsb->filters[i].inplace) {
- hr = IMediaObjectInPlace_Process(dsb->filters[i].inplace, size_bytes, (BYTE*)dsb->device->tmp_buffer, 0, DMO_INPLACE_NORMAL);
+ cp_fields(dsb, put, ostride, frames, &dsb->freqAccNum);
+
+ if (using_filters) {
+ if (frames > 0) {
+ for (i = 0; i < dsb->num_filters; i++) {
+ if (dsb->filters[i].inplace) {
+ hr = IMediaObjectInPlace_Process(dsb->filters[i].inplace, frames * sizeof(float) * dsb->mix_channels,
+ (BYTE *)dsb->device->dsp_buffer, 0, DMO_INPLACE_NORMAL);
+ if (FAILED(hr))
+ WARN("IMediaObjectInPlace_Process failed for filter %u\n", i);
+ } else
+ WARN("filter %u has no inplace object - unsupported\n", i);
+ }
+ }
- if (FAILED(hr))
- WARN("IMediaObjectInPlace_Process failed for filter %u\n", i);
- } else
- WARN("filter %u has no inplace object - unsupported\n", i);
- }
- }
+ istride = ostride;
+ ostride = dsb->device->pwfx->nChannels * sizeof(float);
+ for (i = 0; i < frames; i++) {
+ for (channel = 0; channel < dsb->mix_channels; channel++) {
+ dsb->put(dsb, i * ostride, channel, getieee32_dsp(dsb, i * istride, channel));
+ }
+ }
+ }
}
static void DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT frames)
--
2.3.3

View File

@ -0,0 +1,121 @@
From b95848a7794ff437b58f1a307da8c8fdca6a362f Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 15 Mar 2015 18:04:16 +0000
Subject: dsound: Add EAX v1 constants and structs.
---
dlls/dsound/dsound_eax.h | 89 ++++++++++++++++++++++++++++++++++++++++++++
dlls/dsound/dsound_private.h | 1 +
2 files changed, 90 insertions(+)
create mode 100644 dlls/dsound/dsound_eax.h
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
new file mode 100644
index 0000000..600029f
--- /dev/null
+++ b/dlls/dsound/dsound_eax.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 Mark Harmstone
+ *
+ * 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
+ */
+
+#ifndef DSOUND_EAX_H_DEFINED
+#define DSOUND_EAX_H_DEFINED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DEFINE_GUID(DSPROPSETID_EAX_ReverbProperties, 0x4a4e6fc1, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
+DEFINE_GUID(DSPROPSETID_EAXBUFFER_ReverbProperties, 0x4a4e6fc0, 0xc341, 0x11d1, 0xb7, 0x3a, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
+
+typedef enum {
+ DSPROPERTY_EAX_ALL,
+ DSPROPERTY_EAX_ENVIRONMENT,
+ DSPROPERTY_EAX_VOLUME,
+ DSPROPERTY_EAX_DECAYTIME,
+ DSPROPERTY_EAX_DAMPING
+} DSPROPERTY_EAX_REVERBPROPERTY;
+
+typedef struct {
+ unsigned long environment;
+ float fVolume;
+ float fDecayTime_sec;
+ float fDamping;
+} EAX_REVERBPROPERTIES;
+
+enum {
+ EAX_ENVIRONMENT_GENERIC,
+ EAX_ENVIRONMENT_PADDEDCELL,
+ EAX_ENVIRONMENT_ROOM,
+ EAX_ENVIRONMENT_BATHROOM,
+ EAX_ENVIRONMENT_LIVINGROOM,
+ EAX_ENVIRONMENT_STONEROOM,
+ EAX_ENVIRONMENT_AUDITORIUM,
+ EAX_ENVIRONMENT_CONCERTHALL,
+ EAX_ENVIRONMENT_CAVE,
+ EAX_ENVIRONMENT_ARENA,
+ EAX_ENVIRONMENT_HANGAR,
+ EAX_ENVIRONMENT_CARPETEDHALLWAY,
+ EAX_ENVIRONMENT_HALLWAY,
+ EAX_ENVIRONMENT_STONECORRIDOR,
+ EAX_ENVIRONMENT_ALLEY,
+ EAX_ENVIRONMENT_FOREST,
+ EAX_ENVIRONMENT_CITY,
+ EAX_ENVIRONMENT_MOUNTAINS,
+ EAX_ENVIRONMENT_QUARRY,
+ EAX_ENVIRONMENT_PLAIN,
+ EAX_ENVIRONMENT_PARKINGLOT,
+ EAX_ENVIRONMENT_SEWERPIPE,
+ EAX_ENVIRONMENT_UNDERWATER,
+ EAX_ENVIRONMENT_DRUGGED,
+ EAX_ENVIRONMENT_DIZZY,
+ EAX_ENVIRONMENT_PSYCHOTIC,
+ EAX_ENVIRONMENT_COUNT
+};
+
+typedef enum {
+ DSPROPERTY_EAXBUFFER_ALL,
+ DSPROPERTY_EAXBUFFER_REVERBMIX
+} DSPROPERTY_EAXBUFFER_REVERBPROPERTY;
+
+typedef struct {
+ float fMix;
+} EAXBUFFER_REVERBPROPERTIES;
+
+#define EAX_REVERBMIX_USEDISTANCE -1.0f
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index ed645db..3c7dc7a 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -29,6 +29,7 @@
#include "mediaobj.h"
#include "mmsystem.h"
#include "uuids.h"
+#include "dsound_eax.h"
#include "wine/list.h"
--
2.3.3

View File

@ -0,0 +1,35 @@
From 8d33bbc39a573848f00c95699ec8c0eee9fdb416 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 15 Mar 2015 18:04:38 +0000
Subject: dsound: Report that we support EAX v1.
---
dlls/dsound/buffer.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index d735dc3..9eff140 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1319,6 +1319,18 @@ static HRESULT WINAPI IKsPropertySetImpl_QuerySupport(IKsPropertySet *iface, REF
TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
+ if (IsEqualGUID(&DSPROPSETID_EAX_ReverbProperties, guidPropSet)) {
+ if (dwPropID <= DSPROPERTY_EAX_DAMPING) {
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
+ return S_OK;
+ }
+ } else if (IsEqualGUID(&DSPROPSETID_EAXBUFFER_ReverbProperties, guidPropSet)) {
+ if (dwPropID <= DSPROPERTY_EAXBUFFER_REVERBMIX) {
+ *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
+ return S_OK;
+ }
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
--
2.3.3

View File

@ -0,0 +1,131 @@
From 601e237d1321fcdea3a678c31fd9eac62b89cfb4 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 13:58:53 +0000
Subject: dsound: Add EAX propset stubs.
---
dlls/dsound/Makefile.in | 1 +
dlls/dsound/buffer.c | 6 +++++
dlls/dsound/dsound_private.h | 8 +++++++
dlls/dsound/eax.c | 54 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 69 insertions(+)
create mode 100644 dlls/dsound/eax.c
diff --git a/dlls/dsound/Makefile.in b/dlls/dsound/Makefile.in
index 6cb653f..1c04bf3 100644
--- a/dlls/dsound/Makefile.in
+++ b/dlls/dsound/Makefile.in
@@ -9,6 +9,7 @@ C_SRCS = \
dsound_convert.c \
dsound_main.c \
duplex.c \
+ eax.c \
mixer.c \
primary.c \
propset.c \
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 9eff140..0596ce3 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1298,6 +1298,9 @@ static HRESULT WINAPI IKsPropertySetImpl_Get(IKsPropertySet *iface, REFGUID guid
TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
+ if (IsEqualGUID(&DSPROPSETID_EAX_ReverbProperties, guidPropSet) || IsEqualGUID(&DSPROPSETID_EAXBUFFER_ReverbProperties, guidPropSet))
+ return EAX_Get(This, guidPropSet, dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
+
return E_PROP_ID_UNSUPPORTED;
}
@@ -1309,6 +1312,9 @@ static HRESULT WINAPI IKsPropertySetImpl_Set(IKsPropertySet *iface, REFGUID guid
TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
+ if (IsEqualGUID(&DSPROPSETID_EAX_ReverbProperties, guidPropSet) || IsEqualGUID(&DSPROPSETID_EAXBUFFER_ReverbProperties, guidPropSet))
+ return EAX_Set(This, guidPropSet, dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData);
+
return E_PROP_ID_UNSUPPORTED;
}
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 3c7dc7a..e4495b2 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -229,6 +229,14 @@ LONG capped_refcount_dec(LONG *ref) DECLSPEC_HIDDEN;
HRESULT DSOUND_FullDuplexCreate(REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+/* eax.c */
+HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
+ ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
+ ULONG cbPropData, ULONG *pcbReturned) DECLSPEC_HIDDEN;
+HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
+ ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
+ ULONG cbPropData) DECLSPEC_HIDDEN;
+
/* mixer.c */
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len) DECLSPEC_HIDDEN;
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
new file mode 100644
index 0000000..c30c7e1
--- /dev/null
+++ b/dlls/dsound/eax.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 Mark Harmstone
+ *
+ * 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
+ */
+
+#include <stdarg.h>
+#include <math.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "mmsystem.h"
+#include "winternl.h"
+#include "vfwmsgs.h"
+#include "wine/debug.h"
+#include "dsound.h"
+#include "dsound_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(eax);
+
+HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
+ ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
+ ULONG cbPropData, ULONG *pcbReturned)
+{
+ TRACE("(buf=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
+ buf, debugstr_guid(guidPropSet), dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
+
+ *pcbReturned = 0;
+
+ return E_PROP_ID_UNSUPPORTED;
+}
+
+HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
+ ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
+ ULONG cbPropData)
+{
+ TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",
+ buf, debugstr_guid(guidPropSet), dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData);
+
+ return E_PROP_ID_UNSUPPORTED;
+}
--
2.3.3

View File

@ -0,0 +1,149 @@
From e46e2000764539dab113dd508b6a20beba953c87 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 14:10:06 +0000
Subject: dsound: Add EAX presets.
---
dlls/dsound/dsound_eax.h | 29 +++++++++++++++++++++++
dlls/dsound/eax.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 600029f..06d961e 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2008-2009 Christopher Fitzgerald
* Copyright (c) 2015 Mark Harmstone
*
* This library is free software; you can redistribute it and/or
@@ -16,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+/* Taken in large part from OpenAL. */
+
#ifndef DSOUND_EAX_H_DEFINED
#define DSOUND_EAX_H_DEFINED
@@ -82,6 +85,32 @@ typedef struct {
#define EAX_REVERBMIX_USEDISTANCE -1.0f
+typedef struct {
+ float flDensity;
+ float flDiffusion;
+ float flGain;
+ float flGainHF;
+ float flGainLF;
+ float flDecayTime;
+ float flDecayHFRatio;
+ float flDecayLFRatio;
+ float flReflectionsGain;
+ float flReflectionsDelay;
+ float flReflectionsPan[3];
+ float flLateReverbGain;
+ float flLateReverbDelay;
+ float flLateReverbPan[3];
+ float flEchoTime;
+ float flEchoDepth;
+ float flModulationTime;
+ float flModulationDepth;
+ float flAirAbsorptionGainHF;
+ float flHFReference;
+ float flLFReference;
+ float flRoomRolloffFactor;
+ int iDecayHFLimit;
+} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
+
#ifdef __cplusplus
}
#endif
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index c30c7e1..57d88e7 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2008-2009 Christopher Fitzgerald
* Copyright (c) 2015 Mark Harmstone
*
* This library is free software; you can redistribute it and/or
@@ -16,6 +17,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+/* Taken in large part from OpenAL's Alc/alcReverb.c. */
+
#include <stdarg.h>
#include <math.h>
@@ -31,6 +34,64 @@
WINE_DEFAULT_DEBUG_CHANNEL(eax);
+static const EAX_REVERBPROPERTIES presets[] = {
+ { EAX_ENVIRONMENT_GENERIC, 0.5f, 1.493f, 0.5f },
+ { EAX_ENVIRONMENT_PADDEDCELL, 0.25f, 0.1f, 0.0f },
+ { EAX_ENVIRONMENT_ROOM, 0.417f, 0.4f, 0.666f },
+ { EAX_ENVIRONMENT_BATHROOM, 0.653f, 1.499f, 0.166f },
+ { EAX_ENVIRONMENT_LIVINGROOM, 0.208f, 0.478f, 0.0f },
+ { EAX_ENVIRONMENT_STONEROOM, 0.5f, 2.309f, 0.888f },
+ { EAX_ENVIRONMENT_AUDITORIUM, 0.403f, 4.279f, 0.5f },
+ { EAX_ENVIRONMENT_CONCERTHALL, 0.5f, 3.961f, 0.5f },
+ { EAX_ENVIRONMENT_CAVE, 0.5f, 2.886f, 1.304f },
+ { EAX_ENVIRONMENT_ARENA, 0.361f, 7.284f, 0.332f },
+ { EAX_ENVIRONMENT_HANGAR, 0.5f, 10.0f, 0.3f },
+ { EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153f, 0.259f, 2.0f },
+ { EAX_ENVIRONMENT_HALLWAY, 0.361f, 1.493f, 0.0f },
+ { EAX_ENVIRONMENT_STONECORRIDOR, 0.444f, 2.697f, 0.638f },
+ { EAX_ENVIRONMENT_ALLEY, 0.25f, 1.752f, 0.776f },
+ { EAX_ENVIRONMENT_FOREST, 0.111f, 3.145f, 0.472f },
+ { EAX_ENVIRONMENT_CITY, 0.111f, 2.767f, 0.224f },
+ { EAX_ENVIRONMENT_MOUNTAINS, 0.194f, 7.841f, 0.472f },
+ { EAX_ENVIRONMENT_QUARRY, 1.0f, 1.499f, 0.5f },
+ { EAX_ENVIRONMENT_PLAIN, 0.097f, 2.767f, 0.224f },
+ { EAX_ENVIRONMENT_PARKINGLOT, 0.208f, 1.652f, 1.5f },
+ { EAX_ENVIRONMENT_SEWERPIPE, 0.652f, 2.886f, 0.25f },
+ { EAX_ENVIRONMENT_UNDERWATER, 1.0f, 1.499f, 0.0f },
+ { EAX_ENVIRONMENT_DRUGGED, 0.875f, 8.392f, 1.388f },
+ { EAX_ENVIRONMENT_DIZZY, 0.139f, 17.234f, 0.666f },
+ { EAX_ENVIRONMENT_PSYCHOTIC, 0.486f, 7.563f, 0.806f }
+};
+
+static const EFXEAXREVERBPROPERTIES efx_presets[] = {
+ { 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* generic */
+ { 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* padded cell */
+ { 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* room */
+ { 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* bathroom */
+ { 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* living room */
+ { 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* stone room */
+ { 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* auditorium */
+ { 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* concert hall */
+ { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }, /* cave */
+ { 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* arena */
+ { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* hangar */
+ { 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* carpeted hallway */
+ { 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* hallway */
+ { 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* stone corridor */
+ { 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* alley */
+ { 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* forest */
+ { 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* city */
+ { 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }, /* mountains */
+ { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* quarry */
+ { 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* plain */
+ { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }, /* parking lot */
+ { 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* sewer pipe */
+ { 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }, /* underwater */
+ { 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }, /* drugged */
+ { 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }, /* dizzy */
+ { 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
+};
+
HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
ULONG cbPropData, ULONG *pcbReturned)
--
2.3.3

View File

@ -0,0 +1,240 @@
From fe1de4d0856517f1ce59a3a5eb15a13f6ce4a9e6 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 14:22:02 +0000
Subject: dsound: Support getting and setting EAX properties.
---
dlls/dsound/dsound_eax.h | 8 +++
dlls/dsound/dsound_private.h | 2 +
dlls/dsound/eax.c | 167 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 06d961e..c90d82d 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -111,6 +111,14 @@ typedef struct {
int iDecayHFLimit;
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
+typedef struct {
+ BOOL using_eax;
+ unsigned long environment;
+ float volume;
+ float damping;
+ EFXEAXREVERBPROPERTIES eax_props;
+} eax_info;
+
#ifdef __cplusplus
}
#endif
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index e4495b2..c16f770 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -99,6 +99,8 @@ struct DirectSoundDevice
normfunc normfunction;
+ eax_info eax;
+
/* DirectSound3DListener fields */
DS3DLISTENER ds3dl;
BOOL ds3dl_need_recalc;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 57d88e7..cdd03be 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,6 +92,22 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
+{
+ /* stub */
+ return TRUE;
+}
+
+static void init_eax(DirectSoundDevice *dev)
+{
+ dev->eax.using_eax = TRUE;
+ dev->eax.environment = presets[0].environment;
+ dev->eax.volume = presets[0].fVolume;
+ dev->eax.damping = presets[0].fDamping;
+ memcpy(&dev->eax.eax_props, &efx_presets[0], sizeof(dev->eax.eax_props));
+ dev->eax.eax_props.flDecayTime = presets[0].fDecayTime_sec;
+}
+
HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
ULONG cbPropData, ULONG *pcbReturned)
@@ -101,6 +117,70 @@ HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
*pcbReturned = 0;
+ if (IsEqualGUID(&DSPROPSETID_EAX_ReverbProperties, guidPropSet)) {
+ EAX_REVERBPROPERTIES *props;
+
+ if (!buf->device->eax.using_eax)
+ init_eax(buf->device);
+
+ switch (dwPropID) {
+ case DSPROPERTY_EAX_ALL:
+ if (cbPropData < sizeof(EAX_REVERBPROPERTIES))
+ return E_FAIL;
+
+ props = pPropData;
+
+ props->environment = buf->device->eax.environment;
+ props->fVolume = buf->device->eax.volume;
+ props->fDecayTime_sec = buf->device->eax.eax_props.flDecayTime;
+ props->fDamping = buf->device->eax.damping;
+
+ *pcbReturned = sizeof(EAX_REVERBPROPERTIES);
+ break;
+
+ case DSPROPERTY_EAX_ENVIRONMENT:
+ if (cbPropData < sizeof(unsigned long))
+ return E_FAIL;
+
+ *(unsigned long*)pPropData = buf->device->eax.environment;
+
+ *pcbReturned = sizeof(unsigned long);
+ break;
+
+ case DSPROPERTY_EAX_VOLUME:
+ if (cbPropData < sizeof(float))
+ return E_FAIL;
+
+ *(float*)pPropData = buf->device->eax.volume;
+
+ *pcbReturned = sizeof(float);
+ break;
+
+ case DSPROPERTY_EAX_DECAYTIME:
+ if (cbPropData < sizeof(float))
+ return E_FAIL;
+
+ *(float*)pPropData = buf->device->eax.eax_props.flDecayTime;
+
+ *pcbReturned = sizeof(float);
+ break;
+
+ case DSPROPERTY_EAX_DAMPING:
+ if (cbPropData < sizeof(float))
+ return E_FAIL;
+
+ *(float*)pPropData = buf->device->eax.damping;
+
+ *pcbReturned = sizeof(float);
+ break;
+
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
@@ -108,8 +188,95 @@ HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
ULONG cbPropData)
{
+ EAX_REVERBPROPERTIES *props;
+
TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",
buf, debugstr_guid(guidPropSet), dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData);
+ if (IsEqualGUID(&DSPROPSETID_EAX_ReverbProperties, guidPropSet)) {
+ if (!buf->device->eax.using_eax)
+ init_eax(buf->device);
+
+ switch (dwPropID) {
+ case DSPROPERTY_EAX_ALL:
+ if (cbPropData != sizeof(EAX_REVERBPROPERTIES))
+ return E_FAIL;
+
+ props = pPropData;
+
+ TRACE("setting environment = %lu, fVolume = %f, fDecayTime_sec = %f, fDamping = %f\n",
+ props->environment, props->fVolume, props->fDecayTime_sec,
+ props->fDamping);
+
+ buf->device->eax.environment = props->environment;
+
+ if (buf->device->eax.environment < EAX_ENVIRONMENT_COUNT)
+ memcpy(&buf->device->eax.eax_props, &efx_presets[buf->device->eax.environment], sizeof(buf->device->eax.eax_props));
+
+ buf->device->eax.volume = props->fVolume;
+ buf->device->eax.eax_props.flDecayTime = props->fDecayTime_sec;
+ buf->device->eax.damping = props->fDamping;
+
+ ReverbDeviceUpdate(buf->device);
+ break;
+
+ case DSPROPERTY_EAX_ENVIRONMENT:
+ if (cbPropData != sizeof(unsigned long))
+ return E_FAIL;
+
+ TRACE("setting environment to %lu\n", *(unsigned long*)pPropData);
+
+ buf->device->eax.environment = *(unsigned long*)pPropData;
+
+ if (buf->device->eax.environment < EAX_ENVIRONMENT_COUNT) {
+ memcpy(&buf->device->eax.eax_props, &efx_presets[buf->device->eax.environment], sizeof(buf->device->eax.eax_props));
+ buf->device->eax.volume = presets[buf->device->eax.environment].fVolume;
+ buf->device->eax.eax_props.flDecayTime = presets[buf->device->eax.environment].fDecayTime_sec;
+ buf->device->eax.damping = presets[buf->device->eax.environment].fDamping;
+ }
+
+ ReverbDeviceUpdate(buf->device);
+ break;
+
+ case DSPROPERTY_EAX_VOLUME:
+ if (cbPropData != sizeof(float))
+ return E_FAIL;
+
+ TRACE("setting volume to %f\n", *(float*)pPropData);
+
+ buf->device->eax.volume = *(float*)pPropData;
+
+ ReverbDeviceUpdate(buf->device);
+ break;
+
+ case DSPROPERTY_EAX_DECAYTIME:
+ if (cbPropData != sizeof(float))
+ return E_FAIL;
+
+ TRACE("setting decay time to %f\n", *(float*)pPropData);
+
+ buf->device->eax.eax_props.flDecayTime = *(float*)pPropData;
+
+ ReverbDeviceUpdate(buf->device);
+ break;
+
+ case DSPROPERTY_EAX_DAMPING:
+ if (cbPropData != sizeof(float))
+ return E_FAIL;
+
+ TRACE("setting damping to %f\n", *(float*)pPropData);
+
+ buf->device->eax.damping = *(float*)pPropData;
+
+ ReverbDeviceUpdate(buf->device);
+ break;
+
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
+ }
+
return E_PROP_ID_UNSUPPORTED;
}
--
2.3.3

View File

@ -0,0 +1,138 @@
From 43637cb46c48e84e7f1b127ba4427900c76f2470 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:48:19 +0000
Subject: dsound: Support getting and setting EAX buffer properties.
---
dlls/dsound/buffer.c | 2 ++
dlls/dsound/dsound_eax.h | 4 +++
dlls/dsound/dsound_private.h | 2 ++
dlls/dsound/eax.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 72 insertions(+)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 0596ce3..1c318f5 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1092,6 +1092,8 @@ HRESULT IDirectSoundBufferImpl_Create(
/* calculate fragment size and write lead */
DSOUND_RecalcFormat(dsb);
+ dsb->eax.reverb_mix = EAX_REVERBMIX_USEDISTANCE;
+
if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
dsb->ds3db_ds3db.vPosition.x = 0.0;
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index c90d82d..2ee83b9 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -119,6 +119,10 @@ typedef struct {
EFXEAXREVERBPROPERTIES eax_props;
} eax_info;
+typedef struct {
+ float reverb_mix;
+} eax_buffer_info;
+
#ifdef __cplusplus
}
#endif
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index c16f770..c732b52 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -176,6 +176,8 @@ struct IDirectSoundBufferImpl
int num_filters;
DSFilter* filters;
+ eax_buffer_info eax;
+
struct list entry;
};
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index cdd03be..3931681 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -179,6 +179,38 @@ HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
}
return S_OK;
+ } else if (IsEqualGUID(&DSPROPSETID_EAXBUFFER_ReverbProperties, guidPropSet)) {
+ EAXBUFFER_REVERBPROPERTIES *props;
+
+ if (!buf->device->eax.using_eax)
+ init_eax(buf->device);
+
+ switch (dwPropID) {
+ case DSPROPERTY_EAXBUFFER_ALL:
+ if (cbPropData < sizeof(EAXBUFFER_REVERBPROPERTIES))
+ return E_FAIL;
+
+ props = pPropData;
+
+ props->fMix = buf->eax.reverb_mix;
+
+ *pcbReturned = sizeof(EAXBUFFER_REVERBPROPERTIES);
+ break;
+
+ case DSPROPERTY_EAXBUFFER_REVERBMIX:
+ if (cbPropData < sizeof(float))
+ return E_FAIL;
+
+ *(float*)pPropData = buf->eax.reverb_mix;
+
+ *pcbReturned = sizeof(float);
+ break;
+
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
}
return E_PROP_ID_UNSUPPORTED;
@@ -276,6 +308,38 @@ HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
}
return S_OK;
+ } else if (IsEqualGUID(&DSPROPSETID_EAXBUFFER_ReverbProperties, guidPropSet)) {
+ EAXBUFFER_REVERBPROPERTIES *props;
+
+ if (!buf->device->eax.using_eax)
+ init_eax(buf->device);
+
+ switch (dwPropID) {
+ case DSPROPERTY_EAXBUFFER_ALL:
+ if (cbPropData != sizeof(EAXBUFFER_REVERBPROPERTIES))
+ return E_FAIL;
+
+ props = pPropData;
+
+ TRACE("setting reverb mix to %f\n", props->fMix);
+
+ buf->eax.reverb_mix = props->fMix;
+ break;
+
+ case DSPROPERTY_EAXBUFFER_REVERBMIX:
+ if (cbPropData != sizeof(float))
+ return E_FAIL;
+
+ TRACE("setting reverb mix to %f\n", *(float*)pPropData);
+
+ buf->eax.reverb_mix = *(float*)pPropData;
+ break;
+
+ default:
+ return E_PROP_ID_UNSUPPORTED;
+ }
+
+ return S_OK;
}
return E_PROP_ID_UNSUPPORTED;
--
2.3.3

View File

@ -0,0 +1,102 @@
From 76cd66f5f32045665fe392401b63738a5a089072 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:58:37 +0000
Subject: dsound: Add EAX init and free stubs.
---
dlls/dsound/buffer.c | 5 +++++
dlls/dsound/dsound_private.h | 2 ++
dlls/dsound/eax.c | 28 +++++++++++++++++++++++++++-
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 1c318f5..c098043 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1130,6 +1130,9 @@ HRESULT IDirectSoundBufferImpl_Create(
HeapFree(GetProcessHeap(),0,dsb);
dsb = NULL;
}
+
+ if (dsb->device->eax.using_eax)
+ init_eax_buffer(dsb);
}
IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
@@ -1169,6 +1172,8 @@ void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
HeapFree(GetProcessHeap(), 0, This->filters);
}
+ free_eax_buffer(This);
+
HeapFree(GetProcessHeap(), 0, This);
TRACE("(%p) released\n", This);
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index c732b52..a918cd2 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -240,6 +240,8 @@ HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
ULONG dwPropID, void *pInstanceData, ULONG cbInstanceData, void *pPropData,
ULONG cbPropData) DECLSPEC_HIDDEN;
+void free_eax_buffer(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
+void init_eax_buffer(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
/* mixer.c */
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 3931681..c0afb0f 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,20 +92,46 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
-static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
+static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
/* stub */
+}
+
+static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
+{
+ int i;
+
+ for (i = 0; i < dev->nrofbuffers; i++) {
+ ReverbUpdate(dev->buffers[i]);
+ }
+
return TRUE;
}
+void init_eax_buffer(IDirectSoundBufferImpl *dsb)
+{
+ ReverbUpdate(dsb);
+}
+
static void init_eax(DirectSoundDevice *dev)
{
+ int i;
+
dev->eax.using_eax = TRUE;
dev->eax.environment = presets[0].environment;
dev->eax.volume = presets[0].fVolume;
dev->eax.damping = presets[0].fDamping;
memcpy(&dev->eax.eax_props, &efx_presets[0], sizeof(dev->eax.eax_props));
dev->eax.eax_props.flDecayTime = presets[0].fDecayTime_sec;
+
+ for (i = 0; i < dev->nrofbuffers; i++) {
+ init_eax_buffer(dev->buffers[i]);
+ }
+}
+
+void free_eax_buffer(IDirectSoundBufferImpl *dsb)
+{
+ /* stub */
}
HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
--
2.3.3

View File

@ -0,0 +1,65 @@
From 735da63bda0fed9b01779bd8922a4cc13b05d598 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:59:57 +0000
Subject: dsound: Feed data through EAX function.
---
dlls/dsound/dsound_private.h | 1 +
dlls/dsound/eax.c | 5 +++++
dlls/dsound/mixer.c | 5 ++++-
3 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index a918cd2..cc55d70 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -242,6 +242,7 @@ HRESULT WINAPI EAX_Set(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
ULONG cbPropData) DECLSPEC_HIDDEN;
void free_eax_buffer(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
void init_eax_buffer(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
+void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count) DECLSPEC_HIDDEN;
/* mixer.c */
void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index c0afb0f..4368594 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,6 +92,11 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count)
+{
+ /* stub */
+}
+
static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
/* stub */
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index ff92cc1..b159834 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -453,7 +453,7 @@ static void putieee32_dsp(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD ch
*/
static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames)
{
- BOOL using_filters = dsb->num_filters > 0;
+ BOOL using_filters = dsb->num_filters > 0 || dsb->device->eax.using_eax;
UINT istride, ostride, size_bytes;
DWORD channel, i;
bitsputfunc put;
@@ -500,6 +500,9 @@ static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames)
}
}
+ if (dsb->device->eax.using_eax)
+ process_eax_buffer(dsb, dsb->device->dsp_buffer, frames * dsb->mix_channels);
+
istride = ostride;
ostride = dsb->device->pwfx->nChannels * sizeof(float);
for (i = 0; i < frames; i++) {
--
2.3.3

View File

@ -0,0 +1,184 @@
From 213aef0ba57c925f48c36e6167584a4ee0b7587b Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 21:06:42 +0000
Subject: dsound: Allocate EAX delay lines.
---
dlls/dsound/dsound_eax.h | 16 ++++++++
dlls/dsound/eax.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 2ee83b9..132f060 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -85,6 +85,9 @@ typedef struct {
#define EAX_REVERBMIX_USEDISTANCE -1.0f
+#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
+#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
+
typedef struct {
float flDensity;
float flDiffusion;
@@ -111,6 +114,12 @@ typedef struct {
int iDecayHFLimit;
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
+typedef struct DelayLine
+{
+ unsigned int Mask;
+ float *Line;
+} DelayLine;
+
typedef struct {
BOOL using_eax;
unsigned long environment;
@@ -121,6 +130,13 @@ typedef struct {
typedef struct {
float reverb_mix;
+
+ float *SampleBuffer;
+ unsigned int TotalSamples;
+
+ DelayLine Delay;
+
+ unsigned int Offset;
} eax_buffer_info;
#ifdef __cplusplus
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 4368594..babc2a7 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,14 +92,99 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static unsigned int fastf2u(float f)
+{
+ return (unsigned int)f;
+}
+
void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count)
{
/* stub */
}
+static unsigned int NextPowerOf2(unsigned int value)
+{
+ if (value > 0)
+ {
+ value--;
+ value |= value>>1;
+ value |= value>>2;
+ value |= value>>4;
+ value |= value>>8;
+ value |= value>>16;
+ }
+ return value+1;
+}
+
+static unsigned int CalcLineLength(float length, unsigned int offset, unsigned int frequency, DelayLine *Delay)
+{
+ unsigned int samples;
+
+ /* All line lengths are powers of 2, calculated from their lengths, with
+ * an additional sample in case of rounding errors. */
+ samples = NextPowerOf2(fastf2u(length * frequency) + 1);
+ /* All lines share a single sample buffer. */
+ Delay->Mask = samples - 1;
+ Delay->Line = (float*)offset;
+ /* Return the sample count for accumulation. */
+ return samples;
+}
+
+static void RealizeLineOffset(float *sampleBuffer, DelayLine *Delay)
+{
+ Delay->Line = &sampleBuffer[(unsigned int)Delay->Line];
+}
+
+static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
+{
+ unsigned int totalSamples, index;
+ float length;
+ float *newBuffer = NULL;
+
+ /* All delay line lengths are calculated to accomodate the full range of
+ * lengths given their respective paramters. */
+ totalSamples = 0;
+
+ /* The initial delay is the sum of the reflections and late reverb
+ * delays. */
+ length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
+ AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
+ totalSamples += CalcLineLength(length, totalSamples, frequency,
+ &dsb->eax.Delay);
+
+ if (totalSamples != dsb->eax.TotalSamples)
+ {
+ TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
+
+ if (dsb->eax.SampleBuffer)
+ newBuffer = HeapReAlloc(GetProcessHeap(), 0, dsb->eax.SampleBuffer, sizeof(float) * totalSamples);
+ else
+ newBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(float) * totalSamples);
+
+ if (newBuffer == NULL)
+ return FALSE;
+ dsb->eax.SampleBuffer = newBuffer;
+ dsb->eax.TotalSamples = totalSamples;
+ }
+
+ /* Update all delays to reflect the new sample buffer. */
+ RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Delay);
+
+ /* Clear the sample buffer. */
+ for (index = 0; index < dsb->eax.TotalSamples; index++)
+ dsb->eax.SampleBuffer[index] = 0.0f;
+
+ return TRUE;
+}
+
static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
- /* stub */
+ /* avoid segfaults in mixing thread when we recalculate the line offsets */
+ EnterCriticalSection(&dsb->device->mixlock);
+
+ AllocLines(dsb->device->pwfx->nSamplesPerSec, dsb);
+
+ LeaveCriticalSection(&dsb->device->mixlock);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -115,6 +200,14 @@ static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
void init_eax_buffer(IDirectSoundBufferImpl *dsb)
{
+ dsb->eax.TotalSamples = 0;
+ dsb->eax.SampleBuffer = NULL;
+
+ dsb->eax.Delay.Mask = 0;
+ dsb->eax.Delay.Line = NULL;
+
+ dsb->eax.Offset = 0;
+
ReverbUpdate(dsb);
}
@@ -136,7 +229,8 @@ static void init_eax(DirectSoundDevice *dev)
void free_eax_buffer(IDirectSoundBufferImpl *dsb)
{
- /* stub */
+ if (dsb->eax.SampleBuffer)
+ HeapFree(GetProcessHeap(), 0, dsb->eax.SampleBuffer);
}
HRESULT WINAPI EAX_Get(IDirectSoundBufferImpl *buf, REFGUID guidPropSet,
--
2.3.3

View File

@ -0,0 +1,67 @@
From de72257b18ac1a07ed770f20bede6b42e5baa99b Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 15:38:15 +0000
Subject: dsound: Add EAX VerbPass stub.
---
dlls/dsound/eax.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index babc2a7..6ac4cdf 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,6 +92,14 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
+{
+ /* stub */
+
+ /* Step all delays forward one sample. */
+ dsb->eax.Offset++;
+}
+
static unsigned int fastf2u(float f)
{
return (unsigned int)f;
@@ -99,7 +107,34 @@ static unsigned int fastf2u(float f)
void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count)
{
- /* stub */
+ int i;
+ float* out;
+ float gain;
+
+ if (dsb->device->eax.volume == 0.0f)
+ return;
+
+ if (dsb->mix_channels > 1) {
+ WARN("EAX not yet supported for non-mono sources\n");
+ return;
+ }
+
+ out = HeapAlloc(GetProcessHeap(), 0, sizeof(float)*count*4);
+
+ for (i = 0; i < count; i++) {
+ VerbPass(dsb, buf[i], &out[i*4]);
+ }
+
+ if (dsb->eax.reverb_mix == EAX_REVERBMIX_USEDISTANCE)
+ gain = 1.0f; /* FIXME - should be calculated from distance */
+ else
+ gain = dsb->eax.reverb_mix;
+
+ for (i = 0; i < count; i++) {
+ buf[i] += gain * out[i*4];
+ }
+
+ HeapFree(GetProcessHeap(), 0, out);
}
static unsigned int NextPowerOf2(unsigned int value)
--
2.3.3

View File

@ -0,0 +1,126 @@
From 858f3b43a1197c3b9a8e6f2228995451776b29b4 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 17:57:38 +0000
Subject: dsound: Implement EAX lowpass filter.
---
dlls/dsound/dsound_eax.h | 7 +++++++
dlls/dsound/eax.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 132f060..82b1408 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -121,6 +121,11 @@ typedef struct DelayLine
} DelayLine;
typedef struct {
+ float coeff;
+ float history[2];
+} FILTER;
+
+typedef struct {
BOOL using_eax;
unsigned long environment;
float volume;
@@ -134,6 +139,8 @@ typedef struct {
float *SampleBuffer;
unsigned int TotalSamples;
+ FILTER LpFilter;
+
DelayLine Delay;
unsigned int Offset;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 6ac4cdf..bbb5dad 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,9 +92,24 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
+{
+ float *history = &iir->history[offset*2];
+ float a = iir->coeff;
+ float output = input;
+
+ output = output + (history[0]-output)*a;
+ history[0] = output;
+ output = output + (history[1]-output)*a;
+ history[1] = output;
+
+ return output;
+}
+
static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
{
- /* stub */
+ /* Low-pass filter the incoming sample. */
+ in = lpFilter2P(&dsb->eax.LpFilter, 0, in);
/* Step all delays forward one sample. */
dsb->eax.Offset++;
@@ -137,6 +152,27 @@ void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count)
HeapFree(GetProcessHeap(), 0, out);
}
+static float lpCoeffCalc(float g, float cw)
+{
+ float a = 0.0f;
+
+ if (g < 0.9999f) /* 1-epsilon */
+ {
+ /* Be careful with gains < 0.001, as that causes the coefficient head
+ * towards 1, which will flatten the signal */
+ if (g < 0.001f) g = 0.001f;
+ a = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
+ (1 - g);
+ }
+
+ return a;
+}
+
+static float CalcI3DL2HFreq(float hfRef, unsigned int frequency)
+{
+ return cosf(M_PI*2.0f * hfRef / frequency);
+}
+
static unsigned int NextPowerOf2(unsigned int value)
{
if (value > 0)
@@ -214,12 +250,18 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
+ float cw;
+
/* avoid segfaults in mixing thread when we recalculate the line offsets */
EnterCriticalSection(&dsb->device->mixlock);
AllocLines(dsb->device->pwfx->nSamplesPerSec, dsb);
LeaveCriticalSection(&dsb->device->mixlock);
+
+ cw = CalcI3DL2HFreq(dsb->device->eax.eax_props.flHFReference, dsb->device->pwfx->nSamplesPerSec);
+
+ dsb->eax.LpFilter.coeff = lpCoeffCalc(dsb->device->eax.eax_props.flGainHF, cw);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -238,6 +280,10 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.TotalSamples = 0;
dsb->eax.SampleBuffer = NULL;
+ dsb->eax.LpFilter.coeff = 0.0f;
+ dsb->eax.LpFilter.history[0] = 0.0f;
+ dsb->eax.LpFilter.history[1] = 0.0f;
+
dsb->eax.Delay.Mask = 0;
dsb->eax.Delay.Line = NULL;
--
2.3.3

View File

@ -0,0 +1,89 @@
From 687ccff7f8b336d29eb72b7975500de8cedbae93 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:00:10 +0000
Subject: dsound: Add delay line EAX functions.
---
dlls/dsound/dsound_eax.h | 1 +
dlls/dsound/eax.c | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 82b1408..bd002d7 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -142,6 +142,7 @@ typedef struct {
FILTER LpFilter;
DelayLine Delay;
+ unsigned int DelayTap[2];
unsigned int Offset;
} eax_buffer_info;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index bbb5dad..9569c33 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -106,11 +106,26 @@ static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
return output;
}
+static void DelayLineIn(DelayLine *Delay, unsigned int offset, float in)
+{
+ Delay->Line[offset&Delay->Mask] = in;
+}
+
+static float DelayLineOut(DelayLine *Delay, unsigned int offset)
+{
+ return Delay->Line[offset&Delay->Mask];
+}
+
static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
{
/* Low-pass filter the incoming sample. */
in = lpFilter2P(&dsb->eax.LpFilter, 0, in);
+ /* Feed the initial delay line. */
+ DelayLineIn(&dsb->eax.Delay, dsb->eax.Offset, in);
+
+ in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[0]);
+
/* Step all delays forward one sample. */
dsb->eax.Offset++;
}
@@ -152,6 +167,12 @@ void process_eax_buffer(IDirectSoundBufferImpl *dsb, float *buf, DWORD count)
HeapFree(GetProcessHeap(), 0, out);
}
+static void UpdateDelayLine(float earlyDelay, float lateDelay, unsigned int frequency, eax_buffer_info *State)
+{
+ State->DelayTap[0] = fastf2u(earlyDelay * frequency);
+ State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
+}
+
static float lpCoeffCalc(float g, float cw)
{
float a = 0.0f;
@@ -262,6 +283,10 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
cw = CalcI3DL2HFreq(dsb->device->eax.eax_props.flHFReference, dsb->device->pwfx->nSamplesPerSec);
dsb->eax.LpFilter.coeff = lpCoeffCalc(dsb->device->eax.eax_props.flGainHF, cw);
+
+ UpdateDelayLine(dsb->device->eax.eax_props.flReflectionsDelay,
+ dsb->device->eax.eax_props.flLateReverbDelay,
+ dsb->device->pwfx->nSamplesPerSec, &dsb->eax);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -286,6 +311,8 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.Delay.Mask = 0;
dsb->eax.Delay.Line = NULL;
+ dsb->eax.DelayTap[0] = 0;
+ dsb->eax.DelayTap[1] = 0;
dsb->eax.Offset = 0;
--
2.3.3

View File

@ -0,0 +1,227 @@
From bb7edc0e1283a60b1cfc121356d6a8702f96f689 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:09:34 +0000
Subject: dsound: Implement EAX early reflections.
---
dlls/dsound/dsound_eax.h | 7 +++
dlls/dsound/eax.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index bd002d7..184f7ce 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -144,6 +144,13 @@ typedef struct {
DelayLine Delay;
unsigned int DelayTap[2];
+ struct {
+ float Gain;
+ float Coeff[4];
+ DelayLine Delay[4];
+ unsigned int Offset[4];
+ } Early;
+
unsigned int Offset;
} eax_buffer_info;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 9569c33..964e5f8 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,6 +92,11 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static const float EARLY_LINE_LENGTH[4] =
+{
+ 0.0015f, 0.0045f, 0.0135f, 0.0405f
+};
+
static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
{
float *history = &iir->history[offset*2];
@@ -116,6 +121,62 @@ static float DelayLineOut(DelayLine *Delay, unsigned int offset)
return Delay->Line[offset&Delay->Mask];
}
+static float AttenuatedDelayLineOut(DelayLine *Delay, unsigned int offset, float coeff)
+{
+ return coeff * Delay->Line[offset&Delay->Mask];
+}
+
+static float EarlyDelayLineOut(IDirectSoundBufferImpl* dsb, unsigned int index)
+{
+ return AttenuatedDelayLineOut(&dsb->eax.Early.Delay[index],
+ dsb->eax.Offset - dsb->eax.Early.Offset[index],
+ dsb->eax.Early.Coeff[index]);
+}
+
+static void EarlyReflection(IDirectSoundBufferImpl* dsb, float in, float *out)
+{
+ float d[4], v, f[4];
+
+ /* Obtain the decayed results of each early delay line. */
+ d[0] = EarlyDelayLineOut(dsb, 0);
+ d[1] = EarlyDelayLineOut(dsb, 1);
+ d[2] = EarlyDelayLineOut(dsb, 2);
+ d[3] = EarlyDelayLineOut(dsb, 3);
+
+ /* The following uses a lossless scattering junction from waveguide
+ * theory. It actually amounts to a householder mixing matrix, which
+ * will produce a maximally diffuse response, and means this can probably
+ * be considered a simple feed-back delay network (FDN).
+ * N
+ * ---
+ * \
+ * v = 2/N / d_i
+ * ---
+ * i=1
+ */
+ v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
+ /* The junction is loaded with the input here. */
+ v += in;
+
+ /* Calculate the feed values for the delay lines. */
+ f[0] = v - d[0];
+ f[1] = v - d[1];
+ f[2] = v - d[2];
+ f[3] = v - d[3];
+
+ /* Re-feed the delay lines. */
+ DelayLineIn(&dsb->eax.Early.Delay[0], dsb->eax.Offset, f[0]);
+ DelayLineIn(&dsb->eax.Early.Delay[1], dsb->eax.Offset, f[1]);
+ DelayLineIn(&dsb->eax.Early.Delay[2], dsb->eax.Offset, f[2]);
+ DelayLineIn(&dsb->eax.Early.Delay[3], dsb->eax.Offset, f[3]);
+
+ /* Output the results of the junction for all four channels. */
+ out[0] = dsb->eax.Early.Gain * f[0];
+ out[1] = dsb->eax.Early.Gain * f[1];
+ out[2] = dsb->eax.Early.Gain * f[2];
+ out[3] = dsb->eax.Early.Gain * f[3];
+}
+
static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
{
/* Low-pass filter the incoming sample. */
@@ -124,7 +185,9 @@ static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
/* Feed the initial delay line. */
DelayLineIn(&dsb->eax.Delay, dsb->eax.Offset, in);
+ /* Calculate the early reflection from the first delay tap. */
in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[0]);
+ EarlyReflection(dsb, in, out);
/* Step all delays forward one sample. */
dsb->eax.Offset++;
@@ -173,6 +236,27 @@ static void UpdateDelayLine(float earlyDelay, float lateDelay, unsigned int freq
State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
}
+static float CalcDecayCoeff(float length, float decayTime)
+{
+ return powf(0.001f/*-60 dB*/, length/decayTime);
+}
+
+static void UpdateEarlyLines(float reverbGain, float earlyGain, float lateDelay, eax_buffer_info *State)
+{
+ unsigned int index;
+
+ /* Calculate the early reflections gain (from the master effect gain, and
+ * reflections gain parameters) with a constant attenuation of 0.5. */
+ State->Early.Gain = 0.5f * reverbGain * earlyGain;
+
+ /* Calculate the gain (coefficient) for each early delay line using the
+ * late delay time. This expands the early reflections to the start of
+ * the late reverb. */
+ for(index = 0; index < 4; index++)
+ State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index],
+ lateDelay);
+}
+
static float lpCoeffCalc(float g, float cw)
{
float a = 0.0f;
@@ -244,6 +328,11 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
totalSamples += CalcLineLength(length, totalSamples, frequency,
&dsb->eax.Delay);
+ /* The early reflection lines. */
+ for (index = 0; index < 4; index++)
+ totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
+ frequency, &dsb->eax.Early.Delay[index]);
+
if (totalSamples != dsb->eax.TotalSamples)
{
TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
@@ -261,6 +350,10 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
/* Update all delays to reflect the new sample buffer. */
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Delay);
+ for(index = 0; index < 4; index++)
+ {
+ RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Early.Delay[index]);
+ }
/* Clear the sample buffer. */
for (index = 0; index < dsb->eax.TotalSamples; index++)
@@ -271,6 +364,7 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
+ unsigned int index;
float cw;
/* avoid segfaults in mixing thread when we recalculate the line offsets */
@@ -280,6 +374,11 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
LeaveCriticalSection(&dsb->device->mixlock);
+ for(index = 0; index < 4; index++)
+ {
+ dsb->eax.Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] * dsb->device->pwfx->nSamplesPerSec);
+ }
+
cw = CalcI3DL2HFreq(dsb->device->eax.eax_props.flHFReference, dsb->device->pwfx->nSamplesPerSec);
dsb->eax.LpFilter.coeff = lpCoeffCalc(dsb->device->eax.eax_props.flGainHF, cw);
@@ -287,6 +386,10 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
UpdateDelayLine(dsb->device->eax.eax_props.flReflectionsDelay,
dsb->device->eax.eax_props.flLateReverbDelay,
dsb->device->pwfx->nSamplesPerSec, &dsb->eax);
+
+ UpdateEarlyLines(dsb->device->eax.eax_props.flGain,
+ dsb->device->eax.eax_props.flReflectionsGain,
+ dsb->device->eax.eax_props.flLateReverbDelay, &dsb->eax);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -302,6 +405,8 @@ static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
void init_eax_buffer(IDirectSoundBufferImpl *dsb)
{
+ unsigned int index;
+
dsb->eax.TotalSamples = 0;
dsb->eax.SampleBuffer = NULL;
@@ -314,6 +419,15 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.DelayTap[0] = 0;
dsb->eax.DelayTap[1] = 0;
+ dsb->eax.Early.Gain = 0.0f;
+ for(index = 0; index < 4; index++)
+ {
+ dsb->eax.Early.Coeff[index] = 0.0f;
+ dsb->eax.Early.Delay[index].Mask = 0;
+ dsb->eax.Early.Delay[index].Line = NULL;
+ dsb->eax.Early.Offset[index] = 0;
+ }
+
dsb->eax.Offset = 0;
ReverbUpdate(dsb);
--
2.3.3

View File

@ -0,0 +1,124 @@
From 51655ef153a69a2cd2e34e8791a4e3b9088962fe Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:19:17 +0000
Subject: dsound: Implement EAX decorrelator.
---
dlls/dsound/dsound_eax.h | 3 +++
dlls/dsound/eax.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 184f7ce..c33a2ff 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -151,6 +151,9 @@ typedef struct {
unsigned int Offset[4];
} Early;
+ DelayLine Decorrelator;
+ unsigned int DecoTap[3];
+
unsigned int Offset;
} eax_buffer_info;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 964e5f8..d40b7d6 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -92,11 +92,21 @@ static const EFXEAXREVERBPROPERTIES efx_presets[] = {
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } /* psychotic */
};
+static const float DECO_FRACTION = 0.15f;
+static const float DECO_MULTIPLIER = 2.0f;
+
static const float EARLY_LINE_LENGTH[4] =
{
0.0015f, 0.0045f, 0.0135f, 0.0405f
};
+static const float LATE_LINE_LENGTH[4] =
+{
+ 0.0211f, 0.0311f, 0.0461f, 0.0680f
+};
+
+static const float LATE_LINE_MULTIPLIER = 4.0f;
+
static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
{
float *history = &iir->history[offset*2];
@@ -273,6 +283,26 @@ static float lpCoeffCalc(float g, float cw)
return a;
}
+static void UpdateDecorrelator(float density, unsigned int frequency, eax_buffer_info *State)
+{
+ unsigned int index;
+ float length;
+
+ /* The late reverb inputs are decorrelated to smooth the reverb tail and
+ * reduce harsh echos. The first tap occurs immediately, while the
+ * remaining taps are delayed by multiples of a fraction of the smallest
+ * cyclical delay time.
+ *
+ * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
+ */
+ for (index = 0; index < 3; index++)
+ {
+ length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (float)index)) *
+ LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
+ State->DecoTap[index] = fastf2u(length * frequency);
+ }
+}
+
static float CalcI3DL2HFreq(float hfRef, unsigned int frequency)
{
return cosf(M_PI*2.0f * hfRef / frequency);
@@ -333,6 +363,13 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
frequency, &dsb->eax.Early.Delay[index]);
+ /* The decorrelator line is calculated from the lowest reverb density (a
+ * parameter value of 1). */
+ length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) *
+ LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER);
+ totalSamples += CalcLineLength(length, totalSamples, frequency,
+ &dsb->eax.Decorrelator);
+
if (totalSamples != dsb->eax.TotalSamples)
{
TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
@@ -350,6 +387,7 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
/* Update all delays to reflect the new sample buffer. */
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Delay);
+ RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Decorrelator);
for(index = 0; index < 4; index++)
{
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Early.Delay[index]);
@@ -390,6 +428,8 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
UpdateEarlyLines(dsb->device->eax.eax_props.flGain,
dsb->device->eax.eax_props.flReflectionsGain,
dsb->device->eax.eax_props.flLateReverbDelay, &dsb->eax);
+
+ UpdateDecorrelator(dsb->device->eax.eax_props.flDensity, dsb->device->pwfx->nSamplesPerSec, &dsb->eax);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -428,6 +468,12 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.Early.Offset[index] = 0;
}
+ dsb->eax.Decorrelator.Mask = 0;
+ dsb->eax.Decorrelator.Line = NULL;
+ dsb->eax.DecoTap[0] = 0;
+ dsb->eax.DecoTap[1] = 0;
+ dsb->eax.DecoTap[2] = 0;
+
dsb->eax.Offset = 0;
ReverbUpdate(dsb);
--
2.3.3

View File

@ -0,0 +1,372 @@
From 03930e42e47619af1b84a11aa21b937404e290fc Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:21:02 +0000
Subject: dsound: Implement EAX late reverb.
---
dlls/dsound/dsound_eax.h | 13 +++
dlls/dsound/eax.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 268 insertions(+), 1 deletion(-)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index c33a2ff..fac4d9b 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -154,6 +154,19 @@ typedef struct {
DelayLine Decorrelator;
unsigned int DecoTap[3];
+ struct {
+ float Gain;
+ float DensityGain;
+ float MixCoeff;
+
+ float Coeff[4];
+ DelayLine Delay[4];
+ unsigned int Offset[4];
+
+ float LpCoeff[4];
+ float LpSample[4];
+ } Late;
+
unsigned int Offset;
} eax_buffer_info;
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index d40b7d6..c9a5eb6 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -107,6 +107,8 @@ static const float LATE_LINE_LENGTH[4] =
static const float LATE_LINE_MULTIPLIER = 4.0f;
+#define SPEEDOFSOUNDMETRESPERSEC 343.3f
+
static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
{
float *history = &iir->history[offset*2];
@@ -121,6 +123,11 @@ static float lpFilter2P(FILTER *iir, unsigned int offset, float input)
return output;
}
+static float lerp(float val1, float val2, float mu)
+{
+ return val1 + (val2-val1)*mu;
+}
+
static void DelayLineIn(DelayLine *Delay, unsigned int offset, float in)
{
Delay->Line[offset&Delay->Mask] = in;
@@ -187,8 +194,85 @@ static void EarlyReflection(IDirectSoundBufferImpl* dsb, float in, float *out)
out[3] = dsb->eax.Early.Gain * f[3];
}
+static float LateDelayLineOut(IDirectSoundBufferImpl* dsb, unsigned int index)
+{
+ return AttenuatedDelayLineOut(&dsb->eax.Late.Delay[index],
+ dsb->eax.Offset - dsb->eax.Late.Offset[index],
+ dsb->eax.Late.Coeff[index]);
+}
+
+static float LateLowPassInOut(IDirectSoundBufferImpl* dsb, unsigned int index, float in)
+{
+ in = lerp(in, dsb->eax.Late.LpSample[index], dsb->eax.Late.LpCoeff[index]);
+ dsb->eax.Late.LpSample[index] = in;
+ return in;
+}
+
+static void LateReverb(IDirectSoundBufferImpl* dsb, const float *in, float *out)
+{
+ float d[4], f[4];
+
+ /* Obtain the decayed results of the cyclical delay lines, and add the
+ * corresponding input channels. Then pass the results through the
+ * low-pass filters. */
+
+ /* This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
+ * to 0. */
+ d[0] = LateLowPassInOut(dsb, 2, in[2] + LateDelayLineOut(dsb, 2));
+ d[1] = LateLowPassInOut(dsb, 0, in[0] + LateDelayLineOut(dsb, 0));
+ d[2] = LateLowPassInOut(dsb, 3, in[3] + LateDelayLineOut(dsb, 3));
+ d[3] = LateLowPassInOut(dsb, 1, in[1] + LateDelayLineOut(dsb, 1));
+
+ /* Late reverb is done with a modified feed-back delay network (FDN)
+ * topology. Four input lines are each fed through their own all-pass
+ * filter and then into the mixing matrix. The four outputs of the
+ * mixing matrix are then cycled back to the inputs. Each output feeds
+ * a different input to form a circlular feed cycle.
+ *
+ * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
+ * using a single unitary rotational parameter:
+ *
+ * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2
+ * [ -a, d, c, -b ]
+ * [ -b, -c, d, a ]
+ * [ -c, b, -a, d ]
+ *
+ * The rotation is constructed from the effect's diffusion parameter,
+ * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
+ * with differing signs, and d is the coefficient x. The matrix is thus:
+ *
+ * [ x, y, -y, y ] n = sqrt(matrix_order - 1)
+ * [ -y, x, y, y ] t = diffusion_parameter * atan(n)
+ * [ y, -y, x, y ] x = cos(t)
+ * [ -y, -y, -y, x ] y = sin(t) / n
+ *
+ * To reduce the number of multiplies, the x coefficient is applied with
+ * the cyclical delay line coefficients. Thus only the y coefficient is
+ * applied when mixing, and is modified to be: y / x.
+ */
+ f[0] = d[0] + (dsb->eax.Late.MixCoeff * ( d[1] + -d[2] + d[3]));
+ f[1] = d[1] + (dsb->eax.Late.MixCoeff * (-d[0] + d[2] + d[3]));
+ f[2] = d[2] + (dsb->eax.Late.MixCoeff * ( d[0] + -d[1] + d[3]));
+ f[3] = d[3] + (dsb->eax.Late.MixCoeff * (-d[0] + -d[1] + -d[2] ));
+
+ /* Output the results of the matrix for all four channels, attenuated by
+ * the late reverb gain (which is attenuated by the 'x' mix coefficient). */
+ out[0] = dsb->eax.Late.Gain * f[0];
+ out[1] = dsb->eax.Late.Gain * f[1];
+ out[2] = dsb->eax.Late.Gain * f[2];
+ out[3] = dsb->eax.Late.Gain * f[3];
+
+ /* Re-feed the cyclical delay lines. */
+ DelayLineIn(&dsb->eax.Late.Delay[0], dsb->eax.Offset, f[0]);
+ DelayLineIn(&dsb->eax.Late.Delay[1], dsb->eax.Offset, f[1]);
+ DelayLineIn(&dsb->eax.Late.Delay[2], dsb->eax.Offset, f[2]);
+ DelayLineIn(&dsb->eax.Late.Delay[3], dsb->eax.Offset, f[3]);
+}
+
static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
{
+ float feed, late[4], taps[4];
+
/* Low-pass filter the incoming sample. */
in = lpFilter2P(&dsb->eax.LpFilter, 0, in);
@@ -199,6 +283,25 @@ static void VerbPass(IDirectSoundBufferImpl* dsb, float in, float* out)
in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[0]);
EarlyReflection(dsb, in, out);
+ /* Feed the decorrelator from the energy-attenuated output of the second
+ * delay tap. */
+ in = DelayLineOut(&dsb->eax.Delay, dsb->eax.Offset - dsb->eax.DelayTap[1]);
+ feed = in * dsb->eax.Late.DensityGain;
+ DelayLineIn(&dsb->eax.Decorrelator, dsb->eax.Offset, feed);
+
+ /* Calculate the late reverb from the decorrelator taps. */
+ taps[0] = feed;
+ taps[1] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[0]);
+ taps[2] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[1]);
+ taps[3] = DelayLineOut(&dsb->eax.Decorrelator, dsb->eax.Offset - dsb->eax.DecoTap[2]);
+ LateReverb(dsb, taps, late);
+
+ /* Mix early reflections and late reverb. */
+ out[0] += late[0];
+ out[1] += late[1];
+ out[2] += late[2];
+ out[3] += late[3];
+
/* Step all delays forward one sample. */
dsb->eax.Offset++;
}
@@ -308,6 +411,95 @@ static float CalcI3DL2HFreq(float hfRef, unsigned int frequency)
return cosf(M_PI*2.0f * hfRef / frequency);
}
+static float CalcDensityGain(float a)
+{
+ return sqrtf(1.0f - (a * a));
+}
+
+static float CalcDampingCoeff(float hfRatio, float length, float decayTime, float decayCoeff, float cw)
+{
+ float coeff, g;
+
+ coeff = 0.0f;
+ if (hfRatio < 1.0f)
+ {
+ /* Calculate the low-pass coefficient by dividing the HF decay
+ * coefficient by the full decay coefficient. */
+ g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
+
+ /* Damping is done with a 1-pole filter, so g needs to be squared. */
+ g *= g;
+ coeff = lpCoeffCalc(g, cw);
+
+ /* Very low decay times will produce minimal output, so apply an
+ * upper bound to the coefficient. */
+ if (coeff > 0.98f) coeff = 0.98f;
+ }
+ return coeff;
+}
+
+static void UpdateLateLines(float reverbGain, float lateGain, float xMix, float density, float decayTime,
+ float diffusion, float hfRatio, float cw, unsigned int frequency, eax_buffer_info *State)
+{
+ float length;
+ unsigned int index;
+
+ /* Calculate the late reverb gain (from the master effect gain, and late
+ * reverb gain parameters). Since the output is tapped prior to the
+ * application of the next delay line coefficients, this gain needs to be
+ * attenuated by the 'x' mixing matrix coefficient as well.
+ */
+ State->Late.Gain = reverbGain * lateGain * xMix;
+
+ /* To compensate for changes in modal density and decay time of the late
+ * reverb signal, the input is attenuated based on the maximal energy of
+ * the outgoing signal. This approximation is used to keep the apparent
+ * energy of the signal equal for all ranges of density and decay time.
+ *
+ * The average length of the cyclcical delay lines is used to calculate
+ * the attenuation coefficient.
+ */
+ length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
+ LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f;
+ length *= 1.0f + (density * LATE_LINE_MULTIPLIER);
+ State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
+ decayTime));
+
+ for(index = 0; index < 4; index++)
+ {
+ /* Calculate the length (in seconds) of each cyclical delay line. */
+ length = LATE_LINE_LENGTH[index] * (1.0f + (density * LATE_LINE_MULTIPLIER));
+
+ /* Calculate the delay offset for each cyclical delay line. */
+ State->Late.Offset[index] = fastf2u(length * frequency);
+
+ /* Calculate the gain (coefficient) for each cyclical line. */
+ State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
+
+ /* Calculate the damping coefficient for each low-pass filter. */
+ State->Late.LpCoeff[index] = CalcDampingCoeff(hfRatio, length, decayTime,
+ State->Late.Coeff[index], cw);
+
+ /* Attenuate the cyclical line coefficients by the mixing coefficient
+ * (x). */
+ State->Late.Coeff[index] *= xMix;
+ }
+}
+
+static void CalcMatrixCoeffs(float diffusion, float *x, float *y)
+{
+ float n, t;
+
+ /* The matrix is of order 4, so n is sqrt (4 - 1). */
+ n = sqrtf(3.0f);
+ t = diffusion * atanf(n);
+
+ /* Calculate the first mixing matrix coefficient. */
+ *x = cosf(t);
+ /* Calculate the second mixing matrix coefficient. */
+ *y = sinf(t) / n;
+}
+
static unsigned int NextPowerOf2(unsigned int value)
{
if (value > 0)
@@ -370,6 +562,14 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
totalSamples += CalcLineLength(length, totalSamples, frequency,
&dsb->eax.Decorrelator);
+ /* The late delay lines are calculated from the lowest reverb density. */
+ for (index = 0; index < 4; index++)
+ {
+ length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
+ totalSamples += CalcLineLength(length, totalSamples, frequency,
+ &dsb->eax.Late.Delay[index]);
+ }
+
if (totalSamples != dsb->eax.TotalSamples)
{
TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
@@ -391,6 +591,7 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
for(index = 0; index < 4; index++)
{
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Early.Delay[index]);
+ RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Late.Delay[index]);
}
/* Clear the sample buffer. */
@@ -400,10 +601,35 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
return TRUE;
}
+static inline float CalcDecayLength(float coeff, float decayTime)
+{
+ return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
+}
+
+static float CalcLimitedHfRatio(float hfRatio, float airAbsorptionGainHF, float decayTime)
+{
+ float limitRatio;
+
+ /* Find the attenuation due to air absorption in dB (converting delay
+ * time to meters using the speed of sound). Then reversing the decay
+ * equation, solve for HF ratio. The delay length is cancelled out of
+ * the equation, so it can be calculated once for all lines.
+ */
+ limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
+ SPEEDOFSOUNDMETRESPERSEC);
+ /* Using the limit calculated above, apply the upper bound to the HF
+ * ratio. Also need to limit the result to a minimum of 0.1, just like the
+ * HF ratio parameter. */
+ if (limitRatio < 0.1f) limitRatio = 0.1f;
+ else if (limitRatio > hfRatio) limitRatio = hfRatio;
+
+ return limitRatio;
+}
+
static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
{
unsigned int index;
- float cw;
+ float cw, hfRatio, x, y;
/* avoid segfaults in mixing thread when we recalculate the line offsets */
EnterCriticalSection(&dsb->device->mixlock);
@@ -430,6 +656,20 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
dsb->device->eax.eax_props.flLateReverbDelay, &dsb->eax);
UpdateDecorrelator(dsb->device->eax.eax_props.flDensity, dsb->device->pwfx->nSamplesPerSec, &dsb->eax);
+
+ CalcMatrixCoeffs(dsb->device->eax.eax_props.flDiffusion, &x, &y);
+ dsb->eax.Late.MixCoeff = y / x;
+
+ hfRatio = dsb->device->eax.eax_props.flDecayHFRatio;
+
+ if (dsb->device->eax.eax_props.iDecayHFLimit && dsb->device->eax.eax_props.flAirAbsorptionGainHF < 1.0f) {
+ hfRatio = CalcLimitedHfRatio(hfRatio, dsb->device->eax.eax_props.flAirAbsorptionGainHF,
+ dsb->device->eax.eax_props.flDecayTime);
+ }
+
+ UpdateLateLines(dsb->device->eax.eax_props.flGain, dsb->device->eax.eax_props.flLateReverbGain,
+ x, dsb->device->eax.eax_props.flDensity, dsb->device->eax.eax_props.flDecayTime,
+ dsb->device->eax.eax_props.flDiffusion, hfRatio, cw, dsb->device->pwfx->nSamplesPerSec, &dsb->eax);
}
static BOOL ReverbDeviceUpdate(DirectSoundDevice *dev)
@@ -474,6 +714,20 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.DecoTap[1] = 0;
dsb->eax.DecoTap[2] = 0;
+ dsb->eax.Late.Gain = 0.0f;
+ dsb->eax.Late.DensityGain = 0.0f;
+ dsb->eax.Late.MixCoeff = 0.0f;
+ for(index = 0; index < 4; index++)
+ {
+ dsb->eax.Late.Coeff[index] = 0.0f;
+ dsb->eax.Late.Delay[index].Mask = 0;
+ dsb->eax.Late.Delay[index].Line = NULL;
+ dsb->eax.Late.Offset[index] = 0;
+
+ dsb->eax.Late.LpCoeff[index] = 0.0f;
+ dsb->eax.Late.LpSample[index] = 0.0f;
+ }
+
dsb->eax.Offset = 0;
ReverbUpdate(dsb);
--
2.3.3

View File

@ -0,0 +1,151 @@
From 510838b8d83a085bda82ac87c0f22ee856eb0f67 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:21:18 +0000
Subject: dsound: Implement EAX late all-pass filter.
---
dlls/dsound/dsound_eax.h | 5 +++++
dlls/dsound/eax.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index fac4d9b..a650108 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -157,8 +157,13 @@ typedef struct {
struct {
float Gain;
float DensityGain;
+ float ApFeedCoeff;
float MixCoeff;
+ float ApCoeff[4];
+ DelayLine ApDelay[4];
+ unsigned int ApOffset[4];
+
float Coeff[4];
DelayLine Delay[4];
unsigned int Offset[4];
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index c9a5eb6..a05b00e 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -100,6 +100,11 @@ static const float EARLY_LINE_LENGTH[4] =
0.0015f, 0.0045f, 0.0135f, 0.0405f
};
+static const float ALLPASS_LINE_LENGTH[4] =
+{
+ 0.0151f, 0.0167f, 0.0183f, 0.0200f,
+};
+
static const float LATE_LINE_LENGTH[4] =
{
0.0211f, 0.0311f, 0.0461f, 0.0680f
@@ -194,6 +199,28 @@ static void EarlyReflection(IDirectSoundBufferImpl* dsb, float in, float *out)
out[3] = dsb->eax.Early.Gain * f[3];
}
+static float AllpassInOut(DelayLine *Delay, unsigned int outOffset, unsigned int inOffset, float in, float feedCoeff, float coeff)
+{
+ float out, feed;
+
+ out = DelayLineOut(Delay, outOffset);
+ feed = feedCoeff * in;
+ DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
+
+ /* The time-based attenuation is only applied to the delay output to
+ * keep it from affecting the feed-back path (which is already controlled
+ * by the all-pass feed coefficient). */
+ return (coeff * out) - feed;
+}
+
+static float LateAllPassInOut(IDirectSoundBufferImpl* dsb, unsigned int index, float in)
+{
+ return AllpassInOut(&dsb->eax.Late.ApDelay[index],
+ dsb->eax.Offset - dsb->eax.Late.ApOffset[index],
+ dsb->eax.Offset, in, dsb->eax.Late.ApFeedCoeff,
+ dsb->eax.Late.ApCoeff[index]);
+}
+
static float LateDelayLineOut(IDirectSoundBufferImpl* dsb, unsigned int index)
{
return AttenuatedDelayLineOut(&dsb->eax.Late.Delay[index],
@@ -223,6 +250,14 @@ static void LateReverb(IDirectSoundBufferImpl* dsb, const float *in, float *out)
d[2] = LateLowPassInOut(dsb, 3, in[3] + LateDelayLineOut(dsb, 3));
d[3] = LateLowPassInOut(dsb, 1, in[1] + LateDelayLineOut(dsb, 1));
+ /* To help increase diffusion, run each line through an all-pass filter.
+ * When there is no diffusion, the shortest all-pass filter will feed the
+ * shortest delay line. */
+ d[0] = LateAllPassInOut(dsb, 0, d[0]);
+ d[1] = LateAllPassInOut(dsb, 1, d[1]);
+ d[2] = LateAllPassInOut(dsb, 2, d[2]);
+ d[3] = LateAllPassInOut(dsb, 3, d[3]);
+
/* Late reverb is done with a modified feed-back delay network (FDN)
* topology. Four input lines are each fed through their own all-pass
* filter and then into the mixing matrix. The four outputs of the
@@ -465,8 +500,15 @@ static void UpdateLateLines(float reverbGain, float lateGain, float xMix, float
State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
decayTime));
+ /* Calculate the all-pass feed-back and feed-forward coefficient. */
+ State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
+
for(index = 0; index < 4; index++)
{
+ /* Calculate the gain (coefficient) for each all-pass line. */
+ State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
+ decayTime);
+
/* Calculate the length (in seconds) of each cyclical delay line. */
length = LATE_LINE_LENGTH[index] * (1.0f + (density * LATE_LINE_MULTIPLIER));
@@ -562,6 +604,11 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
totalSamples += CalcLineLength(length, totalSamples, frequency,
&dsb->eax.Decorrelator);
+ /* The late all-pass lines. */
+ for(index = 0;index < 4;index++)
+ totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples,
+ frequency, &dsb->eax.Late.ApDelay[index]);
+
/* The late delay lines are calculated from the lowest reverb density. */
for (index = 0; index < 4; index++)
{
@@ -591,6 +638,7 @@ static BOOL AllocLines(unsigned int frequency, IDirectSoundBufferImpl *dsb)
for(index = 0; index < 4; index++)
{
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Early.Delay[index]);
+ RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Late.ApDelay[index]);
RealizeLineOffset(dsb->eax.SampleBuffer, &dsb->eax.Late.Delay[index]);
}
@@ -641,6 +689,7 @@ static void ReverbUpdate(IDirectSoundBufferImpl *dsb)
for(index = 0; index < 4; index++)
{
dsb->eax.Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] * dsb->device->pwfx->nSamplesPerSec);
+ dsb->eax.Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] * dsb->device->pwfx->nSamplesPerSec);
}
cw = CalcI3DL2HFreq(dsb->device->eax.eax_props.flHFReference, dsb->device->pwfx->nSamplesPerSec);
@@ -716,9 +765,15 @@ void init_eax_buffer(IDirectSoundBufferImpl *dsb)
dsb->eax.Late.Gain = 0.0f;
dsb->eax.Late.DensityGain = 0.0f;
+ dsb->eax.Late.ApFeedCoeff = 0.0f;
dsb->eax.Late.MixCoeff = 0.0f;
for(index = 0; index < 4; index++)
{
+ dsb->eax.Late.ApCoeff[index] = 0.0f;
+ dsb->eax.Late.ApDelay[index].Mask = 0;
+ dsb->eax.Late.ApDelay[index].Line = NULL;
+ dsb->eax.Late.ApOffset[index] = 0;
+
dsb->eax.Late.Coeff[index] = 0.0f;
dsb->eax.Late.Delay[index].Mask = 0;
dsb->eax.Late.Delay[index].Line = NULL;
--
2.3.3

View File

@ -0,0 +1,2 @@
Fixes: Software support for Environmental Audio Extensions (EAX)
Depends: dsound-Fast_Mixer

View File

@ -94,6 +94,7 @@ patch_enable_all ()
enable_ddraw_Hotpatch="$1"
enable_ddraw_d3d_execute_buffer="$1"
enable_dinput_Events="$1"
enable_dsound_EAX="$1"
enable_dsound_Fast_Mixer="$1"
enable_dxgi_GetDesc="$1"
enable_dxva2_Video_Decoder="$1"
@ -340,6 +341,9 @@ patch_enable ()
dinput-Events)
enable_dinput_Events="$2"
;;
dsound-EAX)
enable_dsound_EAX="$2"
;;
dsound-Fast_Mixer)
enable_dsound_Fast_Mixer="$2"
;;
@ -1170,6 +1174,13 @@ if test "$enable_wined3d_CSMT_Helper" -eq 1; then
enable_wined3d_DXTn=1
fi
if test "$enable_dsound_EAX" -eq 1; then
if test "$enable_dsound_Fast_Mixer" -gt 1; then
abort "Patchset dsound-Fast_Mixer disabled, but dsound-EAX depends on that."
fi
enable_dsound_Fast_Mixer=1
fi
if test "$enable_d3dx9_36_AnimationController" -eq 1; then
if test "$enable_d3dx9_36_DXTn" -gt 1; then
abort "Patchset d3dx9_36-DXTn disabled, but d3dx9_36-AnimationController depends on that."
@ -1797,6 +1808,51 @@ if test "$enable_dsound_Fast_Mixer" -eq 1; then
) >> "$patchlist"
fi
# Patchset dsound-EAX
# |
# | Modified files:
# | * dlls/dsound/Makefile.in, dlls/dsound/buffer.c, dlls/dsound/dsound.c, dlls/dsound/dsound_eax.h,
# | dlls/dsound/dsound_private.h, dlls/dsound/eax.c, dlls/dsound/mixer.c
# |
if test "$enable_dsound_EAX" -eq 1; then
patch_apply dsound-EAX/0001-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch
patch_apply dsound-EAX/0002-dsound-Add-EAX-v1-constants-and-structs.patch
patch_apply dsound-EAX/0003-dsound-Report-that-we-support-EAX-v1.patch
patch_apply dsound-EAX/0004-dsound-Add-EAX-propset-stubs.patch
patch_apply dsound-EAX/0005-dsound-Add-EAX-presets.patch
patch_apply dsound-EAX/0006-dsound-Support-getting-and-setting-EAX-properties.patch
patch_apply dsound-EAX/0007-dsound-Support-getting-and-setting-EAX-buffer-proper.patch
patch_apply dsound-EAX/0008-dsound-Add-EAX-init-and-free-stubs.patch
patch_apply dsound-EAX/0009-dsound-Feed-data-through-EAX-function.patch
patch_apply dsound-EAX/0010-dsound-Allocate-EAX-delay-lines.patch
patch_apply dsound-EAX/0011-dsound-Add-EAX-VerbPass-stub.patch
patch_apply dsound-EAX/0012-dsound-Implement-EAX-lowpass-filter.patch
patch_apply dsound-EAX/0013-dsound-Add-delay-line-EAX-functions.patch
patch_apply dsound-EAX/0014-dsound-Implement-EAX-early-reflections.patch
patch_apply dsound-EAX/0015-dsound-Implement-EAX-decorrelator.patch
patch_apply dsound-EAX/0016-dsound-Implement-EAX-late-reverb.patch
patch_apply dsound-EAX/0017-dsound-Implement-EAX-late-all-pass-filter.patch
(
echo '+ { "Sebastian Lackner", "dsound: Apply filters before sound is multiplied to speakers.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add EAX v1 constants and structs.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Report that we support EAX.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add EAX propset stubs.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add EAX presets.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Support getting and setting EAX properties.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Support getting and setting EAX buffer properties.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add EAX init and free stubs.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Feed data through EAX function.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Allocate EAX delay lines.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add EAX VerbPass stub.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Implement EAX lowpass filter.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Add delay line EAX functions.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Implement EAX early reflections.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Implement EAX decorrelator.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Implement EAX late reverb.", 1 },';
echo '+ { "Mark Harmstone", "dsound: Implement EAX late all-pass filter.", 1 },';
) >> "$patchlist"
fi
# Patchset dxgi-GetDesc
# |
# | This patchset fixes the following Wine bugs:
@ -2486,6 +2542,20 @@ if test "$enable_kernel32_Console_Handles" -eq 1; then
) >> "$patchlist"
fi
# Patchset kernel32-SetFileInformationByHandle
# |
# | Modified files:
# | * dlls/kernel32/file.c, include/winbase.h
# |
if test "$enable_kernel32_SetFileInformationByHandle" -eq 1; then
patch_apply kernel32-SetFileInformationByHandle/0001-include-Declare-a-couple-more-file-information-class.patch
patch_apply kernel32-SetFileInformationByHandle/0002-kernel32-Implement-SetFileInformationByHandle.patch
(
echo '+ { "Michael Müller", "include: Declare a couple more file information class structures.", 1 },';
echo '+ { "Michael Müller", "kernel32: Implement SetFileInformationByHandle.", 1 },';
) >> "$patchlist"
fi
# Patchset ntdll-FileDispositionInformation
# |
# | This patchset fixes the following Wine bugs:
@ -2505,20 +2575,6 @@ if test "$enable_ntdll_FileDispositionInformation" -eq 1; then
) >> "$patchlist"
fi
# Patchset kernel32-SetFileInformationByHandle
# |
# | Modified files:
# | * dlls/kernel32/file.c, include/winbase.h
# |
if test "$enable_kernel32_SetFileInformationByHandle" -eq 1; then
patch_apply kernel32-SetFileInformationByHandle/0001-include-Declare-a-couple-more-file-information-class.patch
patch_apply kernel32-SetFileInformationByHandle/0002-kernel32-Implement-SetFileInformationByHandle.patch
(
echo '+ { "Michael Müller", "include: Declare a couple more file information class structures.", 1 },';
echo '+ { "Michael Müller", "kernel32: Implement SetFileInformationByHandle.", 1 },';
) >> "$patchlist"
fi
# Patchset kernel32-CopyFileEx
# |
# | This patchset fixes the following Wine bugs: