From: Giovanni Mascellani gmascellani@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);
From: Giovanni Mascellani gmascellani@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) {
From: Giovanni Mascellani gmascellani@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;
From: Giovanni Mascellani gmascellani@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; }
From: Giovanni Mascellani gmascellani@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);
As usual the test failures don't seem to be related to my changes. They happen on other MRs as well.