From: Giovanni Mascellani gmascellani@codeweavers.com
Since 00211db0d08d60ee9a0e40206bf7cf9b5b88987b, and on native, IAudioClient::Initialize() rejects formats that differ by channel count from the mix format, which might be smaller than the channel count the underlying audio system supports. Therefore an internal API is introduced to bypass the channel count check.
This fixes a failure in spatialaudio tests. --- dlls/mmdevapi/client.c | 9 +++++---- dlls/mmdevapi/mmdevapi_private.h | 6 ++++++ dlls/mmdevapi/spatialaudio.c | 7 ++++++- 3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/mmdevapi/client.c b/dlls/mmdevapi/client.c index 61b9167f3c6..23aa3c745cf 100644 --- a/dlls/mmdevapi/client.c +++ b/dlls/mmdevapi/client.c @@ -366,7 +366,8 @@ skip: return wcsdup(name); }
-static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_period, +HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_period, + const BOOL check_mix_format, const AUDCLNT_SHAREMODE mode, const DWORD flags, REFERENCE_TIME duration, REFERENCE_TIME period, const WAVEFORMATEX *fmt, const GUID *sessionguid) @@ -398,7 +399,7 @@ static HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_ return E_INVALIDARG; }
- if (mode == AUDCLNT_SHAREMODE_SHARED) { + if (check_mix_format && mode == AUDCLNT_SHAREMODE_SHARED) { WAVEFORMATEX *mix_fmt; HRESULT hr;
@@ -702,7 +703,7 @@ static HRESULT WINAPI client_Initialize(IAudioClient3 *iface, AUDCLNT_SHAREMODE wine_dbgstr_longlong(period), fmt, debugstr_guid(sessionguid));
- return stream_init(This, TRUE, mode, flags, duration, period, fmt, sessionguid); + return stream_init(This, TRUE, TRUE, mode, flags, duration, period, fmt, sessionguid); }
static HRESULT WINAPI client_GetBufferSize(IAudioClient3 *iface, UINT32 *out) @@ -1137,7 +1138,7 @@ static HRESULT WINAPI client_InitializeSharedAudioStream(IAudioClient3 *iface, D
period = period_frames * (REFERENCE_TIME)10000000 / format->nSamplesPerSec;
- return stream_init(This, FALSE, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid); + return stream_init(This, FALSE, TRUE, AUDCLNT_SHAREMODE_SHARED, flags, 0, period, format, session_guid); }
const IAudioClient3Vtbl AudioClient3_Vtbl = diff --git a/dlls/mmdevapi/mmdevapi_private.h b/dlls/mmdevapi/mmdevapi_private.h index 8dff5aa0805..094698ef345 100644 --- a/dlls/mmdevapi/mmdevapi_private.h +++ b/dlls/mmdevapi/mmdevapi_private.h @@ -134,3 +134,9 @@ extern void main_loop_stop(void); extern const WCHAR drv_keyW[];
extern HRESULT get_audio_sessions(IMMDevice *device, GUID **ret, int *ret_count); + +extern HRESULT stream_init(struct audio_client *client, const BOOLEAN force_def_period, + const BOOL check_mix_format, + const AUDCLNT_SHAREMODE mode, const DWORD flags, + REFERENCE_TIME duration, REFERENCE_TIME period, + const WAVEFORMATEX *fmt, const GUID *sessionguid); diff --git a/dlls/mmdevapi/spatialaudio.c b/dlls/mmdevapi/spatialaudio.c index eab3ceade6b..82b5f917e2a 100644 --- a/dlls/mmdevapi/spatialaudio.c +++ b/dlls/mmdevapi/spatialaudio.c @@ -700,6 +700,11 @@ static void static_mask_to_channels(AudioObjectType static_mask, WORD *count, DW CONVERT_MASK(AudioObjectType_BackCenter, SPEAKER_BACK_CENTER); }
+static inline struct audio_client *impl_from_IAudioClient(IAudioClient *iface) +{ + return CONTAINING_RECORD(iface, struct audio_client, IAudioClient3_iface); +} + static HRESULT activate_stream(SpatialAudioStreamImpl *stream) { HRESULT hr; @@ -731,7 +736,7 @@ static HRESULT activate_stream(SpatialAudioStreamImpl *stream) stream->stream_fmtex.Samples.wValidBitsPerSample = stream->stream_fmtex.Format.wBitsPerSample; stream->stream_fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
- hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED, + hr = stream_init(impl_from_IAudioClient(stream->client), TRUE, FALSE, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, period, 0, &stream->stream_fmtex.Format, NULL); if(FAILED(hr)){