[PATCH] mmdevapi: Make spatial audio objects buffer update size constant.
Andrew Eikum
aeikum at codeweavers.com
Fri Mar 19 09:35:14 CDT 2021
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Wed, Mar 17, 2021 at 07:41:52PM +0300, Paul Gofman wrote:
> Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
> ---
> dlls/mmdevapi/spatialaudio.c | 22 ++-------
> dlls/mmdevapi/tests/Makefile.in | 2 +-
> dlls/mmdevapi/tests/spatialaudio.c | 73 +++++++++++++++++++++++++++---
> 3 files changed, 72 insertions(+), 25 deletions(-)
>
> diff --git a/dlls/mmdevapi/spatialaudio.c b/dlls/mmdevapi/spatialaudio.c
> index cbca57b4890..7ec09b663aa 100644
> --- a/dlls/mmdevapi/spatialaudio.c
> +++ b/dlls/mmdevapi/spatialaudio.c
> @@ -41,8 +41,6 @@
>
> WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
>
> -#define MAX_PERIODS 3
> -
> static UINT32 AudioObjectType_to_index(AudioObjectType type)
> {
> UINT32 o = 0;
> @@ -361,7 +359,6 @@ static HRESULT WINAPI SAORS_BeginUpdatingAudioObjects(ISpatialAudioObjectRenderS
> static BOOL fixme_once = FALSE;
> SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
> SpatialAudioObjectImpl *object;
> - UINT32 pad;
> HRESULT hr;
>
> TRACE("(%p)->(%p, %p)\n", This, dyn_count, frames);
> @@ -373,18 +370,7 @@ static HRESULT WINAPI SAORS_BeginUpdatingAudioObjects(ISpatialAudioObjectRenderS
> return SPTLAUDCLNT_E_OUT_OF_ORDER;
> }
>
> - hr = IAudioClient_GetCurrentPadding(This->client, &pad);
> - if(FAILED(hr)){
> - WARN("GetCurrentPadding failed: %08x\n", hr);
> - LeaveCriticalSection(&This->lock);
> - return hr;
> - }
> -
> - if(pad < This->period_frames * MAX_PERIODS){
> - This->update_frames = This->period_frames * MAX_PERIODS - pad;
> - }else{
> - This->update_frames = 0;
> - }
> + This->update_frames = This->period_frames;
>
> if(This->update_frames > 0){
> hr = IAudioRenderClient_GetBuffer(This->render, This->update_frames, (BYTE **)&This->buf);
> @@ -496,7 +482,7 @@ static HRESULT WINAPI SAORS_ActivateSpatialAudioObject(ISpatialAudioObjectRender
> obj->sa_stream = This;
> SAORS_AddRef(&This->ISpatialAudioObjectRenderStream_iface);
>
> - obj->buf = heap_alloc_zero(This->period_frames * MAX_PERIODS * This->sa_client->object_fmtex.Format.nBlockAlign);
> + obj->buf = heap_alloc_zero(This->period_frames * This->sa_client->object_fmtex.Format.nBlockAlign);
>
> EnterCriticalSection(&This->lock);
>
> @@ -616,7 +602,7 @@ static HRESULT WINAPI SAC_GetMaxFrameCount(ISpatialAudioClient *iface,
>
> TRACE("(%p)->(%p, %p)\n", This, format, count);
>
> - *count = MulDiv(period, format->nSamplesPerSec, 10000000) * MAX_PERIODS;
> + *count = MulDiv(period, format->nSamplesPerSec, 10000000);
>
> return S_OK;
> }
> @@ -731,7 +717,7 @@ static HRESULT activate_stream(SpatialAudioStreamImpl *stream)
>
> hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED,
> AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
> - period * MAX_PERIODS, 0, &stream->stream_fmtex.Format, NULL);
> + period, 0, &stream->stream_fmtex.Format, NULL);
> if(FAILED(hr)){
> WARN("Initialize failed: %08x\n", hr);
> IAudioClient_Release(stream->client);
> diff --git a/dlls/mmdevapi/tests/Makefile.in b/dlls/mmdevapi/tests/Makefile.in
> index 062ad413922..dd180a253b9 100644
> --- a/dlls/mmdevapi/tests/Makefile.in
> +++ b/dlls/mmdevapi/tests/Makefile.in
> @@ -1,5 +1,5 @@
> TESTDLL = mmdevapi.dll
> -IMPORTS = ole32 version user32 advapi32
> +IMPORTS = ole32 version user32 advapi32 winmm
>
> C_SRCS = \
> capture.c \
> diff --git a/dlls/mmdevapi/tests/spatialaudio.c b/dlls/mmdevapi/tests/spatialaudio.c
> index f2612499350..d9ccc429ce8 100644
> --- a/dlls/mmdevapi/tests/spatialaudio.c
> +++ b/dlls/mmdevapi/tests/spatialaudio.c
> @@ -29,6 +29,7 @@
>
> #include "mmdeviceapi.h"
> #include "spatialaudioclient.h"
> +#include "mmsystem.h"
>
> static IMMDeviceEnumerator *mme = NULL;
> static IMMDevice *dev = NULL;
> @@ -269,15 +270,14 @@ static BOOL is_buffer_zeroed(const BYTE *buffer, UINT32 buffer_length)
>
> static void test_audio_object_buffers(void)
> {
> - HRESULT hr;
> + UINT32 dyn_object_count, frame_count, max_frame_count, buffer_length;
> + SpatialAudioObjectRenderStreamActivationParams activation_params;
> ISpatialAudioObjectRenderStream *sas = NULL;
> + PROPVARIANT activation_params_prop;
> ISpatialAudioObject *sao[4];
> - UINT32 dyn_object_count, frame_count, buffer_length;
> BYTE *buffer;
> - INT i;
> -
> - SpatialAudioObjectRenderStreamActivationParams activation_params;
> - PROPVARIANT activation_params_prop;
> + INT i, j, k;
> + HRESULT hr;
>
> PropVariantInit(&activation_params_prop);
> activation_params_prop.vt = VT_BLOB;
> @@ -288,6 +288,17 @@ static void test_audio_object_buffers(void)
> hr = ISpatialAudioClient_ActivateSpatialAudioStream(sac, &activation_params_prop, &IID_ISpatialAudioObjectRenderStream, (void**)&sas);
> ok(hr == S_OK, "Failed to activate spatial audio stream: 0x%08x\n", hr);
>
> + hr = ISpatialAudioClient_GetMaxFrameCount(sac, &format, &max_frame_count);
> + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
> + frame_count = format.nSamplesPerSec / 100; /* 10ms */
> + /* Most of the time the frame count matches the 10ms interval exactly.
> + * However (seen on some Testbot machines) it might be a bit higher for some reason. */
> + ok(max_frame_count <= frame_count + frame_count / 4, "Got unexpected frame count %u.\n", frame_count);
> +
> + /* The tests below which check frame count from _BeginUpdatingAudioObjects fail on some Testbot machines
> + * with max_frame_count from _GetMaxFrameCount(). */
> + max_frame_count = frame_count + frame_count / 4;
> +
> hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_FrontLeft, &sao[0]);
> ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);
>
> @@ -306,6 +317,7 @@ static void test_audio_object_buffers(void)
> hr = ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas, &dyn_object_count, &frame_count);
> ok(hr == S_OK, "Failed to beging updating audio objects: 0x%08x\n", hr);
> ok(dyn_object_count == 0, "Unexpected dynamic objects\n");
> + ok(frame_count <= max_frame_count, "Got unexpected frame count %u.\n", frame_count);
>
> hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_SideRight, &sao[3]);
> ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);
> @@ -323,6 +335,55 @@ static void test_audio_object_buffers(void)
> hr = ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas);
> ok(hr == S_OK, "Failed to end updating audio objects: 0x%08x\n", hr);
>
> + /* Emulate underrun and test frame count approximate limit. */
> +
> + /* Force 1ms Sleep() timer resolution. */
> + timeBeginPeriod(1);
> + for (j = 0; j < 20; ++j)
> + {
> + hr = WaitForSingleObject(event, 200);
> + ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x, j %u.\n", hr, j);
> +
> + hr = ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas, &dyn_object_count, &frame_count);
> + ok(hr == S_OK, "Failed to beging updating audio objects: 0x%08x\n", hr);
> + ok(dyn_object_count == 0, "Unexpected dynamic objects\n");
> + ok(frame_count <= max_frame_count, "Got unexpected frame_count %u.\n", frame_count);
> +
> + /* Audio starts crackling with delays 10ms and above. However, setting such delay (that is, the delay
> + * which skips the whole quantum) breaks SA on some Testbot machines: _BeginUpdatingAudioObjects fails
> + * with SPTLAUDCLNT_E_INTERNAL starting from some iteration or WaitForSingleObject timeouts. That seems
> + * to work on the real hardware though. */
> + Sleep(5);
> +
> + for (i = 0; i < ARRAYSIZE(sao); i++)
> + {
> + hr = ISpatialAudioObject_GetBuffer(sao[i], &buffer, &buffer_length);
> + ok(hr == S_OK, "Expected to be able to get buffers for audio object: 0x%08x, i %d\n", hr, i);
> + ok(buffer != NULL, "Expected to get a non-NULL buffer\n");
> + ok(buffer_length == frame_count * format.wBitsPerSample / 8,
> + "Expected buffer length to be sample_size * frame_count = %hu but got %u\n",
> + frame_count * format.wBitsPerSample / 8, buffer_length);
> +
> + /* Enable to hear the test sound. */
> + if (0)
> + {
> + if (format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
> + {
> + for (k = 0; k < frame_count; ++k)
> + {
> + float time_sec = 10.0f / 1000.0f * (j + (float)k / frame_count);
> +
> + /* 440Hz tone. */
> + ((float *)buffer)[k] = sinf(2.0f * M_PI * time_sec * 440.0f);
> + }
> + }
> + }
> + }
> + hr = ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas);
> + ok(hr == S_OK, "Failed to end updating audio objects: 0x%08x\n", hr);
> + }
> + timeEndPeriod(1);
> +
> hr = WaitForSingleObject(event, 200);
> ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x\n", hr);
>
> --
> 2.30.2
>
>
More information about the wine-devel
mailing list