Added patch to implement EAX support in dsound.

This commit is contained in:
Mark Harmstone 2015-03-27 21:24:40 +00:00
parent f3032f5a57
commit cc21d373b5
18 changed files with 2926 additions and 0 deletions

View File

@ -0,0 +1,107 @@
From d417a8b92faa9cef33db57fc259186facce51c12 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:27:37 +0000
Subject: [PATCH 01/18] dsound: Add cp_fields_proc variable for buffers.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_private.h | 3 +++
dlls/dsound/mixer.c | 20 +++++++++++++++-----
2 files changed, 18 insertions(+), 5 deletions(-)
--------------2.0.5
Content-Type: text/x-patch; name="0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch"
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index 9c001ed..c10f1dc 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -126,6 +126,8 @@ HRESULT DirectSoundDevice_AddBuffer(
IDirectSoundBufferImpl * pDSB) DECLSPEC_HIDDEN;
void DirectSoundDevice_RemoveBuffer(DirectSoundDevice * device, IDirectSoundBufferImpl * pDSB) DECLSPEC_HIDDEN;
+typedef UINT (*CPFIELDSPROC)(IDirectSoundBufferImpl*, UINT, LONG64*);
+
/*****************************************************************************
* IDirectSoundBuffer implementation structure
*/
@@ -171,6 +173,7 @@ struct IDirectSoundBufferImpl
bitsputfunc put, put_aux;
int num_filters;
DSFilter* filters;
+ CPFIELDSPROC cp_fields_proc;
struct list entry;
};
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 85ab14a..ef8f053 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -43,6 +43,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
+static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
+static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
+
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
{
double temp;
@@ -87,6 +90,14 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan)
TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan);
}
+static void DSOUND_RefreshCPFieldsProc(IDirectSoundBufferImpl *dsb)
+{
+ if (dsb->freqAdjustNum == dsb->freqAdjustDen)
+ dsb->cp_fields_proc = cp_fields_noresample;
+ else
+ dsb->cp_fields_proc = cp_fields_resample;
+}
+
/**
* Recalculate the size for temporary buffer, and new writelead
* Should be called when one of the following things occur:
@@ -179,6 +190,8 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
FIXME("Conversion from %u to %u channels is not implemented, falling back to stereo\n", ichannels, ochannels);
dsb->mix_channels = 2;
}
+
+ DSOUND_RefreshCPFieldsProc(dsb);
}
/**
@@ -266,7 +279,7 @@ 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, UINT count, LONG64 *freqAccNum)
{
UINT istride = dsb->pwfx->nBlockAlign;
UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
@@ -348,10 +361,7 @@ static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNu
{
DWORD ipos, adv;
- if (dsb->freqAdjustNum == dsb->freqAdjustDen)
- adv = cp_fields_noresample(dsb, count); /* *freqAccNum is unmodified */
- else
- adv = cp_fields_resample(dsb, count, freqAccNum);
+ adv = dsb->cp_fields_proc(dsb, count, freqAccNum);
ipos = dsb->sec_mixpos + adv * dsb->pwfx->nBlockAlign;
if (ipos >= dsb->buflen) {
--------------2.0.5--

View File

@ -0,0 +1,270 @@
From bb619d6e5ee74714f2f524fb91dbe1da697dc977 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:39:43 +0000
Subject: [PATCH 02/18] dsound: Apply filters before sound is multiplied to
speakers.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/buffer.c | 3 +
dlls/dsound/dsound_private.h | 1 +
dlls/dsound/mixer.c | 151 ++++++++++++++++++++++++++++++++++++++-----
3 files changed, 138 insertions(+), 17 deletions(-)
--------------2.0.5
Content-Type: text/x-patch; name="0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch"
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 4e84d17..7df6348 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -739,6 +739,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, D
This->num_filters = 0;
}
+ DSOUND_RefreshCPFieldsProc(This);
return DS_OK;
}
@@ -824,6 +825,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, D
This->num_filters = dwEffectsCount;
}
+ DSOUND_RefreshCPFieldsProc(This);
+
return hr;
}
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index c10f1dc..5219dbb 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -236,6 +236,7 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) DECLSPEC_HIDDEN;
void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan) DECLSPEC_HIDDEN;
void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, float *overshot) DECLSPEC_HIDDEN;
+void DSOUND_RefreshCPFieldsProc(IDirectSoundBufferImpl *dsb) DECLSPEC_HIDDEN;
DWORD CALLBACK DSOUND_mixthread(void *ptr) DECLSPEC_HIDDEN;
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index ef8f053..7327b5f 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -44,7 +44,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(dsound);
static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
+static UINT cp_fields_noresample_dsp(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
+static UINT cp_fields_resample_dsp(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum);
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
{
@@ -90,12 +92,14 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan)
TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan);
}
-static void DSOUND_RefreshCPFieldsProc(IDirectSoundBufferImpl *dsb)
+void DSOUND_RefreshCPFieldsProc(IDirectSoundBufferImpl *dsb)
{
+ BOOL using_filters = dsb->num_filters > 0;
+
if (dsb->freqAdjustNum == dsb->freqAdjustDen)
- dsb->cp_fields_proc = cp_fields_noresample;
+ dsb->cp_fields_proc = using_filters ? cp_fields_noresample_dsp : cp_fields_noresample;
else
- dsb->cp_fields_proc = cp_fields_resample;
+ dsb->cp_fields_proc = using_filters ? cp_fields_resample_dsp : cp_fields_resample;
}
/**
@@ -279,6 +283,25 @@ static inline float get_current_sample(const IDirectSoundBufferImpl *dsb,
return dsb->get(dsb, mixpos % dsb->buflen, channel);
}
+static void apply_filters(IDirectSoundBufferImpl *dsb, float* buf, UINT count)
+{
+ int i;
+ HRESULT hr;
+
+ if (count > 0) {
+ for (i = 0; i < dsb->num_filters; i++) {
+ if (dsb->filters[i].inplace) {
+ hr = IMediaObjectInPlace_Process(dsb->filters[i].inplace, count * dsb->mix_channels * sizeof(float),
+ (BYTE*)buf, 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);
+ }
+ }
+}
+
static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
{
UINT istride = dsb->pwfx->nBlockAlign;
@@ -291,6 +314,33 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count, LONG64
return count;
}
+static UINT cp_fields_noresample_dsp(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
+{
+ UINT istride = dsb->pwfx->nBlockAlign;
+ UINT ostride = dsb->device->pwfx->nChannels * sizeof(float);
+ DWORD channel, i;
+ float* buf;
+
+ buf = HeapAlloc(GetProcessHeap(), 0, count * dsb->mix_channels * sizeof(float));
+ for (i = 0; i < count; i++) {
+ for (channel = 0; channel < dsb->mix_channels; channel++) {
+ buf[(i*dsb->mix_channels)+channel] = get_current_sample(dsb, dsb->sec_mixpos + i*istride, channel);
+ }
+ }
+
+ apply_filters(dsb, buf, count);
+
+ for (i = 0; i < count; i++) {
+ for (channel = 0; channel < dsb->mix_channels; channel++) {
+ dsb->put(dsb, i * ostride, channel, buf[(i*dsb->mix_channels)+channel]);
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, buf);
+
+ return count;
+}
+
static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
{
UINT i, channel;
@@ -357,6 +407,87 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *
return max_ipos;
}
+static UINT cp_fields_resample_dsp(IDirectSoundBufferImpl *dsb, 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;
+ UINT dsbfirstep = dsb->firstep;
+ UINT channels = dsb->mix_channels;
+ UINT max_ipos = (freqAcc_start + count * dsb->freqAdjustNum) / dsb->freqAdjustDen;
+
+ UINT fir_cachesize = (fir_len + dsbfirstep - 2) / dsbfirstep;
+ UINT required_input = max_ipos + fir_cachesize;
+
+ float* intermediate = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(float) * required_input * channels);
+
+ float* fir_copy = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(float) * fir_cachesize);
+
+ float* buf = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(float) * count * dsb->mix_channels);
+ float* buftmp = buf;
+
+ /* Important: this buffer MUST be non-interleaved
+ * if you want -msse3 to have any effect.
+ * This is good for CPU cache effects, too.
+ */
+ float* itmp = intermediate;
+ for (channel = 0; channel < channels; channel++)
+ for (i = 0; i < required_input; i++)
+ *(itmp++) = get_current_sample(dsb,
+ dsb->sec_mixpos + i * istride, channel);
+
+ for(i = 0; i < count; ++i) {
+ UINT int_fir_steps = (freqAcc_start + i * dsb->freqAdjustNum) * dsbfirstep / dsb->freqAdjustDen;
+ float total_fir_steps = (freqAcc_start + i * dsb->freqAdjustNum) * dsbfirstep / (float)dsb->freqAdjustDen;
+ UINT ipos = int_fir_steps / dsbfirstep;
+
+ UINT idx = (ipos + 1) * dsbfirstep - int_fir_steps - 1;
+ float rem = int_fir_steps + 1.0 - total_fir_steps;
+
+ int fir_used = 0;
+ while (idx < fir_len - 1) {
+ fir_copy[fir_used++] = fir[idx] * (1.0 - rem) + fir[idx + 1] * rem;
+ idx += dsb->firstep;
+ }
+
+ assert(fir_used <= fir_cachesize);
+ assert(ipos + fir_used <= required_input);
+
+ for (channel = 0; channel < dsb->mix_channels; channel++) {
+ int j;
+ float sum = 0.0;
+ float* cache = &intermediate[channel * required_input + ipos];
+ for (j = 0; j < fir_used; j++)
+ sum += fir_copy[j] * cache[j];
+ *(buftmp++) = sum * dsb->firgain;
+ }
+ }
+
+ apply_filters(dsb, buf, count);
+
+ buftmp = buf;
+ for(i = 0; i < count; ++i) {
+ for (channel = 0; channel < dsb->mix_channels; channel++) {
+ dsb->put(dsb, i * ostride, channel, *buftmp);
+ buftmp++;
+ }
+ }
+
+ *freqAccNum = freqAcc_end % dsb->freqAdjustDen;
+
+ HeapFree(GetProcessHeap(), 0, fir_copy);
+ HeapFree(GetProcessHeap(), 0, intermediate);
+ HeapFree(GetProcessHeap(), 0, buf);
+
+ return max_ipos;
+}
+
static void cp_fields(IDirectSoundBufferImpl *dsb, UINT count, LONG64 *freqAccNum)
{
DWORD ipos, adv;
@@ -407,8 +538,6 @@ 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;
- HRESULT hr;
- int i;
if (dsb->device->tmp_buffer_len < size_bytes || !dsb->device->tmp_buffer)
{
@@ -420,18 +549,6 @@ static void DSOUND_MixToTemporary(IDirectSoundBufferImpl *dsb, DWORD frames)
}
cp_fields(dsb, frames, &dsb->freqAccNum);
-
- 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);
-
- if (FAILED(hr))
- WARN("IMediaObjectInPlace_Process failed for filter %u\n", i);
- } else
- WARN("filter %u has no inplace object - unsupported\n", i);
- }
- }
}
static void DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT frames)
--------------2.0.5--

View File

@ -0,0 +1,135 @@
From a76952522ebce6b2c0e08cb98baa4cd6a261975a Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 15 Mar 2015 18:04:16 +0000
Subject: [PATCH 03/18] dsound: Add EAX v1 constants and structs.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
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
--------------2.0.5
Content-Type: text/x-patch; name="0003-dsound-Add-EAX-v1-constants-and-structs.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0003-dsound-Add-EAX-v1-constants-and-structs.patch"
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 5219dbb..b52cc31 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.0.5--

View File

@ -0,0 +1,49 @@
From 293bff08260858a815cf2acc863da482bc53522a Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 15 Mar 2015 18:04:38 +0000
Subject: [PATCH 04/18] dsound: Report that we support EAX v1.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/buffer.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0004-dsound-Report-that-we-support-EAX-v1.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0004-dsound-Report-that-we-support-EAX-v1.patch"
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 7df6348..a0db5db 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1322,6 +1322,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.0.5--

View File

@ -0,0 +1,145 @@
From 4b43643b83bfa1a69232bbc8489b116feb8c61bc Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 13:58:53 +0000
Subject: [PATCH 05/18] dsound: Add EAX propset stubs.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
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
--------------2.0.5
Content-Type: text/x-patch; name="0005-dsound-Add-EAX-propset-stubs.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0005-dsound-Add-EAX-propset-stubs.patch"
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 a0db5db..4ceb176 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1301,6 +1301,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;
}
@@ -1312,6 +1315,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 b52cc31..72ac025 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -231,6 +231,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.0.5--

View File

@ -0,0 +1,151 @@
From ac35ac1bf501d36b32ec3be2b2e73b4506932435 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 14:10:06 +0000
Subject: [PATCH 06/18] dsound: Add EAX presets.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 28 ++++++++++++++++++++++
dlls/dsound/eax.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 88 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0006-dsound-Add-EAX-presets.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0006-dsound-Add-EAX-presets.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 600029f..9c29385 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -16,6 +16,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 +84,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..525875c 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -16,6 +16,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 +33,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.0.5--

View File

@ -0,0 +1,254 @@
From 563415997a8a95b87c47ea8fe72e172aae5cd3d5 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 14:22:02 +0000
Subject: [PATCH 07/18] dsound: Support getting and setting EAX properties.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 8 +++
dlls/dsound/dsound_private.h | 2 +
dlls/dsound/eax.c | 167 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0007-dsound-Support-getting-and-setting-EAX-properties.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0007-dsound-Support-getting-and-setting-EAX-properties.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 9c29385..d9e88f4 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -110,6 +110,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 72ac025..d9be65b 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -98,6 +98,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 525875c..3b06495 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -91,6 +91,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)
@@ -100,6 +116,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;
}
@@ -107,8 +187,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.0.5--

View File

@ -0,0 +1,153 @@
From 3765b43e4c646b3cbbcfbec79a2e84791d88349e Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:48:19 +0000
Subject: [PATCH 08/18] dsound: Support getting and setting EAX buffer
properties.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
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(+)
--------------2.0.5
Content-Type: text/x-patch; name="0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch"
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 4ceb176..9ebf213 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1095,6 +1095,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 d9e88f4..56b4263 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -118,6 +118,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 d9be65b..0aef20f 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -178,6 +178,8 @@ struct IDirectSoundBufferImpl
DSFilter* filters;
CPFIELDSPROC cp_fields_proc;
+ eax_buffer_info eax;
+
struct list entry;
};
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index 3b06495..56a76f6 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -178,6 +178,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;
@@ -275,6 +307,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.0.5--

View File

@ -0,0 +1,133 @@
From 5b3eccbf7a66a21dbb38d4115f01389102775116 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:58:37 +0000
Subject: [PATCH 09/18] dsound: Add EAX init and free stubs.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/buffer.c | 6 ++++++
dlls/dsound/dsound_private.h | 2 ++
dlls/dsound/eax.c | 30 +++++++++++++++++++++++++++++-
dlls/dsound/mixer.c | 2 +-
4 files changed, 38 insertions(+), 2 deletions(-)
--------------2.0.5
Content-Type: text/x-patch; name="0009-dsound-Add-EAX-init-and-free-stubs.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0009-dsound-Add-EAX-init-and-free-stubs.patch"
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c
index 9ebf213..a62ca40 100644
--- a/dlls/dsound/buffer.c
+++ b/dlls/dsound/buffer.c
@@ -1133,6 +1133,10 @@ HRESULT IDirectSoundBufferImpl_Create(
HeapFree(GetProcessHeap(),0,dsb);
dsb = NULL;
}
+
+ if (dsb->device->eax.using_eax) {
+ init_eax_buffer(dsb);
+ }
}
IDirectSoundBuffer8_AddRef(&dsb->IDirectSoundBuffer8_iface);
@@ -1172,6 +1176,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 0aef20f..e041526 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -242,6 +242,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 56a76f6..f0c17ff 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -91,20 +91,48 @@ 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);
+
+ DSOUND_RefreshCPFieldsProc(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,
diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 7327b5f..da5a174 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -94,7 +94,7 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan)
void DSOUND_RefreshCPFieldsProc(IDirectSoundBufferImpl *dsb)
{
- BOOL using_filters = dsb->num_filters > 0;
+ BOOL using_filters = dsb->num_filters > 0 || dsb->device->eax.using_eax;
if (dsb->freqAdjustNum == dsb->freqAdjustDen)
dsb->cp_fields_proc = using_filters ? cp_fields_noresample_dsp : cp_fields_noresample;
--------------2.0.5--

View File

@ -0,0 +1,70 @@
From 94026d1694362d5f94f74e8f0c362a1c1efe4bec Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 20:59:57 +0000
Subject: [PATCH 10/18] dsound: Feed data through EAX function.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_private.h | 1 +
dlls/dsound/eax.c | 5 +++++
dlls/dsound/mixer.c | 3 +++
3 files changed, 9 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0010-dsound-Feed-data-through-EAX-function.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0010-dsound-Feed-data-through-EAX-function.patch"
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
index e041526..aabb36f 100644
--- a/dlls/dsound/dsound_private.h
+++ b/dlls/dsound/dsound_private.h
@@ -244,6 +244,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 f0c17ff..df05f8e 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -91,6 +91,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 da5a174..a737707 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -299,6 +299,9 @@ static void apply_filters(IDirectSoundBufferImpl *dsb, float* buf, UINT count)
} else
WARN("filter %u has no inplace object - unsupported\n", i);
}
+
+ if (dsb->device->eax.using_eax)
+ process_eax_buffer(dsb, buf, count);
}
}
--------------2.0.5--

View File

@ -0,0 +1,205 @@
From b8a5fe26a390ced4438df0e50b7c93fd4150ed06 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Fri, 27 Mar 2015 21:06:42 +0000
Subject: [PATCH 11/18] dsound: Allocate EAX delay lines.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 16 ++++++++
dlls/dsound/eax.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 113 insertions(+), 2 deletions(-)
--------------2.0.5
Content-Type: text/x-patch; name="0011-dsound-Allocate-EAX-delay-lines.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0011-dsound-Allocate-EAX-delay-lines.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 56b4263..7565233 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -84,6 +84,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;
@@ -110,6 +113,12 @@ typedef struct {
int iDecayHFLimit;
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
+typedef struct DelayLine
+{
+ unsigned int Mask;
+ float *Line;
+} DelayLine;
+
typedef struct {
BOOL using_eax;
unsigned long environment;
@@ -120,6 +129,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 df05f8e..d12cdd0 100644
--- a/dlls/dsound/eax.c
+++ b/dlls/dsound/eax.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2015 Mark Harmstone
+ * Copyright (c) 2008-9 Christopher Fitzgerald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -91,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)
@@ -114,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);
DSOUND_RefreshCPFieldsProc(dsb);
@@ -137,7 +231,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.0.5--

View File

@ -0,0 +1,81 @@
From 035fe59abb8f8e8444421198838619d532ae840e Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 15:38:15 +0000
Subject: [PATCH 12/18] dsound: Add EAX VerbPass stub.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/eax.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
--------------2.0.5
Content-Type: text/x-patch; name="0012-dsound-Add-EAX-VerbPass-stub.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0012-dsound-Add-EAX-VerbPass-stub.patch"
diff --git a/dlls/dsound/eax.c b/dlls/dsound/eax.c
index d12cdd0..82b5a6a 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.0.5--

View File

@ -0,0 +1,140 @@
From 0c5e512bfe56e21b71c86744410108ac329099e4 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 17:57:38 +0000
Subject: [PATCH 13/18] dsound: Implement EAX lowpass filter.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 7 +++++++
dlls/dsound/eax.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)
--------------2.0.5
Content-Type: text/x-patch; name="0013-dsound-Implement-EAX-lowpass-filter.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0013-dsound-Implement-EAX-lowpass-filter.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 7565233..51bafe0 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -120,6 +120,11 @@ typedef struct DelayLine
} DelayLine;
typedef struct {
+ float coeff;
+ float history[2];
+} FILTER;
+
+typedef struct {
BOOL using_eax;
unsigned long environment;
float volume;
@@ -133,6 +138,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 82b5a6a..54d90cd 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.0.5--

View File

@ -0,0 +1,103 @@
From 8bb87c66ab1fc62d21e3b386d81a8269d979f369 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:00:10 +0000
Subject: [PATCH 14/18] dsound: Add delay line EAX functions.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 1 +
dlls/dsound/eax.c | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0014-dsound-Add-delay-line-EAX-functions.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0014-dsound-Add-delay-line-EAX-functions.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 51bafe0..4e7748c 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -141,6 +141,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 54d90cd..8aafb2a 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.0.5--

View File

@ -0,0 +1,241 @@
From 197e2cef559b2eba88f7446e550e7c0343cfa23f Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:09:34 +0000
Subject: [PATCH 15/18] dsound: Implement EAX early reflections.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 7 +++
dlls/dsound/eax.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0015-dsound-Implement-EAX-early-reflections.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0015-dsound-Implement-EAX-early-reflections.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 4e7748c..1c5716d 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -143,6 +143,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 8aafb2a..5d1eaed 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.0.5--

View File

@ -0,0 +1,138 @@
From d4203ee7e94bc232202b7e9bcf8a4627086c22e8 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:19:17 +0000
Subject: [PATCH 16/18] dsound: Implement EAX decorrelator.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 3 +++
dlls/dsound/eax.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0016-dsound-Implement-EAX-decorrelator.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0016-dsound-Implement-EAX-decorrelator.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index 1c5716d..ca26dea 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -150,6 +150,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 5d1eaed..43697a6 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.0.5--

View File

@ -0,0 +1,386 @@
From d7e40d814a33a3a794e4dabdf0ba78da22d59e4a Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:21:02 +0000
Subject: [PATCH 17/18] dsound: Implement EAX late reverb.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 13 +++
dlls/dsound/eax.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 268 insertions(+), 1 deletion(-)
--------------2.0.5
Content-Type: text/x-patch; name="0017-dsound-Implement-EAX-late-reverb.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0017-dsound-Implement-EAX-late-reverb.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index ca26dea..bb9e529 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -153,6 +153,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 43697a6..178c186 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.0.5--

View File

@ -0,0 +1,165 @@
From efae62efac5e05562c8771107d2f6af0bf0e0114 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 22 Mar 2015 18:21:18 +0000
Subject: [PATCH 18/18] dsound: Implement EAX late all-pass filter.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.0.5"
This is a multi-part message in MIME format.
--------------2.0.5
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
---
dlls/dsound/dsound_eax.h | 5 +++++
dlls/dsound/eax.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+)
--------------2.0.5
Content-Type: text/x-patch; name="0018-dsound-Implement-EAX-late-all-pass-filter.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0018-dsound-Implement-EAX-late-all-pass-filter.patch"
diff --git a/dlls/dsound/dsound_eax.h b/dlls/dsound/dsound_eax.h
index bb9e529..527b081 100644
--- a/dlls/dsound/dsound_eax.h
+++ b/dlls/dsound/dsound_eax.h
@@ -156,8 +156,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 178c186..aec6e1b 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.0.5--