2 * Copyright 2021 Arkadiusz Hiler for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
30 #include "mmdeviceapi.h"
31 #include "spatialaudioclient.h"
34 static IMMDeviceEnumerator
*mme
= NULL
;
35 static IMMDevice
*dev
= NULL
;
36 static ISpatialAudioClient
*sac
= NULL
;
37 static UINT32 max_dyn_count
;
39 static WAVEFORMATEX format
;
41 static void test_formats(void)
44 IAudioFormatEnumerator
*afe
;
45 UINT32 format_count
= 0;
46 WAVEFORMATEX
*fmt
= NULL
;
48 hr
= ISpatialAudioClient_GetSupportedAudioObjectFormatEnumerator(sac
, &afe
);
49 ok(hr
== S_OK
, "Getting format enumerator failed: 0x%08x\n", hr
);
51 hr
= IAudioFormatEnumerator_GetCount(afe
, &format_count
);
52 ok(hr
== S_OK
, "Getting format count failed: 0x%08x\n", hr
);
53 ok(format_count
== 1, "Got wrong format count, expected 1 got %u\n", format_count
);
55 hr
= IAudioFormatEnumerator_GetFormat(afe
, 0, &fmt
);
56 ok(hr
== S_OK
, "Getting format failed: 0x%08x\n", hr
);
57 ok(fmt
!= NULL
, "Expected to get non-NULL format\n");
59 ok(fmt
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
, "Wrong format, expected WAVE_FORMAT_IEEE_FLOAT got %hx\n", fmt
->wFormatTag
);
60 ok(fmt
->nChannels
== 1, "Wrong number of channels, expected 1 got %hu\n", fmt
->nChannels
);
61 ok(fmt
->nSamplesPerSec
== 48000, "Wrong sample ret, expected 48000 got %u\n", fmt
->nSamplesPerSec
);
62 ok(fmt
->wBitsPerSample
== 32, "Wrong bits per sample, expected 32 got %hu\n", fmt
->wBitsPerSample
);
63 ok(fmt
->nBlockAlign
== 4, "Wrong block align, expected 4 got %hu\n", fmt
->nBlockAlign
);
64 ok(fmt
->nAvgBytesPerSec
== 192000, "Wrong avg bytes per sec, expected 192000 got %u\n", fmt
->nAvgBytesPerSec
);
65 ok(fmt
->cbSize
== 0, "Wrong cbSize for simple format, expected 0, got %hu\n", fmt
->cbSize
);
67 memcpy(&format
, fmt
, sizeof(format
));
69 IAudioFormatEnumerator_Release(afe
);
72 static void fill_activation_params(SpatialAudioObjectRenderStreamActivationParams
*activation_params
)
74 activation_params
->StaticObjectTypeMask
= \
75 AudioObjectType_FrontLeft
|
76 AudioObjectType_FrontRight
|
77 AudioObjectType_FrontCenter
|
78 AudioObjectType_LowFrequency
|
79 AudioObjectType_SideLeft
|
80 AudioObjectType_SideRight
|
81 AudioObjectType_BackLeft
|
82 AudioObjectType_BackRight
|
83 AudioObjectType_TopFrontLeft
|
84 AudioObjectType_TopFrontRight
|
85 AudioObjectType_TopBackLeft
|
86 AudioObjectType_TopBackRight
;
88 activation_params
->MinDynamicObjectCount
= 0;
89 activation_params
->MaxDynamicObjectCount
= 0;
90 activation_params
->Category
= AudioCategory_GameEffects
;
91 activation_params
->EventHandle
= event
;
92 activation_params
->NotifyObject
= NULL
;
94 activation_params
->ObjectFormat
= &format
;
97 typedef struct NotifyObject
99 ISpatialAudioObjectRenderStreamNotify ISpatialAudioObjectRenderStreamNotify_iface
;
103 static WINAPI HRESULT
notifyobj_QueryInterface(
104 ISpatialAudioObjectRenderStreamNotify
*This
,
111 static WINAPI ULONG
notifyobj_AddRef(
112 ISpatialAudioObjectRenderStreamNotify
*This
)
114 NotifyObject
*obj
= CONTAINING_RECORD(This
, NotifyObject
, ISpatialAudioObjectRenderStreamNotify_iface
);
115 ULONG ref
= InterlockedIncrement(&obj
->ref
);
119 static WINAPI ULONG
notifyobj_Release(
120 ISpatialAudioObjectRenderStreamNotify
*This
)
122 NotifyObject
*obj
= CONTAINING_RECORD(This
, NotifyObject
, ISpatialAudioObjectRenderStreamNotify_iface
);
123 ULONG ref
= InterlockedDecrement(&obj
->ref
);
127 static WINAPI HRESULT
notifyobj_OnAvailableDynamicObjectCountChange(
128 ISpatialAudioObjectRenderStreamNotify
*This
,
129 ISpatialAudioObjectRenderStreamBase
*stream
,
133 ok(FALSE
, "Expected to never be notified of dynamic object count change\n");
137 static const ISpatialAudioObjectRenderStreamNotifyVtbl notifyobjvtbl
=
139 notifyobj_QueryInterface
,
142 notifyobj_OnAvailableDynamicObjectCountChange
145 static void test_stream_activation(void)
148 WAVEFORMATEX wrong_format
;
149 ISpatialAudioObjectRenderStream
*sas
= NULL
;
151 SpatialAudioObjectRenderStreamActivationParams activation_params
;
152 PROPVARIANT activation_params_prop
;
153 NotifyObject notify_object
;
155 PropVariantInit(&activation_params_prop
);
156 activation_params_prop
.vt
= VT_BLOB
;
157 activation_params_prop
.blob
.cbSize
= sizeof(activation_params
);
158 activation_params_prop
.blob
.pBlobData
= (BYTE
*) &activation_params
;
161 fill_activation_params(&activation_params
);
162 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
163 ok(hr
== S_OK
, "Failed to activate spatial audio stream: 0x%08x\n", hr
);
164 ok(ISpatialAudioObjectRenderStream_Release(sas
) == 0, "Expected to release the last reference\n");
167 fill_activation_params(&activation_params
);
168 activation_params
.EventHandle
= NULL
;
169 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
170 ok(hr
== E_INVALIDARG
, "Expected lack of no EventHandle to be invalid: 0x%08x\n", hr
);
171 ok(sas
== NULL
, "Expected spatial audio stream to be set to NULL upon failed activation\n");
173 activation_params
.EventHandle
= INVALID_HANDLE_VALUE
;
174 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
175 ok(hr
== E_INVALIDARG
, "Expected INVALID_HANDLE_VALUE to be invalid: 0x%08x\n", hr
);
176 ok(sas
== NULL
, "Expected spatial audio stream to be set to NULL upon failed activation\n");
178 /* must use only queried sample rate */
179 fill_activation_params(&activation_params
);
180 memcpy(&wrong_format
, &format
, sizeof(format
));
181 activation_params
.ObjectFormat
= &wrong_format
;
182 wrong_format
.nSamplesPerSec
= 44100;
183 wrong_format
.nAvgBytesPerSec
= wrong_format
.nSamplesPerSec
* wrong_format
.nBlockAlign
;
184 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
185 ok(hr
== AUDCLNT_E_UNSUPPORTED_FORMAT
, "Expected format to be unsupported: 0x%08x\n", hr
);
186 ok(sas
== NULL
, "Expected spatial audio stream to be set to NULL upon failed activation\n");
188 /* dynamic objects are not supported */
189 if (max_dyn_count
== 0)
191 fill_activation_params(&activation_params
);
192 activation_params
.StaticObjectTypeMask
|= AudioObjectType_Dynamic
;
193 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
194 ok(hr
== E_INVALIDARG
, "Expected dynamic objects type be invalid: 0x%08x\n", hr
);
195 ok(sas
== NULL
, "Expected spatial audio stream to be set to NULL upon failed activation\n");
198 activation_params
.MinDynamicObjectCount
= max_dyn_count
+ 1;
199 activation_params
.MaxDynamicObjectCount
= max_dyn_count
+ 1;
200 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
202 ok(hr
== AUDCLNT_E_UNSUPPORTED_FORMAT
, "Expected dynamic object count exceeding max to be unsupported: 0x%08x\n", hr
);
204 ok(hr
== E_INVALIDARG
, "Expected setting dynamic object count to be invalid: 0x%08x\n", hr
);
206 /* ISpatialAudioObjectRenderStreamNotify */
207 fill_activation_params(&activation_params
);
208 notify_object
.ISpatialAudioObjectRenderStreamNotify_iface
.lpVtbl
= ¬ifyobjvtbl
;
209 notify_object
.ref
= 0;
210 activation_params
.NotifyObject
= ¬ify_object
.ISpatialAudioObjectRenderStreamNotify_iface
;
211 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
212 ok(hr
== S_OK
, "Failed to activate spatial audio stream: 0x%08x\n", hr
);
213 ok(notify_object
.ref
== 1, "Expected to get increased NotifyObject's ref count\n");
214 ok(ISpatialAudioObjectRenderStream_Release(sas
) == 0, "Expected to release the last reference\n");
215 ok(notify_object
.ref
== 0, "Expected to get lowered NotifyObject's ref count\n");
218 static void test_audio_object_activation(void)
222 ISpatialAudioObjectRenderStream
*sas
= NULL
;
223 ISpatialAudioObject
*sao1
, *sao2
;
225 SpatialAudioObjectRenderStreamActivationParams activation_params
;
226 PROPVARIANT activation_params_prop
;
228 PropVariantInit(&activation_params_prop
);
229 activation_params_prop
.vt
= VT_BLOB
;
230 activation_params_prop
.blob
.cbSize
= sizeof(activation_params
);
231 activation_params_prop
.blob
.pBlobData
= (BYTE
*) &activation_params
;
233 fill_activation_params(&activation_params
);
234 activation_params
.StaticObjectTypeMask
&= ~AudioObjectType_FrontRight
;
235 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
236 ok(hr
== S_OK
, "Failed to activate spatial audio stream: 0x%08x\n", hr
);
238 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_FrontLeft
, &sao1
);
239 ok(hr
== S_OK
, "Failed to activate spatial audio object: 0x%08x\n", hr
);
240 hr
= ISpatialAudioObject_IsActive(sao1
, &is_active
);
241 todo_wine
ok(hr
== S_OK
, "Failed to check if spatial audio object is active: 0x%08x\n", hr
);
243 ok(is_active
, "Expected spaital audio object to be active\n");
245 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_FrontLeft
, &sao2
);
246 ok(hr
== SPTLAUDCLNT_E_OBJECT_ALREADY_ACTIVE
, "Expected audio object to be already active: 0x%08x\n", hr
);
248 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_FrontRight
, &sao2
);
249 ok(hr
== SPTLAUDCLNT_E_STATIC_OBJECT_NOT_AVAILABLE
, "Expected static object to be not available: 0x%08x\n", hr
);
251 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_Dynamic
, &sao2
);
252 ok(hr
== SPTLAUDCLNT_E_NO_MORE_OBJECTS
, "Expected to not have no more dynamic objects: 0x%08x\n", hr
);
254 ISpatialAudioObject_Release(sao1
);
255 ISpatialAudioObjectRenderStream_Release(sas
);
258 static BOOL
is_buffer_zeroed(const BYTE
*buffer
, UINT32 buffer_length
)
262 for (i
= 0; i
< buffer_length
; i
++)
271 static void test_audio_object_buffers(void)
273 UINT32 dyn_object_count
, frame_count
, max_frame_count
, buffer_length
;
274 SpatialAudioObjectRenderStreamActivationParams activation_params
;
275 ISpatialAudioObjectRenderStream
*sas
= NULL
;
276 PROPVARIANT activation_params_prop
;
277 ISpatialAudioObject
*sao
[4];
282 PropVariantInit(&activation_params_prop
);
283 activation_params_prop
.vt
= VT_BLOB
;
284 activation_params_prop
.blob
.cbSize
= sizeof(activation_params
);
285 activation_params_prop
.blob
.pBlobData
= (BYTE
*) &activation_params
;
287 fill_activation_params(&activation_params
);
288 hr
= ISpatialAudioClient_ActivateSpatialAudioStream(sac
, &activation_params_prop
, &IID_ISpatialAudioObjectRenderStream
, (void**)&sas
);
289 ok(hr
== S_OK
, "Failed to activate spatial audio stream: 0x%08x\n", hr
);
291 hr
= ISpatialAudioClient_GetMaxFrameCount(sac
, &format
, &max_frame_count
);
292 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
293 frame_count
= format
.nSamplesPerSec
/ 100; /* 10ms */
294 /* Most of the time the frame count matches the 10ms interval exactly.
295 * However (seen on some Testbot machines) it might be a bit higher for some reason. */
296 ok(max_frame_count
<= frame_count
+ frame_count
/ 4, "Got unexpected frame count %u.\n", frame_count
);
298 /* The tests below which check frame count from _BeginUpdatingAudioObjects fail on some Testbot machines
299 * with max_frame_count from _GetMaxFrameCount(). */
300 max_frame_count
= frame_count
+ frame_count
/ 4;
302 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_FrontLeft
, &sao
[0]);
303 ok(hr
== S_OK
, "Failed to activate spatial audio object: 0x%08x\n", hr
);
305 hr
= ISpatialAudioObjectRenderStream_Start(sas
);
306 ok(hr
== S_OK
, "Failed to activate spatial audio render stream: 0x%08x\n", hr
);
308 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_FrontRight
, &sao
[1]);
309 ok(hr
== S_OK
, "Failed to activate spatial audio object: 0x%08x\n", hr
);
311 hr
= WaitForSingleObject(event
, 200);
312 ok(hr
== WAIT_OBJECT_0
, "Expected event to be flagged: 0x%08x\n", hr
);
314 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_SideLeft
, &sao
[2]);
315 ok(hr
== S_OK
, "Failed to activate spatial audio object: 0x%08x\n", hr
);
317 hr
= ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas
, &dyn_object_count
, &frame_count
);
318 ok(hr
== S_OK
, "Failed to beging updating audio objects: 0x%08x\n", hr
);
319 ok(dyn_object_count
== 0, "Unexpected dynamic objects\n");
320 ok(frame_count
<= max_frame_count
, "Got unexpected frame count %u.\n", frame_count
);
322 hr
= ISpatialAudioObjectRenderStream_ActivateSpatialAudioObject(sas
, AudioObjectType_SideRight
, &sao
[3]);
323 ok(hr
== S_OK
, "Failed to activate spatial audio object: 0x%08x\n", hr
);
325 for (i
= 0; i
< ARRAYSIZE(sao
); i
++)
327 hr
= ISpatialAudioObject_GetBuffer(sao
[i
], &buffer
, &buffer_length
);
328 ok(hr
== S_OK
, "Expected to be able to get buffers for audio object: 0x%08x\n", hr
);
329 ok(buffer
!= NULL
, "Expected to get a non-NULL buffer\n");
330 ok(buffer_length
== frame_count
* format
.wBitsPerSample
/ 8, "Expected buffer length to be sample_size * frame_count = %hu but got %u\n",
331 frame_count
* format
.wBitsPerSample
/ 8, buffer_length
);
332 ok(is_buffer_zeroed(buffer
, buffer_length
), "Expected audio object's buffer to be zeroed\n");
335 hr
= ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas
);
336 ok(hr
== S_OK
, "Failed to end updating audio objects: 0x%08x\n", hr
);
338 /* Emulate underrun and test frame count approximate limit. */
340 /* Force 1ms Sleep() timer resolution. */
342 for (j
= 0; j
< 20; ++j
)
344 hr
= WaitForSingleObject(event
, 200);
345 ok(hr
== WAIT_OBJECT_0
, "Expected event to be flagged: 0x%08x, j %u.\n", hr
, j
);
347 hr
= ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas
, &dyn_object_count
, &frame_count
);
348 ok(hr
== S_OK
, "Failed to beging updating audio objects: 0x%08x\n", hr
);
349 ok(dyn_object_count
== 0, "Unexpected dynamic objects\n");
350 ok(frame_count
<= max_frame_count
, "Got unexpected frame_count %u.\n", frame_count
);
352 /* Audio starts crackling with delays 10ms and above. However, setting such delay (that is, the delay
353 * which skips the whole quantum) breaks SA on some Testbot machines: _BeginUpdatingAudioObjects fails
354 * with SPTLAUDCLNT_E_INTERNAL starting from some iteration or WaitForSingleObject timeouts. That seems
355 * to work on the real hardware though. */
358 for (i
= 0; i
< ARRAYSIZE(sao
); i
++)
360 hr
= ISpatialAudioObject_GetBuffer(sao
[i
], &buffer
, &buffer_length
);
361 ok(hr
== S_OK
, "Expected to be able to get buffers for audio object: 0x%08x, i %d\n", hr
, i
);
362 ok(buffer
!= NULL
, "Expected to get a non-NULL buffer\n");
363 ok(buffer_length
== frame_count
* format
.wBitsPerSample
/ 8,
364 "Expected buffer length to be sample_size * frame_count = %hu but got %u\n",
365 frame_count
* format
.wBitsPerSample
/ 8, buffer_length
);
367 /* Enable to hear the test sound. */
370 if (format
.wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
)
372 for (k
= 0; k
< frame_count
; ++k
)
374 float time_sec
= 10.0f
/ 1000.0f
* (j
+ (float)k
/ frame_count
);
377 ((float *)buffer
)[k
] = sinf(2.0f
* M_PI
* time_sec
* 440.0f
);
382 hr
= ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas
);
383 ok(hr
== S_OK
, "Failed to end updating audio objects: 0x%08x\n", hr
);
387 hr
= WaitForSingleObject(event
, 200);
388 ok(hr
== WAIT_OBJECT_0
, "Expected event to be flagged: 0x%08x\n", hr
);
390 hr
= ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas
, &dyn_object_count
, &frame_count
);
391 ok(hr
== S_OK
, "Failed to beging updating audio objects: 0x%08x\n", hr
);
392 ok(dyn_object_count
== 0, "Unexpected dynamic objects\n");
394 /* one more iteration but not with every object */
395 for (i
= 0; i
< ARRAYSIZE(sao
) - 1; i
++)
397 hr
= ISpatialAudioObject_GetBuffer(sao
[i
], &buffer
, &buffer_length
);
398 ok(hr
== S_OK
, "Expected to be able to get buffers for audio object: 0x%08x\n", hr
);
399 ok(buffer
!= NULL
, "Expected to get a non-NULL buffer\n");
400 ok(buffer_length
== frame_count
* format
.wBitsPerSample
/ 8, "Expected buffer length to be sample_size * frame_count = %hu but got %u\n",
401 frame_count
* format
.wBitsPerSample
/ 8, buffer_length
);
402 ok(is_buffer_zeroed(buffer
, buffer_length
), "Expected audio object's buffer to be zeroed\n");
405 hr
= ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas
);
406 ok(hr
== S_OK
, "Failed to end updating audio objects: 0x%08x\n", hr
);
408 /* ending the stream */
409 hr
= ISpatialAudioObject_SetEndOfStream(sao
[0], 0);
410 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
);
412 hr
= WaitForSingleObject(event
, 200);
413 ok(hr
== WAIT_OBJECT_0
, "Expected event to be flagged: 0x%08x\n", hr
);
415 hr
= ISpatialAudioObject_SetEndOfStream(sao
[0], 0);
416 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
);
418 hr
= ISpatialAudioObjectRenderStream_BeginUpdatingAudioObjects(sas
, &dyn_object_count
, &frame_count
);
419 ok(hr
== S_OK
, "Failed to beging updating audio objects: 0x%08x\n", hr
);
420 ok(dyn_object_count
== 0, "Unexpected dynamic objects\n");
422 /* expect the object that was not updated last cycle to be invalidated */
423 hr
= ISpatialAudioObject_GetBuffer(sao
[ARRAYSIZE(sao
) - 1], &buffer
, &buffer_length
);
424 todo_wine
ok(hr
== SPTLAUDCLNT_E_RESOURCES_INVALIDATED
, "Expected audio object to be invalidated: 0x%08x\n", hr
);
426 for (i
= 0; i
< ARRAYSIZE(sao
) - 1; i
++)
428 hr
= ISpatialAudioObject_GetBuffer(sao
[i
], &buffer
, &buffer_length
);
429 ok(hr
== S_OK
, "Expected to be able to get buffers for audio object: 0x%08x\n", hr
);
431 hr
= ISpatialAudioObject_SetEndOfStream(sao
[i
], 0);
432 todo_wine
ok(hr
== S_OK
, "Failed to end the stream: 0x%08x\n", hr
);
434 hr
= ISpatialAudioObject_GetBuffer(sao
[i
], &buffer
, &buffer_length
);
435 todo_wine
ok(hr
== SPTLAUDCLNT_E_RESOURCES_INVALIDATED
, "Expected audio object to be invalidated: 0x%08x\n", hr
);
438 hr
= ISpatialAudioObjectRenderStream_EndUpdatingAudioObjects(sas
);
439 ok(hr
== S_OK
, "Failed to end updating audio objects: 0x%08x\n", hr
);
441 for (i
= 0; i
< ARRAYSIZE(sao
); i
++)
443 ISpatialAudioObject_Release(sao
[i
]);
446 ISpatialAudioObjectRenderStream_Release(sas
);
449 START_TEST(spatialaudio
)
453 event
= CreateEventA(NULL
, FALSE
, FALSE
, "spatial-audio-test-prog-event");
454 ok(event
!= NULL
, "Failed to create event, last error: 0x%08x\n", GetLastError());
456 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
457 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&mme
);
460 skip("mmdevapi not available: 0x%08x\n", hr
);
464 hr
= IMMDeviceEnumerator_GetDefaultAudioEndpoint(mme
, eRender
, eMultimedia
, &dev
);
465 ok(hr
== S_OK
|| hr
== E_NOTFOUND
, "GetDefaultAudioEndpoint failed: 0x%08x\n", hr
);
466 if (hr
!= S_OK
|| !dev
)
468 if (hr
== E_NOTFOUND
)
469 skip("No sound card available\n");
471 skip("GetDefaultAudioEndpoint returns 0x%08x\n", hr
);
475 hr
= IMMDevice_Activate(dev
, &IID_ISpatialAudioClient
, CLSCTX_INPROC_SERVER
, NULL
, (void**)&sac
);
476 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "ISpatialAudioClient Activation failed: 0x%08x\n", hr
);
477 if (hr
!= S_OK
|| !dev
)
479 if (hr
== E_NOINTERFACE
)
480 skip("ISpatialAudioClient interface not found\n");
482 skip("ISpatialAudioClient Activation returns 0x%08x\n", hr
);
486 hr
= ISpatialAudioClient_GetMaxDynamicObjectCount(sac
, &max_dyn_count
);
487 ok(hr
== S_OK
, "Failed to get max dynamic object count: 0x%08x\n", hr
);
489 /* that's the default, after manually enabling Windows Sonic it's possible to have max_dyn_count > 0 */
490 /* ok(max_dyn_count == 0, "expected max dynamic object count to be 0 got %u\n", max_dyn_count); */
493 test_stream_activation();
494 test_audio_object_activation();
495 test_audio_object_buffers();
497 ISpatialAudioClient_Release(sac
);
501 IMMDevice_Release(dev
);
503 IMMDeviceEnumerator_Release(mme
);