[PATCH 0/5] MR9368: dsound: Use AUTOCONVERTPCM when initializing the render audio client.
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..95e77cf4dbc 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 95e77cf4dbc..eefbf3affa3 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 eefbf3affa3..340e00bd8a0 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 340e00bd8a0..f450dcaa388 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
As usual the test failures don't seem to be related to my changes. They happen on other MRs as well. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9368#note_120976
participants (2)
-
Giovanni Mascellani -
Giovanni Mascellani (@giomasce)