On Mon, Feb 01, 2021 at 04:56:38PM +0200, Arkadiusz Hiler wrote:
From: Andrew Eikum aeikum@codeweavers.com
I'm fine with how you've done it, but if you'd like Git authorship for the tests, you could send that patch separately.
In spatialaudio.c:
+static HRESULT activate_stream(SpatialAudioStreamImpl *stream) +{
- WAVEFORMATEXTENSIBLE *object_fmtex = (WAVEFORMATEXTENSIBLE *)stream->params.ObjectFormat;
- HRESULT hr;
- REFERENCE_TIME period;
- if(!(object_fmtex->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
(object_fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&IsEqualGUID(&object_fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))){FIXME("Only float formats are supported for now\n");return E_INVALIDARG;- }
- hr = IMMDevice_Activate(stream->sa_client->mmdev, &IID_IAudioClient,
CLSCTX_INPROC_SERVER, NULL, (void**)&stream->client);- if(FAILED(hr)){
WARN("Activate failed: %08x\n", hr);return hr;- }
- hr = IAudioClient_GetDevicePeriod(stream->client, &period, NULL);
- if(FAILED(hr)){
WARN("GetDevicePeriod failed: %08x\n", hr);IAudioClient_Release(stream->client);return hr;- }
- stream->stream_fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- static_mask_to_channels(stream->params.StaticObjectTypeMask,
&stream->stream_fmtex.Format.nChannels, &stream->stream_fmtex.dwChannelMask,stream->static_object_map);- stream->stream_fmtex.Format.nSamplesPerSec = stream->params.ObjectFormat->nSamplesPerSec;
- stream->stream_fmtex.Format.wBitsPerSample = stream->params.ObjectFormat->wBitsPerSample;
- stream->stream_fmtex.Format.nBlockAlign = (stream->stream_fmtex.Format.nChannels * stream->stream_fmtex.Format.wBitsPerSample) / 8;
- stream->stream_fmtex.Format.nAvgBytesPerSec = stream->stream_fmtex.Format.nSamplesPerSec * stream->stream_fmtex.Format.nBlockAlign;
- stream->stream_fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
- 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,
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);return hr;- }
- /* XXX: OK that this is the user's handle? */
We can remove this comment, we are cloning the handle below.
+static HRESULT WINAPI SAC_ActivateSpatialAudioStream(ISpatialAudioClient *iface,
const PROPVARIANT *prop, REFIID riid, void **stream)+{
- SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
- SpatialAudioObjectRenderStreamActivationParams *params;
- HRESULT hr;
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), stream);
- if(IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStream)){
SpatialAudioStreamImpl *obj;if(prop &&(prop->vt != VT_BLOB ||prop->u.blob.cbSize != sizeof(SpatialAudioObjectRenderStreamActivationParams))){WARN("Got invalid params\n");*stream = NULL;return E_INVALIDARG;}params = (SpatialAudioObjectRenderStreamActivationParams*) prop->u.blob.pBlobData;if(params->StaticObjectTypeMask & AudioObjectType_Dynamic){*stream = NULL;return E_INVALIDARG;}if(!params->ObjectFormat || memcmp(params->ObjectFormat, &This->object_fmtex.Format, sizeof(*params->ObjectFormat) + params->ObjectFormat->cbSize)) {*stream = NULL;return AUDCLNT_E_UNSUPPORTED_FORMAT;}obj = heap_alloc_zero(sizeof(SpatialAudioStreamImpl));obj->ISpatialAudioObjectRenderStream_iface.lpVtbl = &ISpatialAudioObjectRenderStream_vtbl;obj->ref = 1;memcpy(&obj->params, params, sizeof(obj->params));obj->update_frames = ~0;InitializeCriticalSection(&obj->lock);list_init(&obj->objects);obj->sa_client = This;SAC_AddRef(&This->ISpatialAudioClient_iface);obj->params.ObjectFormat = clone_fmtex(obj->params.ObjectFormat);if(obj->params.EventHandle != INVALID_HANDLE_VALUE &&obj->params.EventHandle != 0)
The tests show you can't give a NULL or invalid handle, so I think you could check for this and bail out earlier.
In tests/spatialaudio.c:
+static void fill_activation_params(SpatialAudioObjectRenderStreamActivationParams *activation_params) +{
- activation_params->StaticObjectTypeMask = \
AudioObjectType_FrontLeft |AudioObjectType_FrontRight |AudioObjectType_FrontCenter |AudioObjectType_LowFrequency |AudioObjectType_SideLeft |AudioObjectType_SideRight |AudioObjectType_BackLeft |AudioObjectType_BackRight |AudioObjectType_TopFrontLeft |AudioObjectType_TopFrontRight |AudioObjectType_TopBackLeft |AudioObjectType_TopBackRight;- activation_params->MinDynamicObjectCount = 0;
- activation_params->MaxDynamicObjectCount = 0;
- activation_params->Category = AudioCategory_GameEffects;
- activation_params->EventHandle = event;
- activation_params->NotifyObject = NULL;
activation_params->ObjectFormat = &format;
Mixed tabs/spaces (and all over this file).
+static void test_audio_object_buffers(void) +{
HRESULT hr;ISpatialAudioObjectRenderStream *sas = NULL;- ISpatialAudioObject *sao[4];
UINT32 dyn_object_count, frame_count, buffer_length;BYTE *buffer;INT i;- SpatialAudioObjectRenderStreamActivationParams activation_params;
- PROPVARIANT activation_params_prop;
- PropVariantInit(&activation_params_prop);
- activation_params_prop.vt = VT_BLOB;
- activation_params_prop.blob.cbSize = sizeof(activation_params);
- activation_params_prop.blob.pBlobData = (BYTE*) &activation_params;
fill_activation_params(&activation_params);- 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 = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_FrontLeft, &sao[0]);ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);hr = ISpatialAudioObjectRenderStream_Start(sas);ok(hr == S_OK, "Failed to activate spatial audio render stream: 0x%08x\n", hr);hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_FrontRight, &sao[1]);ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);hr = WaitForSingleObject(event, 200);ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x\n", hr);hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_SideLeft, &sao[2]);ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);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 > 0, "Expected to get non-zero frames to update\n");hr = ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas, AudioObjectType_SideRight, &sao[3]);ok(hr == S_OK, "Failed to activate spatial audio object: 0x%08x\n", hr);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\n", hr);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);ok(is_buffer_zeroed(buffer, buffer_length), "Expected audio object's buffer to be zeroed\n");}hr = ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas);ok(hr == S_OK, "Failed to end updating audio objects: 0x%08x\n", hr);hr = WaitForSingleObject(event, 200);ok(hr == WAIT_OBJECT_0, "Expected event to be flagged: 0x%08x\n", hr);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 > 0, "Expected to get non-zero frames to update\n");/* one more iteration but not with every object */for (i = 0; i < ARRAYSIZE(sao) - 1; 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\n", hr);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);ok(is_buffer_zeroed(buffer, buffer_length), "Expected audio object's buffer to be zeroed\n");}hr = ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas);ok(hr == S_OK, "Failed to end updating audio objects: 0x%08x\n", hr);/* ending the stream */hr = ISpatialAudioObject_SetEndOfStream(sao[0], 0);todo_wine ok(hr == SPTLAUDCLNT_E_OUT_OF_ORDER, "Expected that ending the stream at this point won't be allowed: 0x%08x\n", hr);hr = WaitForSingleObject(event, 10000);
This wait timeout can be decreased.
+START_TEST(spatialaudio) +{
- HRESULT hr;
- event = CreateEventA(NULL, FALSE, FALSE, "spatial-audio-test-prog-event");
- ok (event != NULL, "Failed to create event, last error: 0x%08x\n", GetLastError());
Extra space here.
Andrew