mmdevapi: Make spatial audio objects buffer update size constant.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3a7d95135f
commit
1d66a108b9
|
@ -41,8 +41,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
|
WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
|
||||||
|
|
||||||
#define MAX_PERIODS 3
|
|
||||||
|
|
||||||
static UINT32 AudioObjectType_to_index(AudioObjectType type)
|
static UINT32 AudioObjectType_to_index(AudioObjectType type)
|
||||||
{
|
{
|
||||||
UINT32 o = 0;
|
UINT32 o = 0;
|
||||||
|
@ -361,7 +359,6 @@ static HRESULT WINAPI SAORS_BeginUpdatingAudioObjects(ISpatialAudioObjectRenderS
|
||||||
static BOOL fixme_once = FALSE;
|
static BOOL fixme_once = FALSE;
|
||||||
SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
|
SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
|
||||||
SpatialAudioObjectImpl *object;
|
SpatialAudioObjectImpl *object;
|
||||||
UINT32 pad;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("(%p)->(%p, %p)\n", This, dyn_count, frames);
|
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;
|
return SPTLAUDCLNT_E_OUT_OF_ORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = IAudioClient_GetCurrentPadding(This->client, &pad);
|
This->update_frames = This->period_frames;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(This->update_frames > 0){
|
if(This->update_frames > 0){
|
||||||
hr = IAudioRenderClient_GetBuffer(This->render, This->update_frames, (BYTE **)&This->buf);
|
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;
|
obj->sa_stream = This;
|
||||||
SAORS_AddRef(&This->ISpatialAudioObjectRenderStream_iface);
|
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);
|
EnterCriticalSection(&This->lock);
|
||||||
|
|
||||||
|
@ -616,7 +602,7 @@ static HRESULT WINAPI SAC_GetMaxFrameCount(ISpatialAudioClient *iface,
|
||||||
|
|
||||||
TRACE("(%p)->(%p, %p)\n", This, format, count);
|
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;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -731,7 +717,7 @@ static HRESULT activate_stream(SpatialAudioStreamImpl *stream)
|
||||||
|
|
||||||
hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED,
|
hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED,
|
||||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
|
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)){
|
if(FAILED(hr)){
|
||||||
WARN("Initialize failed: %08x\n", hr);
|
WARN("Initialize failed: %08x\n", hr);
|
||||||
IAudioClient_Release(stream->client);
|
IAudioClient_Release(stream->client);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
TESTDLL = mmdevapi.dll
|
TESTDLL = mmdevapi.dll
|
||||||
IMPORTS = ole32 version user32 advapi32
|
IMPORTS = ole32 version user32 advapi32 winmm
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
capture.c \
|
capture.c \
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "mmdeviceapi.h"
|
#include "mmdeviceapi.h"
|
||||||
#include "spatialaudioclient.h"
|
#include "spatialaudioclient.h"
|
||||||
|
#include "mmsystem.h"
|
||||||
|
|
||||||
static IMMDeviceEnumerator *mme = NULL;
|
static IMMDeviceEnumerator *mme = NULL;
|
||||||
static IMMDevice *dev = 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)
|
static void test_audio_object_buffers(void)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
UINT32 dyn_object_count, frame_count, max_frame_count, buffer_length;
|
||||||
ISpatialAudioObjectRenderStream *sas = NULL;
|
|
||||||
ISpatialAudioObject *sao[4];
|
|
||||||
UINT32 dyn_object_count, frame_count, buffer_length;
|
|
||||||
BYTE *buffer;
|
|
||||||
INT i;
|
|
||||||
|
|
||||||
SpatialAudioObjectRenderStreamActivationParams activation_params;
|
SpatialAudioObjectRenderStreamActivationParams activation_params;
|
||||||
|
ISpatialAudioObjectRenderStream *sas = NULL;
|
||||||
PROPVARIANT activation_params_prop;
|
PROPVARIANT activation_params_prop;
|
||||||
|
ISpatialAudioObject *sao[4];
|
||||||
|
BYTE *buffer;
|
||||||
|
INT i, j, k;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
PropVariantInit(&activation_params_prop);
|
PropVariantInit(&activation_params_prop);
|
||||||
activation_params_prop.vt = VT_BLOB;
|
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);
|
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);
|
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]);
|
hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_FrontLeft, &sao[0]);
|
||||||
ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);
|
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);
|
hr = ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas, &dyn_object_count, &frame_count);
|
||||||
ok(hr == S_OK, "Failed to beging updating audio objects: 0x%08x\n", hr);
|
ok(hr == S_OK, "Failed to beging updating audio objects: 0x%08x\n", hr);
|
||||||
ok(dyn_object_count == 0, "Unexpected dynamic objects\n");
|
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]);
|
hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_SideRight, &sao[3]);
|
||||||
ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);
|
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);
|
hr = ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas);
|
||||||
ok(hr == S_OK, "Failed to end updating audio objects: 0x%08x\n", hr);
|
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);
|
hr = WaitForSingleObject(event, 200);
|
||||||
ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x\n", hr);
|
ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x\n", hr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue