[PATCH v3 0/5] MR9368: dsound: Use AUTOCONVERTPCM when initializing the render audio client.
-- v3: dsound: Do not query for supported formats for the primary buffer. dsound: Do not query for mixing format support. dsound: Simplify computing the mixing format. dsound: Always require a floating-point mixing format. dsound: Use AUTOCONVERTPCM when initializing the render audio client. https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
From: Giovanni Mascellani <gmascellani(a)codeweavers.com> Initializing the audio client without AUTOCONVERTPCM is expected to fail when the requested sampling rate or channel count does not match the mixing format. Such behavior is not currently modeled on Wine, but it should be introduced, and since here we expect automatic format conversion to work we add the flag. --- dlls/dsound/primary.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 2073a32240c..451d30309d5 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -306,7 +306,8 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) hres = IAudioClient_Initialize(client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | - AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 800000, 0, wfx, NULL); + AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM, + 800000, 0, wfx, NULL); if(FAILED(hres)){ IAudioClient_Release(client); ERR("Initialize failed: %08lx\n", hres); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
From: Giovanni Mascellani <gmascellani(a)codeweavers.com> The mixer algorithm only supports floating-point, any other format is just unusable for us. Also, AUTOCONVERTPCM is expected to do automatic conversion anyway. --- dlls/dsound/primary.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 451d30309d5..8d4b53b8e19 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -115,7 +115,8 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client HRESULT hr; if (!forcewave) { - WAVEFORMATEXTENSIBLE *mixwfe; + WAVEFORMATEXTENSIBLE *mixwfe, testwfe; + hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe); if (FAILED(hr)) @@ -131,24 +132,15 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client mixwfe->dwChannelMask = speaker_config_to_channel_mask(device->speaker_config); } - if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { - WAVEFORMATEXTENSIBLE testwfe = *mixwfe; - - testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32; - testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8; - testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign; - - if (FAILED(IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &testwfe.Format, (WAVEFORMATEX**)&retwfe))) - w = DSOUND_CopyFormat(&mixwfe->Format); - else if (retwfe) - w = DSOUND_CopyFormat(&retwfe->Format); - else - w = DSOUND_CopyFormat(&testwfe.Format); - CoTaskMemFree(retwfe); - retwfe = NULL; - } else - w = DSOUND_CopyFormat(&mixwfe->Format); + testwfe = *mixwfe; + + testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32; + testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8; + testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign; + + w = DSOUND_CopyFormat(&testwfe.Format); + CoTaskMemFree(mixwfe); } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM || device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
From: Giovanni Mascellani <gmascellani(a)codeweavers.com> --- dlls/dsound/primary.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 8d4b53b8e19..1190a38cfb4 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -115,33 +115,31 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client HRESULT hr; if (!forcewave) { - WAVEFORMATEXTENSIBLE *mixwfe, testwfe; + WAVEFORMATEXTENSIBLE *mixwfe, wfe; hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe); - if (FAILED(hr)) return hr; - if (mixwfe->Format.nChannels < device->num_speakers) { + wfe = *mixwfe; + CoTaskMemFree(mixwfe); + + wfe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + wfe.Samples.wValidBitsPerSample = wfe.Format.wBitsPerSample = 32; + + if (wfe.Format.nChannels < device->num_speakers) { device->speaker_config = DSOUND_FindSpeakerConfig(device->mmdevice, mixwfe->Format.nChannels); DSOUND_ParseSpeakerConfig(device); } else if (mixwfe->Format.nChannels > device->num_speakers) { - mixwfe->Format.nChannels = device->num_speakers; - mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8; - mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign; - mixwfe->dwChannelMask = speaker_config_to_channel_mask(device->speaker_config); + wfe.Format.nChannels = device->num_speakers; + wfe.dwChannelMask = speaker_config_to_channel_mask(device->speaker_config); } - testwfe = *mixwfe; + wfe.Format.nBlockAlign = wfe.Format.nChannels * wfe.Format.wBitsPerSample / 8; + wfe.Format.nAvgBytesPerSec = wfe.Format.nSamplesPerSec * wfe.Format.nBlockAlign; - testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - testwfe.Samples.wValidBitsPerSample = testwfe.Format.wBitsPerSample = 32; - testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8; - testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign; - - w = DSOUND_CopyFormat(&testwfe.Format); - - CoTaskMemFree(mixwfe); + w = DSOUND_CopyFormat(&wfe.Format); } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM || device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { WAVEFORMATEX *wi = device->primary_pwfx; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
From: Giovanni Mascellani <gmascellani(a)codeweavers.com> Despite its name, IsFormatSupported() doesn't really predict what Initialize() will return, especially when AUTOCONVERTPCM is used. So there's no point querying it, let's just call Initialize() and that will tell whether the format is accepted or not. It is also useless to change to the recommended format: both if we're going to use a primary buffer or not, the format that is computer in DSOUND_WaveFormat() is what everything else expects, and if it cannot be satisfied there's not point continuing. --- dlls/dsound/primary.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 1190a38cfb4..9a5557f2c83 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -110,7 +110,6 @@ static DWORD DSOUND_FindSpeakerConfig(IMMDevice *mmdevice, int channels) static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client, BOOL forcewave, WAVEFORMATEX **wfx) { - WAVEFORMATEXTENSIBLE *retwfe = NULL; WAVEFORMATEX *w; HRESULT hr; @@ -170,16 +169,6 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client if (!w) return DSERR_OUTOFMEMORY; - hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, w, (WAVEFORMATEX**)&retwfe); - if (retwfe) { - memcpy(w, retwfe, sizeof(WAVEFORMATEX) + retwfe->Format.cbSize); - CoTaskMemFree(retwfe); - } - if (FAILED(hr)) { - WARN("IsFormatSupported failed: %08lx\n", hr); - free(w); - return hr; - } *wfx = w; return S_OK; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
From: Giovanni Mascellani <gmascellani(a)codeweavers.com> We use AUTOCONVERTPCM, so everything is supported anyway. --- dlls/dsound/dsound.c | 51 +++--------------------------------- dlls/dsound/dsound_private.h | 2 -- 2 files changed, 3 insertions(+), 50 deletions(-) diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c index 7629810db50..fe8011d9b94 100644 --- a/dlls/dsound/dsound.c +++ b/dlls/dsound/dsound.c @@ -247,27 +247,6 @@ static ULONG DirectSoundDevice_Release(DirectSoundDevice * device) return ref; } -BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate, - DWORD depth, WORD channels) -{ - WAVEFORMATEX fmt, *junk; - HRESULT hr; - - fmt.wFormatTag = WAVE_FORMAT_PCM; - fmt.nChannels = channels; - fmt.nSamplesPerSec = rate; - fmt.wBitsPerSample = depth; - fmt.nBlockAlign = (channels * depth) / 8; - fmt.nAvgBytesPerSec = rate * fmt.nBlockAlign; - fmt.cbSize = 0; - - hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &fmt, &junk); - if(SUCCEEDED(hr)) - CoTaskMemFree(junk); - - return hr == S_OK; -} - static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID) { HRESULT hr = DS_OK; @@ -338,33 +317,9 @@ static HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGU ZeroMemory(&device->drvcaps, sizeof(device->drvcaps)); - if(DSOUND_check_supported(device->client, 11025, 8, 1) || - DSOUND_check_supported(device->client, 22050, 8, 1) || - DSOUND_check_supported(device->client, 44100, 8, 1) || - DSOUND_check_supported(device->client, 48000, 8, 1) || - DSOUND_check_supported(device->client, 96000, 8, 1)) - device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYMONO; - - if(DSOUND_check_supported(device->client, 11025, 16, 1) || - DSOUND_check_supported(device->client, 22050, 16, 1) || - DSOUND_check_supported(device->client, 44100, 16, 1) || - DSOUND_check_supported(device->client, 48000, 16, 1) || - DSOUND_check_supported(device->client, 96000, 16, 1)) - device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYMONO; - - if(DSOUND_check_supported(device->client, 11025, 8, 2) || - DSOUND_check_supported(device->client, 22050, 8, 2) || - DSOUND_check_supported(device->client, 44100, 8, 2) || - DSOUND_check_supported(device->client, 48000, 8, 2) || - DSOUND_check_supported(device->client, 96000, 8, 2)) - device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARYSTEREO; - - if(DSOUND_check_supported(device->client, 11025, 16, 2) || - DSOUND_check_supported(device->client, 22050, 16, 2) || - DSOUND_check_supported(device->client, 44100, 16, 2) || - DSOUND_check_supported(device->client, 48000, 16, 2) || - DSOUND_check_supported(device->client, 96000, 16, 2)) - device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO; + /* We use AUTOCONVERTPCM, so everything is supported. */ + device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARY16BIT; + device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO | DSCAPS_PRIMARYSTEREO; /* the dsound mixer supports all of the following */ device->drvcaps.dwFlags |= DSCAPS_SECONDARY8BIT | DSCAPS_SECONDARY16BIT; diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 132af52880c..89053cff722 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -265,7 +265,5 @@ void setup_dsound_options(void); HRESULT get_mmdevice(EDataFlow flow, const GUID *tgt, IMMDevice **device); -BOOL DSOUND_check_supported(IAudioClient *client, DWORD rate, - DWORD depth, WORD channels); HRESULT enumerate_mmdevices(EDataFlow flow, GUID *guids, LPDSENUMCALLBACKW cb, void *user); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
On Fri Nov 7 12:18:58 2025 +0000, Huw Davies wrote:
This hunk is adding a bunch of tabs. I know it gets removed in the next commit, but still. Whoops, I'm not used to that and apparently my editor autodetected that tabs were to be used. Fixed now (also in the first commit).
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9368#note_121154
This merge request was approved by Huw Davies. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9368
participants (3)
-
Giovanni Mascellani -
Giovanni Mascellani (@giomasce) -
Huw Davies (@huw)