[PATCH v5 0/6] MR11082: dsound: Speed up resampling, part 7
-- v5: dsound: Get all channel samples in one go. dsound: Get rid of get_aux and read the values directly. https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> --- dlls/dsound/dsound_private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index c9b8a1b202d..b64483e39a0 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -43,8 +43,8 @@ typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl; typedef struct DirectSoundDevice DirectSoundDevice; /* dsound_convert.h */ -typedef float (*bitsgetfunc)(const IDirectSoundBufferImpl *, BYTE *, DWORD); -typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *, DWORD, DWORD, float); +typedef float (*bitsgetfunc)(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); +typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); extern const bitsgetfunc getbpp[5]; void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void putieee32_sum(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> --- dlls/dsound/dsound_convert.c | 6 +++--- dlls/dsound/dsound_private.h | 3 ++- dlls/dsound/mixer.c | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index c1acc95652c..5672fc7acbc 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -89,7 +89,9 @@ static float get32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) return sample / (float)0x80000000U; } -static float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +const bitsgetfunc getbpp[4] = {get8, get16, get24, get32}; + +float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) { const BYTE *buf = base + 4 * channel; const float *sbuf = (const float*)(buf); @@ -97,8 +99,6 @@ static float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD chan return *sbuf; } -const bitsgetfunc getbpp[5] = {get8, get16, get24, get32, getieee32}; - float get_mono(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) { DWORD channels = dsb->pwfx->nChannels; diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index b64483e39a0..a9ff0f04e3e 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -45,7 +45,8 @@ typedef struct DirectSoundDevice DirectSoundDevice; /* dsound_convert.h */ typedef float (*bitsgetfunc)(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); -extern const bitsgetfunc getbpp[5]; +extern const bitsgetfunc getbpp[4]; +float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void putieee32_sum(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void mixieee32(float *src, float *dst, unsigned samples); diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index c8d0ea369d2..56e7b3b95c6 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -137,7 +137,7 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) dsb->freqAccNum = (dsb->freqAccNum * (LONG64)dsb->freqAdjustDen + oldFreqAdjustDen / 2) / oldFreqAdjustDen; - dsb->get_aux = ieee ? getbpp[4] : getbpp[dsb->pwfx->wBitsPerSample/8 - 1]; + dsb->get_aux = ieee ? getieee32 : getbpp[dsb->pwfx->wBitsPerSample/8 - 1]; dsb->put_aux = putieee32; dsb->get = dsb->get_aux; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> --- dlls/dsound/dsound_convert.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index 5672fc7acbc..2a5878b2c95 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -47,14 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -#ifdef WORDS_BIGENDIAN -#define le16(x) RtlUshortByteSwap((x)) -#define le32(x) RtlUlongByteSwap((x)) -#else -#define le16(x) (x) -#define le32(x) (x) -#endif - static float get8(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) { const BYTE *buf = base + channel; @@ -65,8 +57,7 @@ static float get16(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) { const BYTE *buf = base + 2 * channel; const SHORT *sbuf = (const SHORT*)(buf); - SHORT sample = (SHORT)le16(*sbuf); - return sample / (float)0x8000; + return sbuf[0] / (float)0x8000; } static float get24(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) @@ -85,8 +76,7 @@ static float get32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) { const BYTE *buf = base + 4 * channel; const LONG *sbuf = (const LONG*)(buf); - LONG sample = le32(*sbuf); - return sample / (float)0x80000000U; + return sbuf[0] / (float)0x80000000U; } const bitsgetfunc getbpp[4] = {get8, get16, get24, get32}; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> --- dlls/dsound/dsound_convert.c | 18 ++++++------------ dlls/dsound/dsound_private.h | 2 +- dlls/dsound/mixer.c | 5 +++-- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index 2a5878b2c95..d6c86f1959d 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -89,18 +89,6 @@ float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) return *sbuf; } -float get_mono(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) -{ - DWORD channels = dsb->pwfx->nChannels; - DWORD c; - float val = 0; - /* XXX: does Windows include LFE into the mix? */ - for (c = 0; c < channels; c++) - val += dsb->get_aux(dsb, base, c); - val /= channels; - return val; -} - void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) { BYTE *buf = (BYTE *)dsb->device->tmp_buffer; @@ -164,6 +152,12 @@ void put_stereo2surround51(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD c } } +void put_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +{ + /* XXX: does Windows include LFE into the mix? */ + dsb->put_aux(dsb, pos, 0, value); +} + void put_surround512stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) { /* based on analyzing a recording of a dsound downmix */ diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index a9ff0f04e3e..7f38d223767 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -170,12 +170,12 @@ struct IDirectSoundBufferImpl struct list entry; }; -float get_mono(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_mono2quad(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_stereo2quad(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_mono2surround51(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_stereo2surround51(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); +void put_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_surround512stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_surround712stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void put_quad2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 56e7b3b95c6..6bded757739 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -164,8 +164,9 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) } else if (ochannels == 1) { - dsb->mix_channels = 1; - dsb->get = get_mono; + dsb->mix_channels = ichannels; + dsb->put = put_mono; + dsb->put_aux = putieee32_sum; } else if (ichannels == 2 && ochannels == 4) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> --- dlls/dsound/dsound_private.h | 2 +- dlls/dsound/mixer.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 7f38d223767..c569aa64eb5 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -162,7 +162,7 @@ struct IDirectSoundBufferImpl BOOL ds3db_need_recalc; /* Used for bit depth conversion */ int mix_channels; - bitsgetfunc get, get_aux; + bitsgetfunc get; bitsputfunc put, put_aux; int num_filters; DSFilter* filters; diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 6bded757739..7234394e8df 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -137,10 +137,9 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) dsb->freqAccNum = (dsb->freqAccNum * (LONG64)dsb->freqAdjustDen + oldFreqAdjustDen / 2) / oldFreqAdjustDen; - dsb->get_aux = ieee ? getieee32 : getbpp[dsb->pwfx->wBitsPerSample/8 - 1]; dsb->put_aux = putieee32; - dsb->get = dsb->get_aux; + dsb->get = ieee ? getieee32 : getbpp[dsb->pwfx->wBitsPerSample/8 - 1]; dsb->put = dsb->put_aux; if (ichannels == ochannels) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
From: Anton Baskanov <baskanov@gmail.com> Inspired by a patch by Matteo Bruni, which was in turn inspired by a patch by Giovanni Mascellani. --- dlls/dsound/dsound_convert.c | 56 ++++++++++++++++++--------- dlls/dsound/dsound_private.h | 4 +- dlls/dsound/mixer.c | 74 ++++++++++++++++++++++++++---------- 3 files changed, 95 insertions(+), 39 deletions(-) diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index d6c86f1959d..3160a4ddefa 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -47,46 +47,68 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -static float get8(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +static void get8(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel) { + DWORD channels = dsb->pwfx->nChannels; const BYTE *buf = base + channel; - return (buf[0] - 0x80) / (float)0x80; + int i; + + for (i = 0; i < samples; ++i) + dst[i] = (buf[i * channels] - 0x80) / (float)0x80; } -static float get16(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +static void get16(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel) { + DWORD channels = dsb->pwfx->nChannels; const BYTE *buf = base + 2 * channel; const SHORT *sbuf = (const SHORT*)(buf); - return sbuf[0] / (float)0x8000; + int i; + + for (i = 0; i < samples; ++i) + dst[i] = sbuf[i * channels] / (float)0x8000; } -static float get24(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +static void get24(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel) { - LONG sample; + DWORD channels = dsb->pwfx->nChannels; const BYTE *buf = base + 3 * channel; - - /* The next expression deliberately has an overflow for buf[2] >= 0x80, - this is how negative values are made. - */ - sample = (buf[0] << 8) | (buf[1] << 16) | (buf[2] << 24); - return sample / (float)0x80000000U; + int i; + + for (i = 0; i < samples; ++i) { + /* The next expression deliberately has an overflow for buf[2] >= 0x80, + this is how negative values are made. + */ + LONG sample = + (buf[i * channels * 3 + 0] << 8) | + (buf[i * channels * 3 + 1] << 16) | + (buf[i * channels * 3 + 2] << 24); + dst[i] = sample / (float)0x80000000U; + } } -static float get32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +static void get32(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel) { + DWORD channels = dsb->pwfx->nChannels; const BYTE *buf = base + 4 * channel; const LONG *sbuf = (const LONG*)(buf); - return sbuf[0] / (float)0x80000000U; + int i; + + for (i = 0; i < samples; ++i) + dst[i] = sbuf[i * channels] / (float)0x80000000U; } const bitsgetfunc getbpp[4] = {get8, get16, get24, get32}; -float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel) +void getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel) { + DWORD channels = dsb->pwfx->nChannels; const BYTE *buf = base + 4 * channel; const float *sbuf = (const float*)(buf); - /* The value will be clipped later, when put into some non-float buffer */ - return *sbuf; + int i; + + for (i = 0; i < samples; ++i) + /* The value will be clipped later, when put into some non-float buffer */ + dst[i] = sbuf[i * channels]; } void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index c569aa64eb5..fc6fbfd1cc5 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -43,10 +43,10 @@ typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl; typedef struct DirectSoundDevice DirectSoundDevice; /* dsound_convert.h */ -typedef float (*bitsgetfunc)(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); +typedef void (*bitsgetfunc)(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel); typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); extern const bitsgetfunc getbpp[4]; -float getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, DWORD channel); +void getieee32(const IDirectSoundBufferImpl *dsb, BYTE *base, float *dst, unsigned samples, DWORD channel); void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void putieee32_sum(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); void mixieee32(float *src, float *dst, unsigned samples); diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 7234394e8df..fca7f09d6b6 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -279,12 +279,28 @@ void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len } } -static inline float get_current_sample(const IDirectSoundBufferImpl *dsb, - BYTE *buffer, DWORD buflen, DWORD mixpos, DWORD channel) +static inline void get_samples(const IDirectSoundBufferImpl *dsb, BYTE *buffer, DWORD buflen, + DWORD mixpos, DWORD channel, DWORD count, float *dst) { - if (mixpos >= buflen && !(dsb->playflags & DSBPLAY_LOOPING)) - return 0.0f; - return dsb->get(dsb, buffer + (mixpos % buflen), channel); + UINT istride = dsb->pwfx->nBlockAlign; + DWORD advance; + DWORD pos; + + if (!(dsb->playflags & DSBPLAY_LOOPING)) { + advance = buflen < mixpos ? 0 : min((buflen - mixpos) / istride, count); + dsb->get(dsb, buffer + mixpos, dst, advance, channel); + memset(dst + advance, 0, (count - advance) * sizeof(float)); + return; + } + + advance = min((buflen - mixpos % buflen) / istride, count); + dsb->get(dsb, buffer + mixpos % buflen, dst, advance, channel); + pos = advance; + while (pos < count) { + advance = min(buflen / istride, count - pos); + dsb->get(dsb, buffer, dst + pos, advance, channel); + pos += advance; + } } #ifdef __SSE__ @@ -536,7 +552,7 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, DWORD *f UINT required_input = max( (freqAcc_start + (count - 1) * dsb->freqAdjustNum) / dsb->freqAdjustDen + FIR_WIDTH, (freqAcc_start + (count - 1 + FIR_WIDTH) * dsb->freqAdjustNum) / dsb->freqAdjustDen); - float *intermediate, *output, *itmp; + float *intermediate, *output; DWORD len = required_input * channels; /* Allocate an output buffer for each channel with padding on both ends as @@ -570,14 +586,14 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, DWORD *f * if you want -msse3 to have any effect. * This is good for CPU cache effects, too. */ - itmp = intermediate; for (channel = 0; channel < channels; channel++) { - for (i = 0; i < committed_samples; i++) - *(itmp++) = get_current_sample(dsb, dsb->committedbuff, - dsb->writelead, dsb->committed_mixpos + i * istride, channel); - for (; i < required_input; i++) - *(itmp++) = get_current_sample(dsb, dsb->buffer->memory, - dsb->buflen, dsb->sec_mixpos + i * istride, channel); + get_samples(dsb, dsb->committedbuff, dsb->writelead, dsb->committed_mixpos, channel, + committed_samples, intermediate + channel * required_input); + if (required_input > committed_samples) + get_samples(dsb, dsb->buffer->memory, dsb->buflen, + dsb->sec_mixpos + committed_samples * istride, channel, + required_input - committed_samples, + intermediate + channel * required_input + committed_samples); } for (channel = 0; channel < channels; channel++) @@ -597,25 +613,43 @@ static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count) UINT istride = dsb->pwfx->nBlockAlign; UINT ostride = dsb->device->pwfx->nChannels * sizeof(float); UINT committed_samples = 0; + float *intermediate; DWORD channel, i; + DWORD len = count * dsb->mix_channels; + len *= sizeof(float); + if (!secondarybuffer_is_audible(dsb)) return count; + if (!dsb->device->cp_buffer) { + dsb->device->cp_buffer = malloc(len); + dsb->device->cp_buffer_len = len; + } else if (len > dsb->device->cp_buffer_len) { + dsb->device->cp_buffer = realloc(dsb->device->cp_buffer, len); + dsb->device->cp_buffer_len = len; + } + + intermediate = dsb->device->cp_buffer; + if(dsb->use_committed) { committed_samples = (dsb->writelead - dsb->committed_mixpos) / istride; committed_samples = committed_samples <= count ? committed_samples : count; } - for (i = 0; i < committed_samples; i++) - for (channel = 0; channel < dsb->mix_channels; channel++) - dsb->put(dsb, i * ostride, channel, get_current_sample(dsb, dsb->committedbuff, - dsb->writelead, dsb->committed_mixpos + i * istride, channel)); + for (channel = 0; channel < dsb->mix_channels; channel++) + { + get_samples(dsb, dsb->committedbuff, dsb->writelead, dsb->committed_mixpos, channel, + committed_samples, intermediate + channel * count); + if (count > committed_samples) + get_samples(dsb, dsb->buffer->memory, dsb->buflen, + dsb->sec_mixpos + committed_samples * istride, channel, + count - committed_samples, intermediate + channel * count + committed_samples); + } - for (; i < count; 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->buffer->memory, - dsb->buflen, dsb->sec_mixpos + i * istride, channel)); + dsb->put(dsb, i * ostride, channel, intermediate[channel * count + i]); return count; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
v5: - Fix indentation in `DSOUND_RecalcFormat`. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082#note_144776
On Mon Jun 22 09:55:31 2026 +0000, Anton Baskanov wrote:
Removed `getieee32` from the `getbpp` and now call it directly. Right, that's even better :smile:
I think we can follow this up with moving `getieee32()` into mixer.c, so it can be `static` again and we can get rid of the declaration in dsound_private.h. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082#note_144800
On Mon Jun 22 09:55:31 2026 +0000, Anton Baskanov wrote:
I'm not sure moving the helpers to `mixer.c` would add much value. I can do it in a separate MR, if you think it's worthwhile. It's not super important at this point, given that they aren't called for each sample anymore and the overhead for the unnecessary function prologue + epilogue probably isn't that much. But I see no reason for them to be in their own separate file in any case.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082#note_144801
Never mind, I ran some tests on Windows and it looks like the DMOs should be applied before resampling, not after.
Very interesting! It would be nice to have some Wine test for it at some point.
Dropped the put\_ changes from this MR. I'll have to move the DMO processing before resampling first ([dsound-dmo-before-resample](https://gitlab.winehq.org/baskanov/wine/-/commits/dsound-dmo-before-resample...)).
I had a cursory look at the branch and I generally like what I see :slight_smile: --- I wrote the following paragraphs before your latest update. The specific point isn't relevant anymore, but I think it can still be useful as a snapshot of what I think about dsound performance at this point. At the moment I think I'd be pretty happy to accept a 20% perf decrease if it avoids having separate code for each src and dst format (be it in separate functions or as switch cases). I rebased my dsound-perf branch on top of current Wine, with the ability to switch between the cubic and the FIR resamplers. It's definitely not clean or nice (e.g. I haven't changed the cubic resampler for the downsample case like you did with the FIR one) but it should be good enough for some rough perf testing and comparison. For reference, running `mixer.exe 128` with the SSE2 cubic resampler uses ~3 times less CPU% for me than with the SSE FIR one (that's on an AMD Ryzen 9 6900HS). I think we're rapidly getting to diminishing returns with further optimizations, outside of "radical" changes like switching the resampling algorithm entirely. Moving the mixing to the `put_` helpers seems like a good idea with not many downsides, in terms of maintainability or otherwise; past that, and generally speaking, I don't think it's worth to significantly increase code complexity for marginal perf gains. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082#note_144802
On Fri Jul 3 06:56:15 2026 +0000, Anton Baskanov wrote:
Done. Ah, indeed, that's nice.
Actually, thinking about it some more, I suspect that nowadays we can simply assume that the mixing format has >= 2 channels. We already require floats; a legitimate audio setup exposing floats but not stereo output seems extremely unlikely. For what it's worth, recent Windows versions have more or less thrown mono output under the bus as well. IIRC from when I was testing mono output on Windows a few months ago, on Windows 10 there's only a toggle hidden quite deep somewhere in the advanced sound settings to enable it; I couldn't find anything at all on Windows 11. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082#note_144803
This merge request was approved by Matteo Bruni. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11082
participants (4)
-
Anton Baskanov -
Anton Baskanov (@baskanov) -
Huw Davies (@huw) -
Matteo Bruni (@Mystral)