From: Mark Harmstone Subject: [PATCH] dsound: Apply filters before sound is multiplied to speakers. (try 2) Message-Id: <550B47B7.5090203@burntcomma.com> Date: Thu, 19 Mar 2015 22:03:35 +0000 Now only copies to a temporary buffer if we have any filters enabled. --- dlls/dsound/mixer.c | 97 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 8dbd15a..09155e1 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -266,15 +266,62 @@ 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) { UINT istride = dsb->pwfx->nBlockAlign; UINT ostride = dsb->device->pwfx->nChannels * sizeof(float); DWORD channel, i; - for (i = 0; i < count; i++) - for (channel = 0; channel < dsb->mix_channels; channel++) - dsb->put(dsb, i * ostride, channel, get_current_sample(dsb, - dsb->sec_mixpos + i * istride, channel)); + BOOL using_filters = dsb->num_filters > 0; + float *buf, *buftmp; + + if (using_filters) { + buf = HeapAlloc(GetProcessHeap(), 0, count * dsb->mix_channels * sizeof(float)); + buftmp = buf; + + for (i = 0; i < count; i++) { + for (channel = 0; channel < dsb->mix_channels; channel++) { + *buftmp = get_current_sample(dsb, dsb->sec_mixpos + i*istride, channel); + buftmp++; + } + } + + 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++; + } + } + + HeapFree(GetProcessHeap(), 0, buf); + } else { + for (i = 0; i < count; i++) + for (channel = 0; channel < dsb->mix_channels; channel++) + dsb->put(dsb, i * ostride, channel, get_current_sample(dsb, + dsb->sec_mixpos + i * istride, channel)); + } + return count; } @@ -299,6 +346,9 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * float* fir_copy = HeapAlloc(GetProcessHeap(), 0, sizeof(float) * fir_cachesize); + BOOL using_filters = dsb->num_filters > 0; + float *buf, *buftmp; + /* Important: this buffer MUST be non-interleaved * if you want -msse3 to have any effect. * This is good for CPU cache effects, too. @@ -309,6 +359,11 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * *(itmp++) = get_current_sample(dsb, dsb->sec_mixpos + i * istride, channel); + if (using_filters) { + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(float) * count * dsb->mix_channels); + buftmp = buf; + } + 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; @@ -332,10 +387,28 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, LONG64 * float* cache = &intermediate[channel * required_input + ipos]; for (j = 0; j < fir_used; j++) sum += fir_copy[j] * cache[j]; - dsb->put(dsb, i * ostride, channel, sum * dsb->firgain); + + if (using_filters) + *(buftmp++) = sum * dsb->firgain; + else + dsb->put(dsb, i * ostride, channel, sum * dsb->firgain); } } + if (using_filters) { + 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++; + } + } + + HeapFree(GetProcessHeap(), 0, buf); + } + *freqAccNum = freqAcc_end % dsb->freqAdjustDen; HeapFree(GetProcessHeap(), 0, fir_copy); @@ -397,8 +470,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) { @@ -410,18 +481,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)