From: Anton Baskanov <baskanov@gmail.com> Inspired by a patch by Matteo Bruni. --- dlls/dsound/dsound_convert.c | 178 ++++++++++++++++++++++------------- dlls/dsound/dsound_private.h | 20 ++-- dlls/dsound/mixer.c | 40 +++++--- 3 files changed, 152 insertions(+), 86 deletions(-) diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index 8bc3eb38203..296c1b16e96 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -219,97 +219,134 @@ static inline LONG f_to_32(float value) return le32(lrintf(value * 0x80000000U)); } -void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void putieee32(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - BYTE *buf = (BYTE *)dsb->device->tmp_buffer; - float *fbuf = (float*)(buf + pos + sizeof(float) * channel); - *fbuf = value; + DWORD channels = dsb->device->pwfx->nChannels; + float *dst = dsb->device->tmp_buffer; + int i; + + for (i = 0; i < samples; ++i) + dst[i * channels + channel] = src[i]; } -void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_mono2stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; - dst[0] = value; - dst[1] = value; + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 2 + 0] = value; + dst[i * 2 + 1] = value; + } } -void put_mono2quad(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_mono2quad(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); - - dst[0] = value; - dst[1] = value; - dst[2] = value; - dst[3] = value; + float *dst = dsb->device->tmp_buffer; + int i; + + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 4 + 0] = value; + dst[i * 4 + 1] = value; + dst[i * 4 + 2] = value; + dst[i * 4 + 3] = value; + } } -void put_stereo2quad(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_stereo2quad(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; if (channel == 0) { /* Left */ - dst[0] = value; /* Front left */ - dst[2] = value; /* Back left */ + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 4 + 0] = value; /* Front left */ + dst[i * 4 + 2] = value; /* Back left */ + } } else if (channel == 1) { /* Right */ - dst[1] = value; /* Front right */ - dst[3] = value; /* Back right */ + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 4 + 1] = value; /* Front right */ + dst[i * 4 + 3] = value; /* Back right */ + } } } -void put_mono2surround51(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_mono2surround51(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); - - dst[0] = value; - dst[1] = value; - dst[2] = value; - dst[3] = value; - dst[4] = value; - dst[5] = value; + float *dst = dsb->device->tmp_buffer; + int i; + + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 6 + 0] = value; + dst[i * 6 + 1] = value; + dst[i * 6 + 2] = value; + dst[i * 6 + 3] = value; + dst[i * 6 + 4] = value; + dst[i * 6 + 5] = value; + } } -void put_stereo2surround51(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_stereo2surround51(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; if (channel == 0) { /* Left */ - dst[0] = value; /* Front left */ - dst[4] = value; /* Back left */ - - dst[2] = 0.0f; /* Mute front centre */ - dst[3] = 0.0f; /* Mute LFE */ + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 6 + 0] = value; /* Front left */ + dst[i * 6 + 4] = value; /* Back left */ + + dst[i * 6 + 2] = 0.0f; /* Mute front centre */ + dst[i * 6 + 3] = 0.0f; /* Mute LFE */ + } } else if (channel == 1) { /* Right */ - dst[1] = value; /* Front right */ - dst[5] = value; /* Back right */ + for (i = 0; i < samples; ++i) { + float value = src[i]; + dst[i * 6 + 1] = value; /* Front right */ + dst[i * 6 + 5] = value; /* Back right */ + } } } -void put_surround512stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_surround512stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; /* based on analyzing a recording of a dsound downmix */ switch(channel){ case 4: /* surround left */ - dst[0] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i] * 0.24f; break; case 0: /* front left */ - dst[0] += value; + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i]; break; case 5: /* surround right */ - dst[1] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i] * 0.24f; case 1: /* front right */ - dst[1] += value; + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i]; break; case 2: /* centre */ - dst[0] += value * 0.7f; - dst[1] += value * 0.7f; + for (i = 0; i < samples; ++i) { + float value = src[i] * 0.7f; + dst[i * 2 + 0] += value; + dst[i * 2 + 1] += value; + } break; case 3: @@ -318,39 +355,49 @@ void put_surround512stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD c } } -void put_surround712stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_surround712stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; /* based on analyzing a recording of a dsound downmix */ switch(channel){ case 6: /* back left */ - dst[0] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i] * 0.24f; break; case 4: /* surround left */ - dst[0] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i] * 0.24f; break; case 0: /* front left */ - dst[0] += value; + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i]; break; case 7: /* back right */ - dst[1] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i] * 0.24f; break; case 5: /* surround right */ - dst[1] += value * 0.24f; + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i] * 0.24f; case 1: /* front right */ - dst[1] += value; + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i]; break; case 2: /* centre */ - dst[0] += value * 0.7f; - dst[1] += value * 0.7f; + for (i = 0; i < samples; ++i) { + float value = src[i] * 0.7f; + dst[i * 2 + 0] += value; + dst[i * 2 + 1] += value; + } break; case 3: @@ -359,27 +406,32 @@ void put_surround712stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD c } } -void put_quad2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_quad2stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel) { - float *dst = (float *)((BYTE *)dsb->device->tmp_buffer + pos); + float *dst = dsb->device->tmp_buffer; + int i; /* based on pulseaudio's downmix algorithm */ switch(channel){ case 2: /* back left */ - dst[0] += value * 0.1f; /* (1/9) / (sum of left volumes) */ + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i] * 0.1f; /* (1/9) / (sum of left volumes) */ break; case 0: /* front left */ - dst[0] += value * 0.9f; /* 1 / (sum of left volumes) */ + for (i = 0; i < samples; ++i) + dst[i * 2 + 0] += src[i] * 0.9f; /* 1 / (sum of left volumes) */ break; case 3: /* back right */ - dst[1] += value * 0.1f; /* (1/9) / (sum of right volumes) */ + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i] * 0.1f; /* (1/9) / (sum of right volumes) */ break; case 1: /* front right */ - dst[1] += value * 0.9f; /* 1 / (sum of right volumes) */ + for (i = 0; i < samples; ++i) + dst[i * 2 + 1] += src[i] * 0.9f; /* 1 / (sum of right volumes) */ break; } } diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 8753410b18b..b1443bf49ad 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -44,10 +44,10 @@ 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); +typedef void (*bitsputfunc)(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); extern const bitsgetfunc getbpp[5]; extern const bitsgetfunc getbpp_mono[5]; -void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value); +void putieee32(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); void mixieee32(float *src, float *dst, unsigned samples); typedef void (*normfunc)(const void *src, void *dst, unsigned samples); extern const normfunc normfunctions[4]; @@ -173,14 +173,14 @@ struct IDirectSoundBufferImpl struct list entry; }; -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_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); +void put_mono2stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_mono2quad(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_stereo2quad(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_mono2surround51(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_stereo2surround51(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_surround512stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_surround712stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); +void put_quad2stereo(const IDirectSoundBufferImpl *dsb, float *src, unsigned samples, DWORD channel); HRESULT secondarybuffer_create(DirectSoundDevice *device, const DSBUFFERDESC *dsbd, IDirectSoundBuffer **buffer); diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index fd532408999..7c2d99d65f1 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -519,7 +519,6 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, DWORD *f { UINT i, channel; UINT istride = dsb->pwfx->nBlockAlign; - UINT ostride = dsb->device->pwfx->nChannels * sizeof(float); UINT committed_samples = 0; LONG64 freqAcc_start = *freqAccNum; @@ -579,9 +578,8 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, DWORD *f required_input, count, intermediate + channel * required_input, output + channel * (FIR_WIDTH - 1 + count)); - for(i = 0; i < count; ++i) - for (channel = 0; channel < channels; channel++) - dsb->put(dsb, i * ostride, channel, output[channel * (FIR_WIDTH - 1 + count) + i]); + for (channel = 0; channel < channels; channel++) + dsb->put(dsb, output + channel * (FIR_WIDTH - 1 + count), count, channel); return max_ipos; } @@ -589,27 +587,43 @@ static UINT cp_fields_resample(IDirectSoundBufferImpl *dsb, UINT count, DWORD *f static UINT cp_fields_noresample(IDirectSoundBufferImpl *dsb, UINT count) { UINT istride = dsb->pwfx->nBlockAlign; - UINT ostride = dsb->device->pwfx->nChannels * sizeof(float); + float *intermediate, *itmp; UINT committed_samples = 0; 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)); + itmp = intermediate; + for (channel = 0; channel < dsb->mix_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 < count; i++) + *(itmp++) = get_current_sample(dsb, dsb->buffer->memory, + dsb->buflen, dsb->sec_mixpos + i * istride, channel); + } - for (; 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)); + for (channel = 0; channel < dsb->mix_channels; channel++) + dsb->put(dsb, intermediate + channel * count, count, channel); return count; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11082