Signed-off-by: Paul Gofman pgofman@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);
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Wed, Mar 17, 2021 at 07:41:52PM +0300, Paul Gofman wrote:
Signed-off-by: Paul Gofman pgofman@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);
if(FAILED(hr)){ WARN("Initialize failed: %08x\n", hr); IAudioClient_Release(stream->client);period, 0, &stream->stream_fmtex.Format, NULL);
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