From cc21d373b53a819758a39c5c9c7fb0cf004d18cc Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Fri, 27 Mar 2015 21:24:40 +0000 Subject: [PATCH] Added patch to implement EAX support in dsound. --- ...-cp_fields_proc-variable-for-buffers.patch | 107 +++++ ...ters-before-sound-is-multiplied-to-s.patch | 270 ++++++++++++ ...und-Add-EAX-v1-constants-and-structs.patch | 135 ++++++ ...dsound-Report-that-we-support-EAX-v1.patch | 49 +++ .../0005-dsound-Add-EAX-propset-stubs.patch | 145 +++++++ .../0006-dsound-Add-EAX-presets.patch | 151 +++++++ ...t-getting-and-setting-EAX-properties.patch | 254 ++++++++++++ ...etting-and-setting-EAX-buffer-proper.patch | 153 +++++++ ...9-dsound-Add-EAX-init-and-free-stubs.patch | 133 ++++++ ...sound-Feed-data-through-EAX-function.patch | 70 ++++ ...0011-dsound-Allocate-EAX-delay-lines.patch | 205 ++++++++++ .../0012-dsound-Add-EAX-VerbPass-stub.patch | 81 ++++ ...-dsound-Implement-EAX-lowpass-filter.patch | 140 +++++++ ...-dsound-Add-delay-line-EAX-functions.patch | 103 +++++ ...ound-Implement-EAX-early-reflections.patch | 241 +++++++++++ ...16-dsound-Implement-EAX-decorrelator.patch | 138 +++++++ ...017-dsound-Implement-EAX-late-reverb.patch | 386 ++++++++++++++++++ ...d-Implement-EAX-late-all-pass-filter.patch | 165 ++++++++ 18 files changed, 2926 insertions(+) create mode 100644 patches/dsound-EAX/0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch create mode 100644 patches/dsound-EAX/0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch create mode 100644 patches/dsound-EAX/0003-dsound-Add-EAX-v1-constants-and-structs.patch create mode 100644 patches/dsound-EAX/0004-dsound-Report-that-we-support-EAX-v1.patch create mode 100644 patches/dsound-EAX/0005-dsound-Add-EAX-propset-stubs.patch create mode 100644 patches/dsound-EAX/0006-dsound-Add-EAX-presets.patch create mode 100644 patches/dsound-EAX/0007-dsound-Support-getting-and-setting-EAX-properties.patch create mode 100644 patches/dsound-EAX/0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch create mode 100644 patches/dsound-EAX/0009-dsound-Add-EAX-init-and-free-stubs.patch create mode 100644 patches/dsound-EAX/0010-dsound-Feed-data-through-EAX-function.patch create mode 100644 patches/dsound-EAX/0011-dsound-Allocate-EAX-delay-lines.patch create mode 100644 patches/dsound-EAX/0012-dsound-Add-EAX-VerbPass-stub.patch create mode 100644 patches/dsound-EAX/0013-dsound-Implement-EAX-lowpass-filter.patch create mode 100644 patches/dsound-EAX/0014-dsound-Add-delay-line-EAX-functions.patch create mode 100644 patches/dsound-EAX/0015-dsound-Implement-EAX-early-reflections.patch create mode 100644 patches/dsound-EAX/0016-dsound-Implement-EAX-decorrelator.patch create mode 100644 patches/dsound-EAX/0017-dsound-Implement-EAX-late-reverb.patch create mode 100644 patches/dsound-EAX/0018-dsound-Implement-EAX-late-all-pass-filter.patch diff --git a/patches/dsound-EAX/0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch b/patches/dsound-EAX/0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch new file mode 100644 index 00000000..c0b2a2b0 --- /dev/null +++ b/patches/dsound-EAX/0001-dsound-Add-cp_fields_proc-variable-for-buffers.patch @@ -0,0 +1,107 @@ +From d417a8b92faa9cef33db57fc259186facce51c12 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch b/patches/dsound-EAX/0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch new file mode 100644 index 00000000..8cb574ff --- /dev/null +++ b/patches/dsound-EAX/0002-dsound-Apply-filters-before-sound-is-multiplied-to-s.patch @@ -0,0 +1,270 @@ +From bb619d6e5ee74714f2f524fb91dbe1da697dc977 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0003-dsound-Add-EAX-v1-constants-and-structs.patch b/patches/dsound-EAX/0003-dsound-Add-EAX-v1-constants-and-structs.patch new file mode 100644 index 00000000..02bb71f2 --- /dev/null +++ b/patches/dsound-EAX/0003-dsound-Add-EAX-v1-constants-and-structs.patch @@ -0,0 +1,135 @@ +From a76952522ebce6b2c0e08cb98baa4cd6a261975a Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0004-dsound-Report-that-we-support-EAX-v1.patch b/patches/dsound-EAX/0004-dsound-Report-that-we-support-EAX-v1.patch new file mode 100644 index 00000000..10bde9c0 --- /dev/null +++ b/patches/dsound-EAX/0004-dsound-Report-that-we-support-EAX-v1.patch @@ -0,0 +1,49 @@ +From 293bff08260858a815cf2acc863da482bc53522a Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0005-dsound-Add-EAX-propset-stubs.patch b/patches/dsound-EAX/0005-dsound-Add-EAX-propset-stubs.patch new file mode 100644 index 00000000..7fd456c0 --- /dev/null +++ b/patches/dsound-EAX/0005-dsound-Add-EAX-propset-stubs.patch @@ -0,0 +1,145 @@ +From 4b43643b83bfa1a69232bbc8489b116feb8c61bc Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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 ++#include ++ ++#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-- + + diff --git a/patches/dsound-EAX/0006-dsound-Add-EAX-presets.patch b/patches/dsound-EAX/0006-dsound-Add-EAX-presets.patch new file mode 100644 index 00000000..dbc652f4 --- /dev/null +++ b/patches/dsound-EAX/0006-dsound-Add-EAX-presets.patch @@ -0,0 +1,151 @@ +From ac35ac1bf501d36b32ec3be2b2e73b4506932435 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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 + #include + +@@ -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-- + + diff --git a/patches/dsound-EAX/0007-dsound-Support-getting-and-setting-EAX-properties.patch b/patches/dsound-EAX/0007-dsound-Support-getting-and-setting-EAX-properties.patch new file mode 100644 index 00000000..c8652a24 --- /dev/null +++ b/patches/dsound-EAX/0007-dsound-Support-getting-and-setting-EAX-properties.patch @@ -0,0 +1,254 @@ +From 563415997a8a95b87c47ea8fe72e172aae5cd3d5 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch b/patches/dsound-EAX/0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch new file mode 100644 index 00000000..a9623cce --- /dev/null +++ b/patches/dsound-EAX/0008-dsound-Support-getting-and-setting-EAX-buffer-proper.patch @@ -0,0 +1,153 @@ +From 3765b43e4c646b3cbbcfbec79a2e84791d88349e Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0009-dsound-Add-EAX-init-and-free-stubs.patch b/patches/dsound-EAX/0009-dsound-Add-EAX-init-and-free-stubs.patch new file mode 100644 index 00000000..1deb555e --- /dev/null +++ b/patches/dsound-EAX/0009-dsound-Add-EAX-init-and-free-stubs.patch @@ -0,0 +1,133 @@ +From 5b3eccbf7a66a21dbb38d4115f01389102775116 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0010-dsound-Feed-data-through-EAX-function.patch b/patches/dsound-EAX/0010-dsound-Feed-data-through-EAX-function.patch new file mode 100644 index 00000000..f2d00b8b --- /dev/null +++ b/patches/dsound-EAX/0010-dsound-Feed-data-through-EAX-function.patch @@ -0,0 +1,70 @@ +From 94026d1694362d5f94f74e8f0c362a1c1efe4bec Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0011-dsound-Allocate-EAX-delay-lines.patch b/patches/dsound-EAX/0011-dsound-Allocate-EAX-delay-lines.patch new file mode 100644 index 00000000..85359bab --- /dev/null +++ b/patches/dsound-EAX/0011-dsound-Allocate-EAX-delay-lines.patch @@ -0,0 +1,205 @@ +From b8a5fe26a390ced4438df0e50b7c93fd4150ed06 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0012-dsound-Add-EAX-VerbPass-stub.patch b/patches/dsound-EAX/0012-dsound-Add-EAX-VerbPass-stub.patch new file mode 100644 index 00000000..1ba7588c --- /dev/null +++ b/patches/dsound-EAX/0012-dsound-Add-EAX-VerbPass-stub.patch @@ -0,0 +1,81 @@ +From 035fe59abb8f8e8444421198838619d532ae840e Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0013-dsound-Implement-EAX-lowpass-filter.patch b/patches/dsound-EAX/0013-dsound-Implement-EAX-lowpass-filter.patch new file mode 100644 index 00000000..a7ad2f66 --- /dev/null +++ b/patches/dsound-EAX/0013-dsound-Implement-EAX-lowpass-filter.patch @@ -0,0 +1,140 @@ +From 0c5e512bfe56e21b71c86744410108ac329099e4 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0014-dsound-Add-delay-line-EAX-functions.patch b/patches/dsound-EAX/0014-dsound-Add-delay-line-EAX-functions.patch new file mode 100644 index 00000000..cd003351 --- /dev/null +++ b/patches/dsound-EAX/0014-dsound-Add-delay-line-EAX-functions.patch @@ -0,0 +1,103 @@ +From 8bb87c66ab1fc62d21e3b386d81a8269d979f369 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0015-dsound-Implement-EAX-early-reflections.patch b/patches/dsound-EAX/0015-dsound-Implement-EAX-early-reflections.patch new file mode 100644 index 00000000..c22e33ed --- /dev/null +++ b/patches/dsound-EAX/0015-dsound-Implement-EAX-early-reflections.patch @@ -0,0 +1,241 @@ +From 197e2cef559b2eba88f7446e550e7c0343cfa23f Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0016-dsound-Implement-EAX-decorrelator.patch b/patches/dsound-EAX/0016-dsound-Implement-EAX-decorrelator.patch new file mode 100644 index 00000000..bf1b64af --- /dev/null +++ b/patches/dsound-EAX/0016-dsound-Implement-EAX-decorrelator.patch @@ -0,0 +1,138 @@ +From d4203ee7e94bc232202b7e9bcf8a4627086c22e8 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0017-dsound-Implement-EAX-late-reverb.patch b/patches/dsound-EAX/0017-dsound-Implement-EAX-late-reverb.patch new file mode 100644 index 00000000..4be89acc --- /dev/null +++ b/patches/dsound-EAX/0017-dsound-Implement-EAX-late-reverb.patch @@ -0,0 +1,386 @@ +From d7e40d814a33a3a794e4dabdf0ba78da22d59e4a Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + + diff --git a/patches/dsound-EAX/0018-dsound-Implement-EAX-late-all-pass-filter.patch b/patches/dsound-EAX/0018-dsound-Implement-EAX-late-all-pass-filter.patch new file mode 100644 index 00000000..f9342089 --- /dev/null +++ b/patches/dsound-EAX/0018-dsound-Implement-EAX-late-all-pass-filter.patch @@ -0,0 +1,165 @@ +From efae62efac5e05562c8771107d2f6af0bf0e0114 Mon Sep 17 00:00:00 2001 +From: Mark Harmstone +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-- + +