dwrite: Always initialize output glyph count in GetGlyphs().
[wine.git] / dlls / xaudio2_7 / tests / xaudio2.c
blob502b513fb6bd8f7bd3d2f92ea83ced5fa57473a2
1 /*
2 * Copyright (c) 2015 Andrew Eikum 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
19 #include <windows.h>
20 #include <math.h>
22 #define COBJMACROS
23 #include "wine/test.h"
24 #include "initguid.h"
25 #include "xaudio2.h"
26 #include "xaudio2fx.h"
27 #include "xapo.h"
28 #include "xapofx.h"
29 #include "mmsystem.h"
31 static BOOL xaudio27;
33 static HRESULT (WINAPI *pXAudio2Create)(IXAudio2 **, UINT32, XAUDIO2_PROCESSOR) = NULL;
34 static HRESULT (WINAPI *pCreateAudioVolumeMeter)(IUnknown**) = NULL;
36 #define XA2CALL_0(method) if(xaudio27) hr = IXAudio27_##method((IXAudio27*)xa); else hr = IXAudio2_##method(xa);
37 #define XA2CALL_0V(method) if(xaudio27) IXAudio27_##method((IXAudio27*)xa); else IXAudio2_##method(xa);
38 #define XA2CALL_V(method, ...) if(xaudio27) IXAudio27_##method((IXAudio27*)xa, __VA_ARGS__); else IXAudio2_##method(xa, __VA_ARGS__);
39 #define XA2CALL(method, ...) if(xaudio27) hr = IXAudio27_##method((IXAudio27*)xa, __VA_ARGS__); else hr = IXAudio2_##method(xa, __VA_ARGS__);
41 static void fill_buf(float *buf, WAVEFORMATEX *fmt, DWORD hz, DWORD len_frames)
43 if(winetest_interactive){
44 DWORD offs, c;
45 for(offs = 0; offs < len_frames; ++offs)
46 for(c = 0; c < fmt->nChannels; ++c)
47 buf[offs * fmt->nChannels + c] = sinf(offs * hz * 2 * M_PI / fmt->nSamplesPerSec);
48 }else
49 memset(buf, 0, sizeof(float) * len_frames * fmt->nChannels);
52 static struct _cb_state {
53 BOOL start_called, end_called;
54 } ecb_state, src1_state, src2_state;
56 static int pass_state = 0;
57 static BOOL buffers_called = FALSE;
59 static void WINAPI ECB_OnProcessingPassStart(IXAudio2EngineCallback *This)
61 ok(!xaudio27 || pass_state == 0, "Callbacks called out of order: %u\n", pass_state);
62 ++pass_state;
65 static void WINAPI ECB_OnProcessingPassEnd(IXAudio2EngineCallback *This)
67 ok(!xaudio27 || pass_state == (buffers_called ? 7 : 5), "Callbacks called out of order: %u\n", pass_state);
68 pass_state = 0;
69 buffers_called = FALSE;
72 static void WINAPI ECB_OnCriticalError(IXAudio2EngineCallback *This, HRESULT Error)
74 ok(0, "Unexpected OnCriticalError\n");
77 static const IXAudio2EngineCallbackVtbl ecb_vtbl = {
78 ECB_OnProcessingPassStart,
79 ECB_OnProcessingPassEnd,
80 ECB_OnCriticalError
83 static IXAudio2EngineCallback ecb = { &ecb_vtbl };
85 static IXAudio2VoiceCallback vcb1;
86 static IXAudio2VoiceCallback vcb2;
88 static void WINAPI VCB_OnVoiceProcessingPassStart(IXAudio2VoiceCallback *This,
89 UINT32 BytesRequired)
91 if(This == &vcb1){
92 ok(!xaudio27 || pass_state == (buffers_called ? 4 : 3), "Callbacks called out of order: %u\n", pass_state);
93 ++pass_state;
94 }else{
95 ok(!xaudio27 || pass_state == 1, "Callbacks called out of order: %u\n", pass_state);
96 ++pass_state;
100 static void WINAPI VCB_OnVoiceProcessingPassEnd(IXAudio2VoiceCallback *This)
102 if(This == &vcb1){
103 ok(!xaudio27 || pass_state == (buffers_called ? 6 : 4), "Callbacks called out of order: %u\n", pass_state);
104 ++pass_state;
105 }else{
106 ok(!xaudio27 || pass_state == (buffers_called ? 3 : 2), "Callbacks called out of order: %u\n", pass_state);
107 ++pass_state;
111 static void WINAPI VCB_OnStreamEnd(IXAudio2VoiceCallback *This)
113 ok(0, "Unexpected OnStreamEnd\n");
116 static void WINAPI VCB_OnBufferStart(IXAudio2VoiceCallback *This,
117 void *pBufferContext)
119 if(This == &vcb1){
120 ok(!xaudio27 || pass_state == 5, "Callbacks called out of order: %u\n", pass_state);
121 ++pass_state;
122 }else{
123 ok(!xaudio27 || pass_state == 2, "Callbacks called out of order: %u\n", pass_state);
124 ++pass_state;
125 buffers_called = TRUE;
129 static void WINAPI VCB_OnBufferEnd(IXAudio2VoiceCallback *This,
130 void *pBufferContext)
132 if(This == &vcb1){
133 ok(!xaudio27 || pass_state == 5, "Callbacks called out of order: %u\n", pass_state);
134 ++pass_state;
135 }else{
136 ok(!xaudio27 || pass_state == 2, "Callbacks called out of order: %u\n", pass_state);
137 ++pass_state;
138 buffers_called = TRUE;
142 static void WINAPI VCB_OnLoopEnd(IXAudio2VoiceCallback *This,
143 void *pBufferContext)
145 ok(0, "Unexpected OnLoopEnd\n");
148 static void WINAPI VCB_OnVoiceError(IXAudio2VoiceCallback *This,
149 void *pBuffercontext, HRESULT Error)
151 ok(0, "Unexpected OnVoiceError\n");
154 static const IXAudio2VoiceCallbackVtbl vcb_vtbl = {
155 VCB_OnVoiceProcessingPassStart,
156 VCB_OnVoiceProcessingPassEnd,
157 VCB_OnStreamEnd,
158 VCB_OnBufferStart,
159 VCB_OnBufferEnd,
160 VCB_OnLoopEnd,
161 VCB_OnVoiceError
164 static IXAudio2VoiceCallback vcb1 = { &vcb_vtbl };
165 static IXAudio2VoiceCallback vcb2 = { &vcb_vtbl };
167 static void test_simple_streaming(IXAudio2 *xa)
169 HRESULT hr;
170 IXAudio2MasteringVoice *master;
171 IXAudio2SourceVoice *src, *src2;
172 IUnknown *vumeter;
173 WAVEFORMATEX fmt;
174 XAUDIO2_BUFFER buf, buf2;
175 XAUDIO2_VOICE_STATE state;
176 XAUDIO2_EFFECT_DESCRIPTOR effect;
177 XAUDIO2_EFFECT_CHAIN chain;
178 DWORD chmask;
180 memset(&ecb_state, 0, sizeof(ecb_state));
181 memset(&src1_state, 0, sizeof(src1_state));
182 memset(&src2_state, 0, sizeof(src2_state));
184 XA2CALL_0V(StopEngine);
186 /* Tests show in native XA2.8, ECB is called from a mixer thread, but VCBs
187 * may be called from other threads in any order. So we can't rely on any
188 * sequencing between VCB calls.
190 * XA2.7 does all mixing from a single thread, so call sequence can be
191 * tested. */
192 XA2CALL(RegisterForCallbacks, &ecb);
193 ok(hr == S_OK, "RegisterForCallbacks failed: %08x\n", hr);
195 if(xaudio27)
196 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
197 else
198 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
199 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
201 if(!xaudio27){
202 chmask = 0xdeadbeef;
203 IXAudio2MasteringVoice_GetChannelMask(master, &chmask);
204 ok(chmask == (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT), "Got unexpected channel mask: 0x%x\n", chmask);
207 /* create first source voice */
208 fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
209 fmt.nChannels = 2;
210 fmt.nSamplesPerSec = 44100;
211 fmt.wBitsPerSample = 32;
212 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
213 fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
214 fmt.cbSize = 0;
216 XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &vcb1, NULL, NULL);
217 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
219 if(xaudio27){
220 XAUDIO27_VOICE_DETAILS details;
221 IXAudio27SourceVoice_GetVoiceDetails((IXAudio27SourceVoice*)src, &details);
222 ok(details.CreationFlags == 0, "Got wrong flags: 0x%x\n", details.CreationFlags);
223 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
224 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
225 }else{
226 XAUDIO2_VOICE_DETAILS details;
227 IXAudio2SourceVoice_GetVoiceDetails(src, &details);
228 ok(details.CreationFlags == 0, "Got wrong creation flags: 0x%x\n", details.CreationFlags);
229 ok(details.ActiveFlags == 0, "Got wrong active flags: 0x%x\n", details.CreationFlags);
230 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
231 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
234 memset(&buf, 0, sizeof(buf));
235 buf.AudioBytes = 22050 * fmt.nBlockAlign;
236 buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
237 fill_buf((float*)buf.pAudioData, &fmt, 440, 22050);
239 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
240 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
242 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
243 ok(hr == S_OK, "Start failed: %08x\n", hr);
245 /* create second source voice */
246 XA2CALL(CreateSourceVoice, &src2, &fmt, 0, 1.f, &vcb2, NULL, NULL);
247 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
249 if(xaudio27){
250 XAUDIO27_VOICE_DETAILS details;
251 IXAudio27SourceVoice_GetVoiceDetails((IXAudio27SourceVoice*)src2, &details);
252 ok(details.CreationFlags == 0, "Got wrong flags: 0x%x\n", details.CreationFlags);
253 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
254 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
255 }else{
256 XAUDIO2_VOICE_DETAILS details;
257 IXAudio2SourceVoice_GetVoiceDetails(src2, &details);
258 ok(details.CreationFlags == 0, "Got wrong creation flags: 0x%x\n", details.CreationFlags);
259 ok(details.ActiveFlags == 0, "Got wrong active flags: 0x%x\n", details.CreationFlags);
260 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
261 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
264 memset(&buf2, 0, sizeof(buf2));
265 buf2.AudioBytes = 22050 * fmt.nBlockAlign;
266 buf2.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf2.AudioBytes);
267 fill_buf((float*)buf2.pAudioData, &fmt, 220, 22050);
269 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src2, &buf2, NULL);
270 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
272 hr = IXAudio2SourceVoice_Start(src2, 0, XAUDIO2_COMMIT_NOW);
273 ok(hr == S_OK, "Start failed: %08x\n", hr);
275 XA2CALL_0(StartEngine);
276 ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
278 /* hook up volume meter */
279 if(xaudio27){
280 IXAPO *xapo;
282 hr = CoCreateInstance(&CLSID_AudioVolumeMeter27, NULL,
283 CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&vumeter);
284 ok(hr == S_OK, "CoCreateInstance(AudioVolumeMeter) failed: %08x\n", hr);
286 hr = IUnknown_QueryInterface(vumeter, &IID_IXAPO27, (void**)&xapo);
287 ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr);
288 if(SUCCEEDED(hr))
289 IXAPO_Release(xapo);
290 }else{
291 IXAPO *xapo;
293 hr = pCreateAudioVolumeMeter(&vumeter);
294 ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr);
296 hr = IUnknown_QueryInterface(vumeter, &IID_IXAPO, (void**)&xapo);
297 ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr);
298 if(SUCCEEDED(hr))
299 IXAPO_Release(xapo);
302 effect.InitialState = TRUE;
303 effect.OutputChannels = 2;
304 effect.pEffect = vumeter;
306 chain.EffectCount = 1;
307 chain.pEffectDescriptors = &effect;
309 hr = IXAudio2MasteringVoice_SetEffectChain(master, &chain);
310 ok(hr == S_OK, "SetEffectchain failed: %08x\n", hr);
312 IUnknown_Release(vumeter);
314 while(1){
315 if(xaudio27)
316 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
317 else
318 IXAudio2SourceVoice_GetState(src, &state, 0);
319 if(state.SamplesPlayed >= 22050)
320 break;
321 Sleep(100);
324 ok(state.SamplesPlayed == 22050, "Got wrong samples played\n");
326 HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
327 HeapFree(GetProcessHeap(), 0, (void*)buf2.pAudioData);
329 if(xaudio27){
330 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
331 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src2);
332 }else{
333 IXAudio2SourceVoice_DestroyVoice(src);
334 IXAudio2SourceVoice_DestroyVoice(src2);
336 IXAudio2MasteringVoice_DestroyVoice(master);
338 XA2CALL_V(UnregisterForCallbacks, &ecb);
341 static void WINAPI vcb_buf_OnVoiceProcessingPassStart(IXAudio2VoiceCallback *This,
342 UINT32 BytesRequired)
346 static void WINAPI vcb_buf_OnVoiceProcessingPassEnd(IXAudio2VoiceCallback *This)
350 static void WINAPI vcb_buf_OnStreamEnd(IXAudio2VoiceCallback *This)
352 ok(0, "Unexpected OnStreamEnd\n");
355 struct vcb_buf_testdata {
356 int idx;
357 IXAudio2SourceVoice *src;
360 static int obs_calls = 0;
361 static int obe_calls = 0;
363 static void WINAPI vcb_buf_OnBufferStart(IXAudio2VoiceCallback *This,
364 void *pBufferContext)
366 struct vcb_buf_testdata *data = pBufferContext;
367 XAUDIO2_VOICE_STATE state;
369 ok(data->idx == obs_calls, "Buffer callback out of order: %u\n", data->idx);
371 if(xaudio27)
372 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)data->src, &state);
373 else
374 IXAudio2SourceVoice_GetState(data->src, &state, 0);
376 ok(state.BuffersQueued == 5 - obs_calls, "Got wrong number of buffers remaining: %u\n", state.BuffersQueued);
377 ok(state.pCurrentBufferContext == pBufferContext, "Got wrong buffer from GetState\n");
379 ++obs_calls;
382 static void WINAPI vcb_buf_OnBufferEnd(IXAudio2VoiceCallback *This,
383 void *pBufferContext)
385 struct vcb_buf_testdata *data = pBufferContext;
386 XAUDIO2_VOICE_STATE state;
388 ok(data->idx == obe_calls, "Buffer callback out of order: %u\n", data->idx);
390 if(xaudio27)
391 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)data->src, &state);
392 else
393 IXAudio2SourceVoice_GetState(data->src, &state, 0);
395 ok(state.BuffersQueued == 5 - obe_calls - 1, "Got wrong number of buffers remaining: %u\n", state.BuffersQueued);
396 if(state.BuffersQueued == 0)
397 ok(state.pCurrentBufferContext == NULL, "Got wrong buffer from GetState: %p\n", state.pCurrentBufferContext);
398 else
399 ok(state.pCurrentBufferContext == data + 1, "Got wrong buffer from GetState: %p\n", state.pCurrentBufferContext);
401 ++obe_calls;
404 static void WINAPI vcb_buf_OnLoopEnd(IXAudio2VoiceCallback *This,
405 void *pBufferContext)
407 ok(0, "Unexpected OnLoopEnd\n");
410 static void WINAPI vcb_buf_OnVoiceError(IXAudio2VoiceCallback *This,
411 void *pBuffercontext, HRESULT Error)
413 ok(0, "Unexpected OnVoiceError\n");
416 static const IXAudio2VoiceCallbackVtbl vcb_buf_vtbl = {
417 vcb_buf_OnVoiceProcessingPassStart,
418 vcb_buf_OnVoiceProcessingPassEnd,
419 vcb_buf_OnStreamEnd,
420 vcb_buf_OnBufferStart,
421 vcb_buf_OnBufferEnd,
422 vcb_buf_OnLoopEnd,
423 vcb_buf_OnVoiceError
426 static IXAudio2VoiceCallback vcb_buf = { &vcb_buf_vtbl };
428 static int nloopends = 0;
429 static int nstreamends = 0;
431 static void WINAPI loop_buf_OnStreamEnd(IXAudio2VoiceCallback *This)
433 ++nstreamends;
436 static void WINAPI loop_buf_OnBufferStart(IXAudio2VoiceCallback *This,
437 void *pBufferContext)
441 static void WINAPI loop_buf_OnBufferEnd(IXAudio2VoiceCallback *This,
442 void *pBufferContext)
446 static void WINAPI loop_buf_OnLoopEnd(IXAudio2VoiceCallback *This,
447 void *pBufferContext)
449 ++nloopends;
452 static void WINAPI loop_buf_OnVoiceError(IXAudio2VoiceCallback *This,
453 void *pBuffercontext, HRESULT Error)
457 static const IXAudio2VoiceCallbackVtbl loop_buf_vtbl = {
458 vcb_buf_OnVoiceProcessingPassStart,
459 vcb_buf_OnVoiceProcessingPassEnd,
460 loop_buf_OnStreamEnd,
461 loop_buf_OnBufferStart,
462 loop_buf_OnBufferEnd,
463 loop_buf_OnLoopEnd,
464 loop_buf_OnVoiceError
467 static IXAudio2VoiceCallback loop_buf = { &loop_buf_vtbl };
469 static void test_buffer_callbacks(IXAudio2 *xa)
471 HRESULT hr;
472 IXAudio2MasteringVoice *master;
473 IXAudio2SourceVoice *src;
474 WAVEFORMATEX fmt;
475 XAUDIO2_BUFFER buf;
476 XAUDIO2_VOICE_STATE state;
477 struct vcb_buf_testdata testdata[5];
478 int i, timeout;
480 obs_calls = 0;
481 obe_calls = 0;
483 XA2CALL_0V(StopEngine);
485 if(xaudio27)
486 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
487 else
488 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
489 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
491 /* test OnBufferStart/End callbacks */
492 fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
493 fmt.nChannels = 2;
494 fmt.nSamplesPerSec = 44100;
495 fmt.wBitsPerSample = 32;
496 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
497 fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
498 fmt.cbSize = 0;
500 XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &vcb_buf, NULL, NULL);
501 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
503 memset(&buf, 0, sizeof(buf));
504 buf.AudioBytes = 4410 * fmt.nBlockAlign;
505 buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
506 fill_buf((float*)buf.pAudioData, &fmt, 440, 4410);
508 /* submit same buffer fragment 5 times */
509 for(i = 0; i < 5; ++i){
510 testdata[i].idx = i;
511 testdata[i].src = src;
512 buf.pContext = &testdata[i];
514 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
515 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
518 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
519 ok(hr == S_OK, "Start failed: %08x\n", hr);
522 XA2CALL_0(StartEngine);
523 ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
525 if(xaudio27){
526 hr = IXAudio27SourceVoice_SetSourceSampleRate((IXAudio27SourceVoice*)src, 48000);
527 ok(hr == S_OK, "SetSourceSampleRate failed: %08x\n", hr);
528 }else{
529 hr = IXAudio2SourceVoice_SetSourceSampleRate(src, 48000);
530 ok(hr == XAUDIO2_E_INVALID_CALL, "SetSourceSampleRate should have failed: %08x\n", hr);
533 while(1){
534 if(xaudio27)
535 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
536 else
537 IXAudio2SourceVoice_GetState(src, &state, 0);
538 if(state.SamplesPlayed >= 4410 * 5)
539 break;
540 Sleep(100);
543 ok(state.SamplesPlayed == 4410 * 5, "Got wrong samples played\n");
545 if(xaudio27)
546 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
547 else
548 IXAudio2SourceVoice_DestroyVoice(src);
551 /* test OnStreamEnd callback */
552 XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &loop_buf, NULL, NULL);
553 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
555 buf.Flags = XAUDIO2_END_OF_STREAM;
557 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
558 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
560 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
561 ok(hr == S_OK, "Start failed: %08x\n", hr);
563 timeout = 0;
564 while(nstreamends == 0 && timeout < 1000){
565 Sleep(100);
566 timeout += 100;
569 ok(nstreamends == 1, "Got wrong number of OnStreamEnd calls: %u\n", nstreamends);
571 /* xaudio resets SamplesPlayed after processing an end-of-stream buffer */
572 if(xaudio27)
573 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
574 else
575 IXAudio2SourceVoice_GetState(src, &state, 0);
576 ok(state.SamplesPlayed == 0, "Got wrong samples played\n");
578 if(xaudio27)
579 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
580 else
581 IXAudio2SourceVoice_DestroyVoice(src);
584 IXAudio2MasteringVoice_DestroyVoice(master);
586 HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
589 static UINT32 play_to_completion(IXAudio2SourceVoice *src, UINT32 max_samples)
591 XAUDIO2_VOICE_STATE state;
592 HRESULT hr;
594 nloopends = 0;
596 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
597 ok(hr == S_OK, "Start failed: %08x\n", hr);
599 while(1){
600 if(xaudio27)
601 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
602 else
603 IXAudio2SourceVoice_GetState(src, &state, 0);
604 if(state.BuffersQueued == 0)
605 break;
606 if(state.SamplesPlayed >= max_samples){
607 if(xaudio27)
608 IXAudio27SourceVoice_ExitLoop((IXAudio27SourceVoice*)src, XAUDIO2_COMMIT_NOW);
609 else
610 IXAudio2SourceVoice_ExitLoop(src, XAUDIO2_COMMIT_NOW);
612 Sleep(100);
615 hr = IXAudio2SourceVoice_Stop(src, 0, XAUDIO2_COMMIT_NOW);
616 ok(hr == S_OK, "Start failed: %08x\n", hr);
618 return state.SamplesPlayed;
621 static void test_looping(IXAudio2 *xa)
623 HRESULT hr;
624 IXAudio2MasteringVoice *master;
625 IXAudio2SourceVoice *src;
626 WAVEFORMATEX fmt;
627 XAUDIO2_BUFFER buf;
628 UINT32 played, running_total = 0;
630 XA2CALL_0V(StopEngine);
632 if(xaudio27)
633 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
634 else
635 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
636 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
639 fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
640 fmt.nChannels = 2;
641 fmt.nSamplesPerSec = 44100;
642 fmt.wBitsPerSample = 32;
643 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
644 fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
645 fmt.cbSize = 0;
647 XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, &loop_buf, NULL, NULL);
648 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
650 memset(&buf, 0, sizeof(buf));
652 buf.AudioBytes = 44100 * fmt.nBlockAlign;
653 buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
654 fill_buf((float*)buf.pAudioData, &fmt, 440, 44100);
656 XA2CALL_0(StartEngine);
657 ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
659 /* play from middle to end */
660 buf.PlayBegin = 22050;
661 buf.PlayLength = 0;
662 buf.LoopBegin = 0;
663 buf.LoopLength = 0;
664 buf.LoopCount = 0;
666 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
667 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
669 played = play_to_completion(src, -1);
670 ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total);
671 running_total = played;
672 ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
674 /* play 4410 samples from middle */
675 buf.PlayBegin = 22050;
676 buf.PlayLength = 4410;
677 buf.LoopBegin = 0;
678 buf.LoopLength = 0;
679 buf.LoopCount = 0;
681 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
682 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
684 played = play_to_completion(src, -1);
685 ok(played - running_total == 4410, "Got wrong samples played: %u\n", played - running_total);
686 running_total = played;
687 ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
689 /* loop 4410 samples in middle */
690 buf.PlayBegin = 0;
691 buf.PlayLength = 0;
692 buf.LoopBegin = 22050;
693 buf.LoopLength = 4410;
694 buf.LoopCount = 1;
696 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
697 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
699 played = play_to_completion(src, -1);
700 ok(played - running_total == 44100 + 4410, "Got wrong samples played: %u\n", played - running_total);
701 running_total = played;
702 ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
704 /* play last half, then loop the whole buffer */
705 buf.PlayBegin = 22050;
706 buf.PlayLength = 0;
707 buf.LoopBegin = 0;
708 buf.LoopLength = 0;
709 buf.LoopCount = 1;
711 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
712 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
714 played = play_to_completion(src, -1);
715 ok(played - running_total == 22050 + 44100, "Got wrong samples played: %u\n", played - running_total);
716 running_total = played;
717 ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
719 /* play short segment from middle, loop to the beginning, and end at PlayEnd */
720 buf.PlayBegin = 22050;
721 buf.PlayLength = 4410;
722 buf.LoopBegin = 0;
723 buf.LoopLength = 0;
724 buf.LoopCount = 1;
726 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
727 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
729 played = play_to_completion(src, -1);
730 ok(played - running_total == 4410 + (22050 + 4410), "Got wrong samples played: %u\n", played - running_total);
731 running_total = played;
732 ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
734 /* invalid: LoopEnd must be <= PlayEnd
735 * xaudio27: play until LoopEnd, loop to beginning, play until PlayEnd */
736 buf.PlayBegin = 22050;
737 buf.PlayLength = 4410;
738 buf.LoopBegin = 0;
739 buf.LoopLength = 22050 + 4410 * 2;
740 buf.LoopCount = 1;
742 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
743 if(xaudio27){
744 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
746 played = play_to_completion(src, -1);
747 ok(played - running_total == 4410 + (22050 + 4410 * 2), "Got wrong samples played: %u\n", played - running_total);
748 running_total = played;
749 ok(nloopends == 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
750 }else
751 ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
753 /* invalid: LoopEnd must be within play range
754 * xaudio27: plays only play range */
755 buf.PlayBegin = 22050;
756 buf.PlayLength = 0; /* == until end of buffer */
757 buf.LoopBegin = 0;
758 buf.LoopLength = 22050;
759 buf.LoopCount = 1;
761 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
762 if(xaudio27){
763 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
765 played = play_to_completion(src, -1);
766 ok(played - running_total == 22050, "Got wrong samples played: %u\n", played - running_total);
767 running_total = played;
768 ok(nloopends == 0, "Got wrong OnLoopEnd calls: %u\n", nloopends);
769 }else
770 ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
772 /* invalid: LoopBegin must be before PlayEnd
773 * xaudio27: crashes */
774 if(!xaudio27){
775 buf.PlayBegin = 0;
776 buf.PlayLength = 4410;
777 buf.LoopBegin = 22050;
778 buf.LoopLength = 4410;
779 buf.LoopCount = 1;
781 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
782 ok(hr == XAUDIO2_E_INVALID_CALL, "SubmitSourceBuffer should have failed: %08x\n", hr);
785 /* infinite looping buffer */
786 buf.PlayBegin = 22050;
787 buf.PlayLength = 0;
788 buf.LoopBegin = 0;
789 buf.LoopLength = 0;
790 buf.LoopCount = 255;
792 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
793 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
795 played = play_to_completion(src, running_total + 88200);
796 ok(played - running_total == 22050 + 44100 * 2, "Got wrong samples played: %u\n", played - running_total);
797 ok(nloopends == (played - running_total) / 88200 + 1, "Got wrong OnLoopEnd calls: %u\n", nloopends);
798 running_total = played;
800 if(xaudio27)
801 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
802 else
803 IXAudio2SourceVoice_DestroyVoice(src);
804 IXAudio2MasteringVoice_DestroyVoice(master);
805 HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
808 static void test_submix(IXAudio2 *xa)
810 HRESULT hr;
811 IXAudio2MasteringVoice *master;
812 IXAudio2SubmixVoice *sub;
814 XA2CALL_0V(StopEngine);
816 if(xaudio27)
817 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
818 else
819 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
820 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
822 XA2CALL(CreateSubmixVoice, &sub, 2, 44100, 0, 0, NULL, NULL);
823 ok(hr == S_OK, "CreateSubmixVoice failed: %08x\n", hr);
825 if(xaudio27){
826 XAUDIO27_VOICE_DETAILS details;
827 IXAudio27SubmixVoice_GetVoiceDetails((IXAudio27SubmixVoice*)sub, &details);
828 ok(details.CreationFlags == 0, "Got wrong flags: 0x%x\n", details.CreationFlags);
829 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
830 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
831 }else{
832 XAUDIO2_VOICE_DETAILS details;
833 IXAudio2SubmixVoice_GetVoiceDetails(sub, &details);
834 ok(details.CreationFlags == 0, "Got wrong creation flags: 0x%x\n", details.CreationFlags);
835 ok(details.ActiveFlags == 0, "Got wrong active flags: 0x%x\n", details.CreationFlags);
836 ok(details.InputChannels == 2, "Got wrong channel count: 0x%x\n", details.InputChannels);
837 ok(details.InputSampleRate == 44100, "Got wrong sample rate: 0x%x\n", details.InputSampleRate);
840 IXAudio2SubmixVoice_DestroyVoice(sub);
841 IXAudio2MasteringVoice_DestroyVoice(master);
844 static void test_flush(IXAudio2 *xa)
846 HRESULT hr;
847 IXAudio2MasteringVoice *master;
848 IXAudio2SourceVoice *src;
849 WAVEFORMATEX fmt;
850 XAUDIO2_BUFFER buf;
851 XAUDIO2_VOICE_STATE state;
853 XA2CALL_0V(StopEngine);
855 if(xaudio27)
856 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 2, 44100, 0, 0, NULL);
857 else
858 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
859 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
861 fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
862 fmt.nChannels = 2;
863 fmt.nSamplesPerSec = 44100;
864 fmt.wBitsPerSample = 32;
865 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
866 fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
867 fmt.cbSize = 0;
869 XA2CALL(CreateSourceVoice, &src, &fmt, 0, 1.f, NULL, NULL, NULL);
870 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
872 memset(&buf, 0, sizeof(buf));
873 buf.AudioBytes = 22050 * fmt.nBlockAlign;
874 buf.pAudioData = HeapAlloc(GetProcessHeap(), 0, buf.AudioBytes);
875 fill_buf((float*)buf.pAudioData, &fmt, 440, 22050);
877 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
878 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
880 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
881 ok(hr == S_OK, "Start failed: %08x\n", hr);
883 XA2CALL_0(StartEngine);
884 ok(hr == S_OK, "StartEngine failed: %08x\n", hr);
886 while(1){
887 if(xaudio27)
888 IXAudio27SourceVoice_GetState((IXAudio27SourceVoice*)src, &state);
889 else
890 IXAudio2SourceVoice_GetState(src, &state, 0);
891 if(state.SamplesPlayed >= 2205)
892 break;
893 Sleep(10);
896 hr = IXAudio2SourceVoice_Stop(src, 0, XAUDIO2_COMMIT_NOW);
897 ok(hr == S_OK, "Stop failed: %08x\n", hr);
899 hr = IXAudio2SourceVoice_FlushSourceBuffers(src);
900 ok(hr == S_OK, "FlushSourceBuffers failed: %08x\n", hr);
902 hr = IXAudio2SourceVoice_Start(src, 0, XAUDIO2_COMMIT_NOW);
903 ok(hr == S_OK, "Start failed: %08x\n", hr);
905 Sleep(100);
907 hr = IXAudio2SourceVoice_SubmitSourceBuffer(src, &buf, NULL);
908 ok(hr == S_OK, "SubmitSourceBuffer failed: %08x\n", hr);
910 if(xaudio27){
911 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src);
912 }else{
913 IXAudio2SourceVoice_DestroyVoice(src);
915 IXAudio2MasteringVoice_DestroyVoice(master);
917 HeapFree(GetProcessHeap(), 0, (void*)buf.pAudioData);
920 static UINT32 test_DeviceDetails(IXAudio27 *xa)
922 HRESULT hr;
923 XAUDIO2_DEVICE_DETAILS dd;
924 UINT32 count, i;
926 hr = IXAudio27_GetDeviceCount(xa, &count);
927 ok(hr == S_OK, "GetDeviceCount failed: %08x\n", hr);
929 if(count == 0)
930 return 0;
932 for(i = 0; i < count; ++i){
933 hr = IXAudio27_GetDeviceDetails(xa, i, &dd);
934 ok(hr == S_OK, "GetDeviceDetails failed: %08x\n", hr);
936 if(i == 0)
937 ok(dd.Role == GlobalDefaultDevice, "Got wrong role for index 0: 0x%x\n", dd.Role);
938 else
939 ok(dd.Role == NotDefaultDevice, "Got wrong role for index %u: 0x%x\n", i, dd.Role);
942 return count;
945 static void test_xapo_creation_legacy(const char *module, unsigned int version)
947 HANDLE xapofxdll;
948 HRESULT hr;
949 IUnknown *fx_unk;
950 unsigned int i;
951 ULONG rc;
953 HRESULT (CDECL *pCreateFX)(REFCLSID,IUnknown**) = NULL;
955 /* CLSIDs are the same across all versions */
956 static const GUID *const_clsids[] = {
957 &CLSID_FXEQ27,
958 &CLSID_FXMasteringLimiter27,
959 &CLSID_FXReverb27,
960 &CLSID_FXEcho27,
961 /* older versions of xapofx actually have support for new clsids */
962 &CLSID_FXEQ,
963 &CLSID_FXMasteringLimiter,
964 &CLSID_FXReverb,
965 &CLSID_FXEcho
968 /* different CLSID for each version */
969 static const GUID *avm_clsids[] = {
970 &CLSID_AudioVolumeMeter20,
971 &CLSID_AudioVolumeMeter21,
972 &CLSID_AudioVolumeMeter22,
973 &CLSID_AudioVolumeMeter23,
974 &CLSID_AudioVolumeMeter24,
975 &CLSID_AudioVolumeMeter25,
976 &CLSID_AudioVolumeMeter26,
977 &CLSID_AudioVolumeMeter27
980 static const GUID *ar_clsids[] = {
981 &CLSID_AudioReverb20,
982 &CLSID_AudioReverb21,
983 &CLSID_AudioReverb22,
984 &CLSID_AudioReverb23,
985 &CLSID_AudioReverb24,
986 &CLSID_AudioReverb25,
987 &CLSID_AudioReverb26,
988 &CLSID_AudioReverb27
991 xapofxdll = LoadLibraryA(module);
992 if(xapofxdll){
993 pCreateFX = (void*)GetProcAddress(xapofxdll, "CreateFX");
994 ok(pCreateFX != NULL, "%s did not have CreateFX?\n", module);
995 if(!pCreateFX){
996 FreeLibrary(xapofxdll);
997 return;
999 }else{
1000 win_skip("Couldn't load %s\n", module);
1001 return;
1004 for(i = 0; i < ARRAY_SIZE(const_clsids); ++i){
1005 hr = pCreateFX(const_clsids[i], &fx_unk);
1006 ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i]), hr);
1007 if(SUCCEEDED(hr)){
1008 IXAPO *xapo;
1009 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo);
1010 ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr);
1011 if(SUCCEEDED(hr))
1012 IXAPO_Release(xapo);
1013 rc = IUnknown_Release(fx_unk);
1014 ok(rc == 0, "XAPO via CreateFX should have been released, got refcount: %u\n", rc);
1017 hr = CoCreateInstance(const_clsids[i], NULL, CLSCTX_INPROC_SERVER,
1018 &IID_IUnknown, (void**)&fx_unk);
1019 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed: %08x\n", hr);
1020 if(SUCCEEDED(hr))
1021 IUnknown_Release(fx_unk);
1024 hr = pCreateFX(avm_clsids[version - 20], &fx_unk);
1025 ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(avm_clsids[version - 20]), hr);
1026 if(SUCCEEDED(hr)){
1027 IXAPO *xapo;
1028 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo);
1029 ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr);
1030 if(SUCCEEDED(hr))
1031 IXAPO_Release(xapo);
1032 rc = IUnknown_Release(fx_unk);
1033 ok(rc == 0, "AudioVolumeMeter via CreateFX should have been released, got refcount: %u\n", rc);
1036 hr = pCreateFX(ar_clsids[version - 20], &fx_unk);
1037 ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(ar_clsids[version - 20]), hr);
1038 if(SUCCEEDED(hr)){
1039 IXAPO *xapo;
1040 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO27, (void**)&xapo);
1041 ok(hr == S_OK, "Couldn't get IXAPO27 interface: %08x\n", hr);
1042 if(SUCCEEDED(hr))
1043 IXAPO_Release(xapo);
1044 rc = IUnknown_Release(fx_unk);
1045 ok(rc == 0, "AudioReverb via CreateFX should have been released, got refcount: %u\n", rc);
1048 FreeLibrary(xapofxdll);
1051 static void test_xapo_creation_modern(const char *module)
1053 HANDLE xaudio2dll;
1054 HRESULT hr;
1055 IUnknown *fx_unk;
1056 unsigned int i;
1057 ULONG rc;
1059 HRESULT (CDECL *pCreateFX)(REFCLSID,IUnknown**,void*,UINT32) = NULL;
1060 HRESULT (WINAPI *pCAVM)(IUnknown**) = NULL;
1061 HRESULT (WINAPI *pCAR)(IUnknown**) = NULL;
1063 /* CLSIDs are the same across all versions */
1064 static const GUID *const_clsids[] = {
1065 &CLSID_FXEQ27,
1066 &CLSID_FXMasteringLimiter27,
1067 &CLSID_FXReverb27,
1068 &CLSID_FXEcho27,
1069 &CLSID_FXEQ,
1070 &CLSID_FXMasteringLimiter,
1071 &CLSID_FXReverb,
1072 &CLSID_FXEcho
1076 xaudio2dll = LoadLibraryA(module);
1077 if(xaudio2dll){
1078 pCreateFX = (void*)GetProcAddress(xaudio2dll, "CreateFX");
1079 ok(pCreateFX != NULL, "%s did not have CreateFX?\n", module);
1080 if(!pCreateFX){
1081 FreeLibrary(xaudio2dll);
1082 return;
1084 }else{
1085 win_skip("Couldn't load %s\n", module);
1086 return;
1089 for(i = 0; i < ARRAY_SIZE(const_clsids); ++i){
1090 hr = pCreateFX(const_clsids[i], &fx_unk, NULL, 0);
1091 ok(hr == S_OK, "%s: CreateFX(%s) failed: %08x\n", module, wine_dbgstr_guid(const_clsids[i]), hr);
1092 if(SUCCEEDED(hr)){
1093 IXAPO *xapo;
1094 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo);
1095 ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr);
1096 if(SUCCEEDED(hr))
1097 IXAPO_Release(xapo);
1098 rc = IUnknown_Release(fx_unk);
1099 ok(rc == 0, "XAPO via CreateFX should have been released, got refcount: %u\n", rc);
1102 hr = CoCreateInstance(const_clsids[i], NULL, CLSCTX_INPROC_SERVER,
1103 &IID_IUnknown, (void**)&fx_unk);
1104 ok(hr == REGDB_E_CLASSNOTREG, "CoCreateInstance should have failed: %08x\n", hr);
1105 if(SUCCEEDED(hr))
1106 IUnknown_Release(fx_unk);
1109 /* test legacy CLSID */
1110 hr = pCreateFX(&CLSID_AudioVolumeMeter27, &fx_unk, NULL, 0);
1111 ok(hr == S_OK, "%s: CreateFX(CLSID_AudioVolumeMeter) failed: %08x\n", module, hr);
1112 if(SUCCEEDED(hr)){
1113 IXAPO *xapo;
1114 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo);
1115 ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr);
1116 if(SUCCEEDED(hr))
1117 IXAPO_Release(xapo);
1118 rc = IUnknown_Release(fx_unk);
1119 ok(rc == 0, "XAPO via legacy CreateFX should have been released, got refcount: %u\n", rc);
1122 pCAVM = (void*)GetProcAddress(xaudio2dll, "CreateAudioVolumeMeter");
1123 ok(pCAVM != NULL, "%s did not have CreateAudioVolumeMeter?\n", module);
1125 hr = pCAVM(&fx_unk);
1126 ok(hr == S_OK, "CreateAudioVolumeMeter failed: %08x\n", hr);
1127 if(SUCCEEDED(hr)){
1128 IXAPO *xapo;
1129 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo);
1130 ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr);
1131 if(SUCCEEDED(hr))
1132 IXAPO_Release(xapo);
1133 rc = IUnknown_Release(fx_unk);
1134 ok(rc == 0, "XAPO via CreateAudioVolumeMeter should have been released, got refcount: %u\n", rc);
1137 pCAR = (void*)GetProcAddress(xaudio2dll, "CreateAudioReverb");
1138 ok(pCAR != NULL, "%s did not have CreateAudioReverb?\n", module);
1140 hr = pCAR(&fx_unk);
1141 ok(hr == S_OK, "CreateAudioReverb failed: %08x\n", hr);
1142 if(SUCCEEDED(hr)){
1143 IXAPO *xapo;
1144 hr = IUnknown_QueryInterface(fx_unk, &IID_IXAPO, (void**)&xapo);
1145 ok(hr == S_OK, "Couldn't get IXAPO interface: %08x\n", hr);
1146 if(SUCCEEDED(hr))
1147 IXAPO_Release(xapo);
1148 rc = IUnknown_Release(fx_unk);
1149 ok(rc == 0, "XAPO via CreateAudioReverb should have been released, got refcount: %u\n", rc);
1152 FreeLibrary(xaudio2dll);
1155 static void test_xapo_creation(void)
1157 test_xapo_creation_legacy("xapofx1_1.dll", 22);
1158 test_xapo_creation_legacy("xapofx1_2.dll", 23);
1159 test_xapo_creation_legacy("xapofx1_3.dll", 24);
1160 test_xapo_creation_legacy("xapofx1_3.dll", 25);
1161 test_xapo_creation_legacy("xapofx1_4.dll", 26);
1162 test_xapo_creation_legacy("xapofx1_5.dll", 27);
1163 test_xapo_creation_modern("xaudio2_8.dll");
1166 static void test_setchannelvolumes(IXAudio2 *xa)
1168 HRESULT hr;
1169 IXAudio2MasteringVoice *master;
1170 IXAudio2SourceVoice *src_2ch, *src_8ch;
1171 WAVEFORMATEX fmt_2ch, fmt_8ch;
1172 float volumes[] = {0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f};
1174 if(xaudio27)
1175 hr = IXAudio27_CreateMasteringVoice((IXAudio27*)xa, &master, 8, 44100, 0, 0, NULL);
1176 else
1177 hr = IXAudio2_CreateMasteringVoice(xa, &master, 8, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
1178 ok(hr == S_OK, "CreateMasteringVoice failed: %08x\n", hr);
1180 fmt_2ch.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
1181 fmt_2ch.nChannels = 2;
1182 fmt_2ch.nSamplesPerSec = 44100;
1183 fmt_2ch.wBitsPerSample = 32;
1184 fmt_2ch.nBlockAlign = fmt_2ch.nChannels * fmt_2ch.wBitsPerSample / 8;
1185 fmt_2ch.nAvgBytesPerSec = fmt_2ch.nSamplesPerSec * fmt_2ch.nBlockAlign;
1186 fmt_2ch.cbSize = 0;
1188 fmt_8ch.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
1189 fmt_8ch.nChannels = 8;
1190 fmt_8ch.nSamplesPerSec = 44100;
1191 fmt_8ch.wBitsPerSample = 32;
1192 fmt_8ch.nBlockAlign = fmt_8ch.nChannels * fmt_8ch.wBitsPerSample / 8;
1193 fmt_8ch.nAvgBytesPerSec = fmt_8ch.nSamplesPerSec * fmt_8ch.nBlockAlign;
1194 fmt_8ch.cbSize = 0;
1196 XA2CALL(CreateSourceVoice, &src_2ch, &fmt_2ch, 0, 1.f, NULL, NULL, NULL);
1197 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
1199 XA2CALL(CreateSourceVoice, &src_8ch, &fmt_8ch, 0, 1.f, NULL, NULL, NULL);
1200 ok(hr == S_OK, "CreateSourceVoice failed: %08x\n", hr);
1202 hr = IXAudio2SourceVoice_SetChannelVolumes(src_2ch, 2, volumes, XAUDIO2_COMMIT_NOW);
1203 ok(hr == S_OK, "SetChannelVolumes failed: %08x\n", hr);
1205 hr = IXAudio2SourceVoice_SetChannelVolumes(src_8ch, 8, volumes, XAUDIO2_COMMIT_NOW);
1206 ok(hr == S_OK, "SetChannelVolumes failed: %08x\n", hr);
1208 if(xaudio27){
1209 /* XAudio 2.7 doesn't check the number of channels */
1210 hr = IXAudio2SourceVoice_SetChannelVolumes(src_8ch, 2, volumes, XAUDIO2_COMMIT_NOW);
1211 ok(hr == S_OK, "SetChannelVolumes failed: %08x\n", hr);
1212 }else{
1213 /* the number of channels must be the same as the number of channels on the source voice */
1214 hr = IXAudio2SourceVoice_SetChannelVolumes(src_8ch, 2, volumes, XAUDIO2_COMMIT_NOW);
1215 ok(hr == XAUDIO2_E_INVALID_CALL, "SetChannelVolumes should have failed: %08x\n", hr);
1217 hr = IXAudio2SourceVoice_SetChannelVolumes(src_2ch, 8, volumes, XAUDIO2_COMMIT_NOW);
1218 ok(hr == XAUDIO2_E_INVALID_CALL, "SetChannelVolumes should have failed: %08x\n", hr);
1220 /* volumes must not be NULL, XAudio 2.7 doesn't check this */
1221 hr = IXAudio2SourceVoice_SetChannelVolumes(src_2ch, 2, NULL, XAUDIO2_COMMIT_NOW);
1222 ok(hr == XAUDIO2_E_INVALID_CALL, "SetChannelVolumes should have failed: %08x\n", hr);
1225 if(xaudio27){
1226 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src_2ch);
1227 IXAudio27SourceVoice_DestroyVoice((IXAudio27SourceVoice*)src_8ch);
1228 }else{
1229 IXAudio2SourceVoice_DestroyVoice(src_2ch);
1230 IXAudio2SourceVoice_DestroyVoice(src_8ch);
1233 IXAudio2MasteringVoice_DestroyVoice(master);
1236 static UINT32 check_has_devices(IXAudio2 *xa)
1238 HRESULT hr;
1239 IXAudio2MasteringVoice *master;
1241 hr = IXAudio2_CreateMasteringVoice(xa, &master, 2, 44100, 0, NULL, NULL, AudioCategory_GameEffects);
1242 if(hr != S_OK)
1243 return 0;
1245 IXAudio2MasteringVoice_DestroyVoice(master);
1247 return 1;
1250 START_TEST(xaudio2)
1252 HRESULT hr;
1253 IXAudio27 *xa27 = NULL;
1254 IXAudio2 *xa = NULL;
1255 HANDLE xa28dll;
1256 UINT32 has_devices;
1257 ULONG rc;
1259 CoInitialize(NULL);
1261 xa28dll = LoadLibraryA("xaudio2_8.dll");
1262 if(xa28dll){
1263 pXAudio2Create = (void*)GetProcAddress(xa28dll, "XAudio2Create");
1264 pCreateAudioVolumeMeter = (void*)GetProcAddress(xa28dll, "CreateAudioVolumeMeter");
1267 test_xapo_creation();
1269 /* XAudio 2.7 (Jun 2010 DirectX) */
1270 hr = CoCreateInstance(&CLSID_XAudio27, NULL, CLSCTX_INPROC_SERVER,
1271 &IID_IXAudio27, (void**)&xa27);
1272 if(hr == S_OK){
1273 xaudio27 = TRUE;
1275 hr = IXAudio27_QueryInterface(xa27, &IID_IXAudio28, (void**) &xa);
1276 ok(hr != S_OK, "QueryInterface with IID_IXAudio28 on IXAudio27 object returned success. Expected to fail\n");
1278 hr = IXAudio27_Initialize(xa27, 0, XAUDIO2_ANY_PROCESSOR);
1279 ok(hr == S_OK, "Initialize failed: %08x\n", hr);
1281 has_devices = test_DeviceDetails(xa27);
1282 if(has_devices){
1283 test_simple_streaming((IXAudio2*)xa27);
1284 test_buffer_callbacks((IXAudio2*)xa27);
1285 test_looping((IXAudio2*)xa27);
1286 test_submix((IXAudio2*)xa27);
1287 test_flush((IXAudio2*)xa27);
1288 test_setchannelvolumes((IXAudio2*)xa27);
1289 }else
1290 skip("No audio devices available\n");
1292 rc = IXAudio27_Release(xa27);
1293 ok(rc == 0, "IXAudio2.7 object should have been released, got refcount %u\n", rc);
1294 }else
1295 win_skip("XAudio 2.7 not available\n");
1297 /* XAudio 2.8 (Win8+) */
1298 if(pXAudio2Create){
1299 xaudio27 = FALSE;
1301 hr = pXAudio2Create(&xa, 0, XAUDIO2_DEFAULT_PROCESSOR);
1302 ok(hr == S_OK, "XAudio2Create failed: %08x\n", hr);
1304 hr = IXAudio2_QueryInterface(xa, &IID_IXAudio27, (void**)&xa27);
1305 ok(hr == E_NOINTERFACE, "XA28 object should support IXAudio27, gave: %08x\n", hr);
1307 has_devices = check_has_devices(xa);
1308 if(has_devices){
1309 test_simple_streaming(xa);
1310 test_buffer_callbacks(xa);
1311 test_looping(xa);
1312 test_submix(xa);
1313 test_flush(xa);
1314 test_setchannelvolumes(xa);
1315 }else
1316 skip("No audio devices available\n");
1318 rc = IXAudio2_Release(xa);
1319 ok(rc == 0, "IXAudio2 object should have been released, got refcount %u\n", rc);
1320 }else
1321 win_skip("XAudio 2.8 not available\n");
1323 CoUninitialize();