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--