sapi: Add SpMMAudioOut stub.
[wine.git] / dlls / xaudio2_7 / xaudio_dll.c
blob5730e0b881152e8eb9896f05078924e4828e544b
1 /*
2 * Copyright (c) 2015 Mark Harmstone
3 * Copyright (c) 2015 Andrew Eikum for CodeWeavers
4 * Copyright (c) 2018 Ethan Lee for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define NONAMELESSUNION
24 #define COBJMACROS
26 #include "windows.h"
27 #include "objbase.h"
28 #include "mmdeviceapi.h"
30 #include "initguid.h"
31 #include "xaudio_private.h"
32 #include "xaudio2fx.h"
33 #if XAUDIO2_VER >= 8
34 #include "xapofx.h"
35 #endif
37 #include "wine/asm.h"
38 #include "wine/debug.h"
39 #include "wine/heap.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
43 #if XAUDIO2_VER != 0 && defined(__i386__)
44 /* EVE Online uses an OnVoiceProcessingPassStart callback which corrupts %esi;
45 * League of Legends uses a callback which corrupts %ebx. */
46 #define IXAudio2VoiceCallback_OnVoiceProcessingPassStart(a, b) call_on_voice_processing_pass_start(a, b)
47 extern void call_on_voice_processing_pass_start(IXAudio2VoiceCallback *This, UINT32 BytesRequired);
48 __ASM_GLOBAL_FUNC( call_on_voice_processing_pass_start,
49 "pushl %ebp\n\t"
50 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
51 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
52 "movl %esp,%ebp\n\t"
53 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
54 "pushl %esi\n\t"
55 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
56 "pushl %edi\n\t"
57 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
58 "pushl %ebx\n\t"
59 __ASM_CFI(".cfi_rel_offset %ebx,-12\n\t")
60 "subl $4,%esp\n\t"
61 "pushl 12(%ebp)\n\t" /* BytesRequired */
62 "pushl 8(%ebp)\n\t" /* This */
63 "movl 8(%ebp),%eax\n\t"
64 "movl 0(%eax),%eax\n\t"
65 "call *0(%eax)\n\t" /* This->lpVtbl->OnVoiceProcessingPassStart */
66 "leal -12(%ebp),%esp\n\t"
67 "popl %ebx\n\t"
68 __ASM_CFI(".cfi_same_value %ebx\n\t")
69 "popl %edi\n\t"
70 __ASM_CFI(".cfi_same_value %edi\n\t")
71 "popl %esi\n\t"
72 __ASM_CFI(".cfi_same_value %esi\n\t")
73 "popl %ebp\n\t"
74 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
75 __ASM_CFI(".cfi_same_value %ebp\n\t")
76 "ret" )
77 #endif
79 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface);
81 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved)
83 TRACE("(%p, %ld, %p)\n", hinstDLL, reason, pReserved);
85 switch (reason)
87 case DLL_PROCESS_ATTACH:
88 DisableThreadLibraryCalls( hinstDLL );
89 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
90 break;
92 return TRUE;
95 /* Effect Wrapping */
97 static inline XA2XAPOImpl *impl_from_FAPO(FAPO *iface)
99 return CONTAINING_RECORD(iface, XA2XAPOImpl, FAPO_vtbl);
102 static int32_t FAPOCALL XAPO_AddRef(void *iface)
104 XA2XAPOImpl *This = impl_from_FAPO(iface);
105 TRACE("%p\n", This);
106 return InterlockedIncrement(&This->ref);
109 static int32_t FAPOCALL XAPO_Release(void *iface)
111 int32_t r;
112 XA2XAPOImpl *This = impl_from_FAPO(iface);
113 TRACE("%p\n", This);
114 r = InterlockedDecrement(&This->ref);
115 if(r == 0){
116 IXAPO_Release(This->xapo);
117 if(This->xapo_params)
118 IXAPOParameters_Release(This->xapo_params);
119 heap_free(This);
121 return r;
124 static uint32_t FAPOCALL XAPO_GetRegistrationProperties(void *iface,
125 FAPORegistrationProperties **ppRegistrationProperties)
127 XA2XAPOImpl *This = impl_from_FAPO(iface);
128 XAPO_REGISTRATION_PROPERTIES *xprops;
129 HRESULT hr;
131 TRACE("%p\n", This);
133 hr = IXAPO_GetRegistrationProperties(This->xapo, &xprops);
134 if(FAILED(hr))
135 return hr;
137 /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
138 *ppRegistrationProperties = (FAPORegistrationProperties*) xprops;
139 return 0;
142 static uint32_t FAPOCALL XAPO_IsInputFormatSupported(void *iface,
143 const FAudioWaveFormatEx *pOutputFormat, const FAudioWaveFormatEx *pRequestedInputFormat,
144 FAudioWaveFormatEx **ppSupportedInputFormat)
146 XA2XAPOImpl *This = impl_from_FAPO(iface);
147 TRACE("%p\n", This);
148 return IXAPO_IsInputFormatSupported(This->xapo, (const WAVEFORMATEX*)pOutputFormat,
149 (const WAVEFORMATEX*)pRequestedInputFormat, (WAVEFORMATEX**)ppSupportedInputFormat);
152 static uint32_t FAPOCALL XAPO_IsOutputFormatSupported(void *iface,
153 const FAudioWaveFormatEx *pInputFormat, const FAudioWaveFormatEx *pRequestedOutputFormat,
154 FAudioWaveFormatEx **ppSupportedOutputFormat)
156 XA2XAPOImpl *This = impl_from_FAPO(iface);
157 TRACE("%p\n", This);
158 return IXAPO_IsOutputFormatSupported(This->xapo, (const WAVEFORMATEX *)pInputFormat,
159 (const WAVEFORMATEX *)pRequestedOutputFormat, (WAVEFORMATEX**)ppSupportedOutputFormat);
162 static uint32_t FAPOCALL XAPO_Initialize(void *iface, const void *pData,
163 uint32_t DataByteSize)
165 XA2XAPOImpl *This = impl_from_FAPO(iface);
166 TRACE("%p\n", This);
167 return IXAPO_Initialize(This->xapo, pData, DataByteSize);
170 static void FAPOCALL XAPO_Reset(void *iface)
172 XA2XAPOImpl *This = impl_from_FAPO(iface);
173 TRACE("%p\n", This);
174 IXAPO_Reset(This->xapo);
177 static uint32_t FAPOCALL XAPO_LockForProcess(void *iface,
178 uint32_t InputLockedParameterCount,
179 const FAPOLockForProcessBufferParameters *pInputLockedParameters,
180 uint32_t OutputLockedParameterCount,
181 const FAPOLockForProcessBufferParameters *pOutputLockedParameters)
183 XA2XAPOImpl *This = impl_from_FAPO(iface);
184 TRACE("%p\n", This);
185 return IXAPO_LockForProcess(This->xapo,
186 InputLockedParameterCount,
187 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pInputLockedParameters,
188 OutputLockedParameterCount,
189 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pOutputLockedParameters);
192 static void FAPOCALL XAPO_UnlockForProcess(void *iface)
194 XA2XAPOImpl *This = impl_from_FAPO(iface);
195 TRACE("%p\n", This);
196 IXAPO_UnlockForProcess(This->xapo);
199 static void FAPOCALL XAPO_Process(void *iface,
200 uint32_t InputProcessParameterCount,
201 const FAPOProcessBufferParameters* pInputProcessParameters,
202 uint32_t OutputProcessParameterCount,
203 FAPOProcessBufferParameters* pOutputProcessParameters,
204 int32_t IsEnabled)
206 XA2XAPOImpl *This = impl_from_FAPO(iface);
207 TRACE("%p\n", This);
208 IXAPO_Process(This->xapo, InputProcessParameterCount,
209 (const XAPO_PROCESS_BUFFER_PARAMETERS *)pInputProcessParameters,
210 OutputProcessParameterCount,
211 (XAPO_PROCESS_BUFFER_PARAMETERS *)pOutputProcessParameters,
212 IsEnabled);
215 static uint32_t FAPOCALL XAPO_CalcInputFrames(void *iface,
216 uint32_t OutputFrameCount)
218 XA2XAPOImpl *This = impl_from_FAPO(iface);
219 TRACE("%p\n", This);
220 return IXAPO_CalcInputFrames(This->xapo, OutputFrameCount);
223 static uint32_t FAPOCALL XAPO_CalcOutputFrames(void *iface,
224 uint32_t InputFrameCount)
226 XA2XAPOImpl *This = impl_from_FAPO(iface);
227 TRACE("%p\n", This);
228 return IXAPO_CalcOutputFrames(This->xapo, InputFrameCount);
231 static void FAPOCALL XAPO_SetParameters(void *iface,
232 const void *pParameters, uint32_t ParametersByteSize)
234 XA2XAPOImpl *This = impl_from_FAPO(iface);
235 TRACE("%p\n", This);
236 if(This->xapo_params)
237 IXAPOParameters_SetParameters(This->xapo_params, pParameters, ParametersByteSize);
240 static void FAPOCALL XAPO_GetParameters(void *iface,
241 void *pParameters, uint32_t ParametersByteSize)
243 XA2XAPOImpl *This = impl_from_FAPO(iface);
244 TRACE("%p\n", This);
245 if(This->xapo_params)
246 IXAPOParameters_GetParameters(This->xapo_params, pParameters, ParametersByteSize);
247 else
248 memset(pParameters, 0, ParametersByteSize);
251 static const FAPO FAPO_Vtbl = {
252 XAPO_AddRef,
253 XAPO_Release,
254 XAPO_GetRegistrationProperties,
255 XAPO_IsInputFormatSupported,
256 XAPO_IsOutputFormatSupported,
257 XAPO_Initialize,
258 XAPO_Reset,
259 XAPO_LockForProcess,
260 XAPO_UnlockForProcess,
261 XAPO_Process,
262 XAPO_CalcInputFrames,
263 XAPO_CalcOutputFrames,
264 XAPO_SetParameters,
265 XAPO_GetParameters,
268 static XA2XAPOImpl *wrap_xapo(IUnknown *unk)
270 XA2XAPOImpl *ret;
271 IXAPO *xapo;
272 IXAPOParameters *xapo_params;
273 HRESULT hr;
275 #if XAUDIO2_VER <= 7
276 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27, (void**)&xapo);
277 #else
278 hr = IUnknown_QueryInterface(unk, &IID_IXAPO, (void**)&xapo);
279 #endif
280 if(FAILED(hr)){
281 WARN("XAPO doesn't support IXAPO? %p\n", unk);
282 return NULL;
285 #if XAUDIO2_VER <= 7
286 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27Parameters, (void**)&xapo_params);
287 #else
288 hr = IUnknown_QueryInterface(unk, &IID_IXAPOParameters, (void**)&xapo_params);
289 #endif
290 if(FAILED(hr)){
291 TRACE("XAPO doesn't support IXAPOParameters %p\n", unk);
292 xapo_params = NULL;
295 ret = heap_alloc(sizeof(*ret));
297 ret->xapo = xapo;
298 ret->xapo_params = xapo_params;
299 ret->FAPO_vtbl = FAPO_Vtbl;
300 ret->ref = 1;
302 TRACE("wrapped IXAPO %p with %p\n", xapo, ret);
304 return ret;
307 FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
309 FAudioEffectChain *ret;
310 int i;
312 if(!pEffectChain)
313 return NULL;
315 ret = heap_alloc(sizeof(*ret) + sizeof(FAudioEffectDescriptor) * pEffectChain->EffectCount);
317 ret->EffectCount = pEffectChain->EffectCount;
318 ret->pEffectDescriptors = (void*)(ret + 1);
320 for(i = 0; i < ret->EffectCount; ++i){
321 ret->pEffectDescriptors[i].pEffect = &wrap_xapo(pEffectChain->pEffectDescriptors[i].pEffect)->FAPO_vtbl;
322 ret->pEffectDescriptors[i].InitialState = pEffectChain->pEffectDescriptors[i].InitialState;
323 ret->pEffectDescriptors[i].OutputChannels = pEffectChain->pEffectDescriptors[i].OutputChannels;
326 return ret;
329 static void free_effect_chain(FAudioEffectChain *chain)
331 int i;
332 if(!chain)
333 return;
334 for(i = 0; i < chain->EffectCount; ++i)
335 XAPO_Release(chain->pEffectDescriptors[i].pEffect);
336 heap_free(chain);
339 /* Send Wrapping */
341 static FAudioVoiceSends *wrap_voice_sends(const XAUDIO2_VOICE_SENDS *sends)
343 FAudioVoiceSends *ret;
344 int i;
346 if(!sends)
347 return NULL;
349 ret = heap_alloc(sizeof(*ret) + sends->SendCount * sizeof(FAudioSendDescriptor));
350 ret->SendCount = sends->SendCount;
351 ret->pSends = (FAudioSendDescriptor*)(ret + 1);
352 for(i = 0; i < sends->SendCount; ++i){
353 XA2VoiceImpl *voice = impl_from_IXAudio2Voice(sends->pSends[i].pOutputVoice);
354 ret->pSends[i].pOutputVoice = voice->faudio_voice;
355 ret->pSends[i].Flags = sends->pSends[i].Flags;
357 return ret;
360 static void free_voice_sends(FAudioVoiceSends *sends)
362 if(!sends)
363 return;
364 heap_free(sends);
367 /* Voice Callbacks */
369 static inline XA2VoiceImpl *impl_from_FAudioVoiceCallback(FAudioVoiceCallback *iface)
371 return CONTAINING_RECORD(iface, XA2VoiceImpl, FAudioVoiceCallback_vtbl);
374 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassStart(FAudioVoiceCallback *iface,
375 UINT32 BytesRequired)
377 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
378 TRACE("%p\n", This);
379 if(This->cb)
380 #if XAUDIO2_VER == 0
381 IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)This->cb);
382 #else
383 IXAudio2VoiceCallback_OnVoiceProcessingPassStart(This->cb, BytesRequired);
384 #endif
387 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassEnd(FAudioVoiceCallback *iface)
389 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
390 TRACE("%p\n", This);
391 if(This->cb)
392 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(This->cb);
395 static void FAUDIOCALL XA2VCB_OnStreamEnd(FAudioVoiceCallback *iface)
397 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
398 TRACE("%p\n", This);
399 if(This->cb)
400 IXAudio2VoiceCallback_OnStreamEnd(This->cb);
403 static void FAUDIOCALL XA2VCB_OnBufferStart(FAudioVoiceCallback *iface,
404 void *pBufferContext)
406 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
407 TRACE("%p\n", This);
408 if(This->cb)
409 IXAudio2VoiceCallback_OnBufferStart(This->cb, pBufferContext);
412 static void FAUDIOCALL XA2VCB_OnBufferEnd(FAudioVoiceCallback *iface,
413 void *pBufferContext)
415 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
416 TRACE("%p\n", This);
417 if(This->cb)
418 IXAudio2VoiceCallback_OnBufferEnd(This->cb, pBufferContext);
421 static void FAUDIOCALL XA2VCB_OnLoopEnd(FAudioVoiceCallback *iface,
422 void *pBufferContext)
424 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
425 TRACE("%p\n", This);
426 if(This->cb)
427 IXAudio2VoiceCallback_OnLoopEnd(This->cb, pBufferContext);
430 static void FAUDIOCALL XA2VCB_OnVoiceError(FAudioVoiceCallback *iface,
431 void *pBufferContext, unsigned int Error)
433 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
434 TRACE("%p\n", This);
435 if(This->cb)
436 IXAudio2VoiceCallback_OnVoiceError(This->cb, pBufferContext, (HRESULT)Error);
439 static const FAudioVoiceCallback FAudioVoiceCallback_Vtbl = {
440 XA2VCB_OnBufferEnd,
441 XA2VCB_OnBufferStart,
442 XA2VCB_OnLoopEnd,
443 XA2VCB_OnStreamEnd,
444 XA2VCB_OnVoiceError,
445 XA2VCB_OnVoiceProcessingPassEnd,
446 XA2VCB_OnVoiceProcessingPassStart
449 /* Engine Callbacks */
451 static inline IXAudio2Impl *impl_from_FAudioEngineCallback(FAudioEngineCallback *iface)
453 return CONTAINING_RECORD(iface, IXAudio2Impl, FAudioEngineCallback_vtbl);
456 static void FAUDIOCALL XA2ECB_OnProcessingPassStart(FAudioEngineCallback *iface)
458 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
459 int i;
460 TRACE("%p\n", This);
461 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
462 IXAudio2EngineCallback_OnProcessingPassStart(This->cbs[i]);
465 static void FAUDIOCALL XA2ECB_OnProcessingPassEnd(FAudioEngineCallback *iface)
467 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
468 int i;
469 TRACE("%p\n", This);
470 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
471 IXAudio2EngineCallback_OnProcessingPassEnd(This->cbs[i]);
474 static void FAUDIOCALL XA2ECB_OnCriticalError(FAudioEngineCallback *iface,
475 uint32_t error)
477 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
478 int i;
479 TRACE("%p\n", This);
480 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
481 IXAudio2EngineCallback_OnCriticalError(This->cbs[i], error);
484 static const FAudioEngineCallback FAudioEngineCallback_Vtbl = {
485 XA2ECB_OnCriticalError,
486 XA2ECB_OnProcessingPassEnd,
487 XA2ECB_OnProcessingPassStart
490 /* Common Voice Functions */
492 static inline void destroy_voice(XA2VoiceImpl *This)
494 FAudioVoice_DestroyVoice(This->faudio_voice);
495 free_effect_chain(This->effect_chain);
496 This->effect_chain = NULL;
497 This->in_use = FALSE;
500 /* Source Voices */
502 static inline XA2VoiceImpl *impl_from_IXAudio2SourceVoice(IXAudio2SourceVoice *iface)
504 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SourceVoice_iface);
507 static void WINAPI XA2SRC_GetVoiceDetails(IXAudio2SourceVoice *iface,
508 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
510 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
511 TRACE("%p, %p\n", This, pVoiceDetails);
512 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
515 static HRESULT WINAPI XA2SRC_SetOutputVoices(IXAudio2SourceVoice *iface,
516 const XAUDIO2_VOICE_SENDS *pSendList)
518 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
519 FAudioVoiceSends *faudio_sends;
520 HRESULT hr;
522 TRACE("%p, %p\n", This, pSendList);
524 faudio_sends = wrap_voice_sends(pSendList);
526 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
528 free_voice_sends(faudio_sends);
530 return hr;
533 static HRESULT WINAPI XA2SRC_SetEffectChain(IXAudio2SourceVoice *iface,
534 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
536 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
537 HRESULT hr;
539 TRACE("%p, %p\n", This, pEffectChain);
541 free_effect_chain(This->effect_chain);
542 This->effect_chain = wrap_effect_chain(pEffectChain);
544 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
546 return hr;
549 static HRESULT WINAPI XA2SRC_EnableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
550 UINT32 OperationSet)
552 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
553 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
554 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
557 static HRESULT WINAPI XA2SRC_DisableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
558 UINT32 OperationSet)
560 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
561 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
562 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
565 static void WINAPI XA2SRC_GetEffectState(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
566 BOOL *pEnabled)
568 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
569 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
570 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
573 static HRESULT WINAPI XA2SRC_SetEffectParameters(IXAudio2SourceVoice *iface,
574 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
575 UINT32 OperationSet)
577 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
578 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
579 ParametersByteSize, OperationSet);
580 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
581 pParameters, ParametersByteSize, OperationSet);
584 static HRESULT WINAPI XA2SRC_GetEffectParameters(IXAudio2SourceVoice *iface,
585 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
587 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
588 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
589 ParametersByteSize);
590 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
591 pParameters, ParametersByteSize);
594 static HRESULT WINAPI XA2SRC_SetFilterParameters(IXAudio2SourceVoice *iface,
595 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
597 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
598 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
599 return FAudioVoice_SetFilterParameters(This->faudio_voice,
600 (const FAudioFilterParameters *)pParameters, OperationSet);
603 static void WINAPI XA2SRC_GetFilterParameters(IXAudio2SourceVoice *iface,
604 XAUDIO2_FILTER_PARAMETERS *pParameters)
606 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
607 TRACE("%p, %p\n", This, pParameters);
608 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
611 static HRESULT WINAPI XA2SRC_SetOutputFilterParameters(IXAudio2SourceVoice *iface,
612 IXAudio2Voice *pDestinationVoice,
613 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
615 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
616 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
618 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
620 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
621 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
624 static void WINAPI XA2SRC_GetOutputFilterParameters(IXAudio2SourceVoice *iface,
625 IXAudio2Voice *pDestinationVoice,
626 XAUDIO2_FILTER_PARAMETERS *pParameters)
628 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
629 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
631 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
633 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
634 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
637 static HRESULT WINAPI XA2SRC_SetVolume(IXAudio2SourceVoice *iface, float Volume,
638 UINT32 OperationSet)
640 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
641 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
642 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
645 static void WINAPI XA2SRC_GetVolume(IXAudio2SourceVoice *iface, float *pVolume)
647 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
648 TRACE("%p, %p\n", This, pVolume);
649 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
652 static HRESULT WINAPI XA2SRC_SetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
653 const float *pVolumes, UINT32 OperationSet)
655 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
656 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
657 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
658 pVolumes, OperationSet);
661 static void WINAPI XA2SRC_GetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
662 float *pVolumes)
664 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
665 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
666 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
667 pVolumes);
670 static HRESULT WINAPI XA2SRC_SetOutputMatrix(IXAudio2SourceVoice *iface,
671 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
672 UINT32 DestinationChannels, const float *pLevelMatrix,
673 UINT32 OperationSet)
675 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
676 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
678 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
679 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
681 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
682 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
685 static void WINAPI XA2SRC_GetOutputMatrix(IXAudio2SourceVoice *iface,
686 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
687 UINT32 DestinationChannels, float *pLevelMatrix)
689 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
690 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
692 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
693 SourceChannels, DestinationChannels, pLevelMatrix);
695 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
696 SourceChannels, DestinationChannels, pLevelMatrix);
699 static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
701 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
703 TRACE("%p\n", This);
705 EnterCriticalSection(&This->lock);
707 destroy_voice(This);
709 LeaveCriticalSection(&This->lock);
712 static HRESULT WINAPI XA2SRC_Start(IXAudio2SourceVoice *iface, UINT32 Flags,
713 UINT32 OperationSet)
715 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
717 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
719 return FAudioSourceVoice_Start(This->faudio_voice, Flags, OperationSet);
722 static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
723 UINT32 OperationSet)
725 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
727 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
729 return FAudioSourceVoice_Stop(This->faudio_voice, Flags, OperationSet);
732 static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
733 const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
735 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
737 TRACE("%p, %p, %p\n", This, pBuffer, pBufferWMA);
739 return FAudioSourceVoice_SubmitSourceBuffer(This->faudio_voice, (FAudioBuffer*)pBuffer, (FAudioBufferWMA*)pBufferWMA);
742 static HRESULT WINAPI XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice *iface)
744 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
746 TRACE("%p\n", This);
748 return FAudioSourceVoice_FlushSourceBuffers(This->faudio_voice);
751 static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
753 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
755 TRACE("%p\n", This);
757 return FAudioSourceVoice_Discontinuity(This->faudio_voice);
760 static HRESULT WINAPI XA2SRC_ExitLoop(IXAudio2SourceVoice *iface, UINT32 OperationSet)
762 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
764 TRACE("%p, 0x%x\n", This, OperationSet);
766 return FAudioSourceVoice_ExitLoop(This->faudio_voice, OperationSet);
769 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface,
770 XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags)
772 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
774 TRACE("%p, %p, 0x%x\n", This, pVoiceState, Flags);
776 return FAudioSourceVoice_GetState(This->faudio_voice, (FAudioVoiceState*)pVoiceState, Flags);
779 static HRESULT WINAPI XA2SRC_SetFrequencyRatio(IXAudio2SourceVoice *iface,
780 float Ratio, UINT32 OperationSet)
782 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
784 TRACE("%p, %f, 0x%x\n", This, Ratio, OperationSet);
786 return FAudioSourceVoice_SetFrequencyRatio(This->faudio_voice, Ratio, OperationSet);
789 static void WINAPI XA2SRC_GetFrequencyRatio(IXAudio2SourceVoice *iface, float *pRatio)
791 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
793 TRACE("%p, %p\n", This, pRatio);
795 return FAudioSourceVoice_GetFrequencyRatio(This->faudio_voice, pRatio);
798 static HRESULT WINAPI XA2SRC_SetSourceSampleRate(
799 IXAudio2SourceVoice *iface,
800 UINT32 NewSourceSampleRate)
802 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
804 TRACE("%p, %u\n", This, NewSourceSampleRate);
806 return FAudioSourceVoice_SetSourceSampleRate(This->faudio_voice, NewSourceSampleRate);
809 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl = {
810 XA2SRC_GetVoiceDetails,
811 XA2SRC_SetOutputVoices,
812 XA2SRC_SetEffectChain,
813 XA2SRC_EnableEffect,
814 XA2SRC_DisableEffect,
815 XA2SRC_GetEffectState,
816 XA2SRC_SetEffectParameters,
817 XA2SRC_GetEffectParameters,
818 XA2SRC_SetFilterParameters,
819 XA2SRC_GetFilterParameters,
820 XA2SRC_SetOutputFilterParameters,
821 XA2SRC_GetOutputFilterParameters,
822 XA2SRC_SetVolume,
823 XA2SRC_GetVolume,
824 XA2SRC_SetChannelVolumes,
825 XA2SRC_GetChannelVolumes,
826 XA2SRC_SetOutputMatrix,
827 XA2SRC_GetOutputMatrix,
828 XA2SRC_DestroyVoice,
829 XA2SRC_Start,
830 XA2SRC_Stop,
831 XA2SRC_SubmitSourceBuffer,
832 XA2SRC_FlushSourceBuffers,
833 XA2SRC_Discontinuity,
834 XA2SRC_ExitLoop,
835 XA2SRC_GetState,
836 XA2SRC_SetFrequencyRatio,
837 XA2SRC_GetFrequencyRatio,
838 XA2SRC_SetSourceSampleRate
841 /* Submix Voices */
843 static inline XA2VoiceImpl *impl_from_IXAudio2SubmixVoice(IXAudio2SubmixVoice *iface)
845 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SubmixVoice_iface);
848 static void WINAPI XA2SUB_GetVoiceDetails(IXAudio2SubmixVoice *iface,
849 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
851 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
852 TRACE("%p, %p\n", This, pVoiceDetails);
853 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
856 static HRESULT WINAPI XA2SUB_SetOutputVoices(IXAudio2SubmixVoice *iface,
857 const XAUDIO2_VOICE_SENDS *pSendList)
859 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
860 FAudioVoiceSends *faudio_sends;
861 HRESULT hr;
863 TRACE("%p, %p\n", This, pSendList);
865 faudio_sends = wrap_voice_sends(pSendList);
867 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
869 free_voice_sends(faudio_sends);
871 return hr;
874 static HRESULT WINAPI XA2SUB_SetEffectChain(IXAudio2SubmixVoice *iface,
875 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
877 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
878 HRESULT hr;
880 TRACE("%p, %p\n", This, pEffectChain);
882 free_effect_chain(This->effect_chain);
883 This->effect_chain = wrap_effect_chain(pEffectChain);
885 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
887 return hr;
890 static HRESULT WINAPI XA2SUB_EnableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
891 UINT32 OperationSet)
893 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
894 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
895 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
898 static HRESULT WINAPI XA2SUB_DisableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
899 UINT32 OperationSet)
901 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
902 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
903 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
906 static void WINAPI XA2SUB_GetEffectState(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
907 BOOL *pEnabled)
909 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
910 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
911 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
914 static HRESULT WINAPI XA2SUB_SetEffectParameters(IXAudio2SubmixVoice *iface,
915 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
916 UINT32 OperationSet)
918 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
919 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
920 ParametersByteSize, OperationSet);
921 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
922 pParameters, ParametersByteSize, OperationSet);
925 static HRESULT WINAPI XA2SUB_GetEffectParameters(IXAudio2SubmixVoice *iface,
926 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
928 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
929 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
930 ParametersByteSize);
931 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
932 pParameters, ParametersByteSize);
935 static HRESULT WINAPI XA2SUB_SetFilterParameters(IXAudio2SubmixVoice *iface,
936 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
938 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
939 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
940 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
941 OperationSet);
944 static void WINAPI XA2SUB_GetFilterParameters(IXAudio2SubmixVoice *iface,
945 XAUDIO2_FILTER_PARAMETERS *pParameters)
947 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
948 TRACE("%p, %p\n", This, pParameters);
949 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
952 static HRESULT WINAPI XA2SUB_SetOutputFilterParameters(IXAudio2SubmixVoice *iface,
953 IXAudio2Voice *pDestinationVoice,
954 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
956 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
957 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
959 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
961 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
962 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
965 static void WINAPI XA2SUB_GetOutputFilterParameters(IXAudio2SubmixVoice *iface,
966 IXAudio2Voice *pDestinationVoice,
967 XAUDIO2_FILTER_PARAMETERS *pParameters)
969 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
970 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
972 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
974 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
975 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
978 static HRESULT WINAPI XA2SUB_SetVolume(IXAudio2SubmixVoice *iface, float Volume,
979 UINT32 OperationSet)
981 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
982 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
983 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
986 static void WINAPI XA2SUB_GetVolume(IXAudio2SubmixVoice *iface, float *pVolume)
988 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
989 TRACE("%p, %p\n", This, pVolume);
990 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
993 static HRESULT WINAPI XA2SUB_SetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
994 const float *pVolumes, UINT32 OperationSet)
996 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
997 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
998 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
999 pVolumes, OperationSet);
1002 static void WINAPI XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1003 float *pVolumes)
1005 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1006 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1007 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1008 pVolumes);
1011 static HRESULT WINAPI XA2SUB_SetOutputMatrix(IXAudio2SubmixVoice *iface,
1012 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1013 UINT32 DestinationChannels, const float *pLevelMatrix,
1014 UINT32 OperationSet)
1016 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1017 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1019 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1020 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1022 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1023 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1026 static void WINAPI XA2SUB_GetOutputMatrix(IXAudio2SubmixVoice *iface,
1027 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1028 UINT32 DestinationChannels, float *pLevelMatrix)
1030 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1031 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1033 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1034 SourceChannels, DestinationChannels, pLevelMatrix);
1036 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1037 SourceChannels, DestinationChannels, pLevelMatrix);
1040 static void WINAPI XA2SUB_DestroyVoice(IXAudio2SubmixVoice *iface)
1042 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1044 TRACE("%p\n", This);
1046 EnterCriticalSection(&This->lock);
1048 destroy_voice(This);
1050 LeaveCriticalSection(&This->lock);
1053 static const struct IXAudio2SubmixVoiceVtbl XAudio2SubmixVoice_Vtbl = {
1054 XA2SUB_GetVoiceDetails,
1055 XA2SUB_SetOutputVoices,
1056 XA2SUB_SetEffectChain,
1057 XA2SUB_EnableEffect,
1058 XA2SUB_DisableEffect,
1059 XA2SUB_GetEffectState,
1060 XA2SUB_SetEffectParameters,
1061 XA2SUB_GetEffectParameters,
1062 XA2SUB_SetFilterParameters,
1063 XA2SUB_GetFilterParameters,
1064 XA2SUB_SetOutputFilterParameters,
1065 XA2SUB_GetOutputFilterParameters,
1066 XA2SUB_SetVolume,
1067 XA2SUB_GetVolume,
1068 XA2SUB_SetChannelVolumes,
1069 XA2SUB_GetChannelVolumes,
1070 XA2SUB_SetOutputMatrix,
1071 XA2SUB_GetOutputMatrix,
1072 XA2SUB_DestroyVoice
1075 /* Mastering Voices */
1077 static inline XA2VoiceImpl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface)
1079 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2MasteringVoice_iface);
1082 static void WINAPI XA2M_GetVoiceDetails(IXAudio2MasteringVoice *iface,
1083 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
1085 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1086 TRACE("%p, %p\n", This, pVoiceDetails);
1087 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
1090 static HRESULT WINAPI XA2M_SetOutputVoices(IXAudio2MasteringVoice *iface,
1091 const XAUDIO2_VOICE_SENDS *pSendList)
1093 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1094 FAudioVoiceSends *faudio_sends;
1095 HRESULT hr;
1097 TRACE("%p, %p\n", This, pSendList);
1099 faudio_sends = wrap_voice_sends(pSendList);
1101 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
1103 free_voice_sends(faudio_sends);
1105 return hr;
1108 static HRESULT WINAPI XA2M_SetEffectChain(IXAudio2MasteringVoice *iface,
1109 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1111 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1112 HRESULT hr;
1114 TRACE("%p, %p\n", This, pEffectChain);
1116 free_effect_chain(This->effect_chain);
1117 This->effect_chain = wrap_effect_chain(pEffectChain);
1119 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
1121 return hr;
1124 static HRESULT WINAPI XA2M_EnableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1125 UINT32 OperationSet)
1127 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1128 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1129 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
1132 static HRESULT WINAPI XA2M_DisableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1133 UINT32 OperationSet)
1135 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1136 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1137 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
1140 static void WINAPI XA2M_GetEffectState(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1141 BOOL *pEnabled)
1143 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1144 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
1145 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
1148 static HRESULT WINAPI XA2M_SetEffectParameters(IXAudio2MasteringVoice *iface,
1149 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
1150 UINT32 OperationSet)
1152 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1153 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
1154 ParametersByteSize, OperationSet);
1155 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
1156 pParameters, ParametersByteSize, OperationSet);
1159 static HRESULT WINAPI XA2M_GetEffectParameters(IXAudio2MasteringVoice *iface,
1160 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
1162 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1163 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
1164 ParametersByteSize);
1165 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
1166 pParameters, ParametersByteSize);
1169 static HRESULT WINAPI XA2M_SetFilterParameters(IXAudio2MasteringVoice *iface,
1170 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1172 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1173 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
1174 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
1175 OperationSet);
1178 static void WINAPI XA2M_GetFilterParameters(IXAudio2MasteringVoice *iface,
1179 XAUDIO2_FILTER_PARAMETERS *pParameters)
1181 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1182 TRACE("%p, %p\n", This, pParameters);
1183 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
1186 static HRESULT WINAPI XA2M_SetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1187 IXAudio2Voice *pDestinationVoice,
1188 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1190 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1191 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1193 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
1195 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
1196 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
1199 static void WINAPI XA2M_GetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1200 IXAudio2Voice *pDestinationVoice,
1201 XAUDIO2_FILTER_PARAMETERS *pParameters)
1203 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1204 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1206 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
1208 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
1209 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1212 static HRESULT WINAPI XA2M_SetVolume(IXAudio2MasteringVoice *iface, float Volume,
1213 UINT32 OperationSet)
1215 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1216 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1217 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1220 static void WINAPI XA2M_GetVolume(IXAudio2MasteringVoice *iface, float *pVolume)
1222 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1223 TRACE("%p, %p\n", This, pVolume);
1224 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1227 static HRESULT WINAPI XA2M_SetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1228 const float *pVolumes, UINT32 OperationSet)
1230 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1231 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1232 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1233 pVolumes, OperationSet);
1236 static void WINAPI XA2M_GetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1237 float *pVolumes)
1239 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1240 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1241 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1242 pVolumes);
1245 static HRESULT WINAPI XA2M_SetOutputMatrix(IXAudio2MasteringVoice *iface,
1246 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1247 UINT32 DestinationChannels, const float *pLevelMatrix,
1248 UINT32 OperationSet)
1250 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1251 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1253 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1254 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1256 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1257 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1260 static void WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface,
1261 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1262 UINT32 DestinationChannels, float *pLevelMatrix)
1264 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1265 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1267 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1268 SourceChannels, DestinationChannels, pLevelMatrix);
1270 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1271 SourceChannels, DestinationChannels, pLevelMatrix);
1274 static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface)
1276 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1278 TRACE("%p\n", This);
1280 EnterCriticalSection(&This->lock);
1282 destroy_voice(This);
1284 LeaveCriticalSection(&This->lock);
1287 static void WINAPI XA2M_GetChannelMask(IXAudio2MasteringVoice *iface,
1288 DWORD *pChannelMask)
1290 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1292 TRACE("%p, %p\n", This, pChannelMask);
1294 FAudioMasteringVoice_GetChannelMask(This->faudio_voice, (uint32_t *)pChannelMask);
1297 static const struct IXAudio2MasteringVoiceVtbl XAudio2MasteringVoice_Vtbl = {
1298 XA2M_GetVoiceDetails,
1299 XA2M_SetOutputVoices,
1300 XA2M_SetEffectChain,
1301 XA2M_EnableEffect,
1302 XA2M_DisableEffect,
1303 XA2M_GetEffectState,
1304 XA2M_SetEffectParameters,
1305 XA2M_GetEffectParameters,
1306 XA2M_SetFilterParameters,
1307 XA2M_GetFilterParameters,
1308 XA2M_SetOutputFilterParameters,
1309 XA2M_GetOutputFilterParameters,
1310 XA2M_SetVolume,
1311 XA2M_GetVolume,
1312 XA2M_SetChannelVolumes,
1313 XA2M_GetChannelVolumes,
1314 XA2M_SetOutputMatrix,
1315 XA2M_GetOutputMatrix,
1316 XA2M_DestroyVoice,
1317 XA2M_GetChannelMask
1320 /* More Common Voice Functions */
1322 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface)
1324 if(iface->lpVtbl == (void*)&XAudio2SourceVoice_Vtbl)
1325 return impl_from_IXAudio2SourceVoice((IXAudio2SourceVoice*)iface);
1326 if(iface->lpVtbl == (void*)&XAudio2MasteringVoice_Vtbl)
1327 return impl_from_IXAudio2MasteringVoice((IXAudio2MasteringVoice*)iface);
1328 if(iface->lpVtbl == (void*)&XAudio2SubmixVoice_Vtbl)
1329 return impl_from_IXAudio2SubmixVoice((IXAudio2SubmixVoice*)iface);
1330 #if XAUDIO2_VER == 0
1331 if(iface->lpVtbl == (void*)&XAudio20SourceVoice_Vtbl)
1332 return impl_from_IXAudio20SourceVoice((IXAudio20SourceVoice*)iface);
1333 if(iface->lpVtbl == (void*)&XAudio20SubmixVoice_Vtbl)
1334 return impl_from_IXAudio20SubmixVoice((IXAudio20SubmixVoice*)iface);
1335 if(iface->lpVtbl == (void*)&XAudio20MasteringVoice_Vtbl)
1336 return impl_from_IXAudio20MasteringVoice((IXAudio20MasteringVoice*)iface);
1337 #elif XAUDIO2_VER <= 3
1338 if(iface->lpVtbl == (void*)&XAudio23SourceVoice_Vtbl)
1339 return impl_from_IXAudio23SourceVoice((IXAudio23SourceVoice*)iface);
1340 if(iface->lpVtbl == (void*)&XAudio23SubmixVoice_Vtbl)
1341 return impl_from_IXAudio23SubmixVoice((IXAudio23SubmixVoice*)iface);
1342 if(iface->lpVtbl == (void*)&XAudio23MasteringVoice_Vtbl)
1343 return impl_from_IXAudio23MasteringVoice((IXAudio23MasteringVoice*)iface);
1344 #elif XAUDIO2_VER <= 7
1345 if(iface->lpVtbl == (void*)&XAudio27SourceVoice_Vtbl)
1346 return impl_from_IXAudio27SourceVoice((IXAudio27SourceVoice*)iface);
1347 if(iface->lpVtbl == (void*)&XAudio27SubmixVoice_Vtbl)
1348 return impl_from_IXAudio27SubmixVoice((IXAudio27SubmixVoice*)iface);
1349 if(iface->lpVtbl == (void*)&XAudio27MasteringVoice_Vtbl)
1350 return impl_from_IXAudio27MasteringVoice((IXAudio27MasteringVoice*)iface);
1351 #endif
1352 ERR("invalid IXAudio2Voice pointer: %p\n", iface);
1353 return NULL;
1356 /* XAudio2 Engine Implementation */
1358 static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface)
1360 return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2_iface);
1363 static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
1364 void **ppvObject)
1366 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1368 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1370 if(IsEqualGUID(riid, &IID_IUnknown) ||
1371 #if XAUDIO2_VER == 8
1372 IsEqualGUID(riid, &IID_IXAudio28) ||
1373 #endif
1374 IsEqualGUID(riid, &IID_IXAudio2))
1375 *ppvObject = &This->IXAudio2_iface;
1376 else if(IsEqualGUID(riid, &IID_IXAudio27)){
1377 /* all xaudio versions before 28 share an IID */
1378 #if XAUDIO2_VER == 0
1379 *ppvObject = &This->IXAudio20_iface;
1380 #elif XAUDIO2_VER <= 2
1381 *ppvObject = &This->IXAudio22_iface;
1382 #elif XAUDIO2_VER <= 3
1383 *ppvObject = &This->IXAudio23_iface;
1384 #elif XAUDIO2_VER <= 7
1385 *ppvObject = &This->IXAudio27_iface;
1386 #else
1387 *ppvObject = NULL;
1388 #endif
1389 }else
1390 *ppvObject = NULL;
1392 if(*ppvObject){
1393 IUnknown_AddRef((IUnknown*)*ppvObject);
1394 return S_OK;
1397 FIXME("(%p)->(%s,%p), not found\n", This,debugstr_guid(riid), ppvObject);
1399 return E_NOINTERFACE;
1402 static ULONG WINAPI IXAudio2Impl_AddRef(IXAudio2 *iface)
1404 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1405 ULONG ref = FAudio_AddRef(This->faudio);
1406 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1407 return ref;
1410 static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
1412 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1413 ULONG ref = FAudio_Release(This->faudio);
1415 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1417 if (!ref) {
1418 XA2VoiceImpl *v, *v2;
1420 LIST_FOR_EACH_ENTRY_SAFE(v, v2, &This->voices, XA2VoiceImpl, entry){
1421 v->lock.DebugInfo->Spare[0] = 0;
1422 DeleteCriticalSection(&v->lock);
1423 HeapFree(GetProcessHeap(), 0, v);
1426 HeapFree(GetProcessHeap(), 0, This->cbs);
1428 This->lock.DebugInfo->Spare[0] = 0;
1429 DeleteCriticalSection(&This->lock);
1431 HeapFree(GetProcessHeap(), 0, This);
1433 return ref;
1436 static HRESULT WINAPI IXAudio2Impl_RegisterForCallbacks(IXAudio2 *iface,
1437 IXAudio2EngineCallback *pCallback)
1439 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1440 int i;
1442 TRACE("(%p)->(%p)\n", This, pCallback);
1444 EnterCriticalSection(&This->lock);
1446 for(i = 0; i < This->ncbs; ++i){
1447 if(!This->cbs[i] || This->cbs[i] == pCallback){
1448 This->cbs[i] = pCallback;
1449 LeaveCriticalSection(&This->lock);
1450 return S_OK;
1454 This->ncbs++;
1455 This->cbs = heap_realloc(This->cbs, This->ncbs * sizeof(*This->cbs));
1457 This->cbs[i] = pCallback;
1459 LeaveCriticalSection(&This->lock);
1461 return S_OK;
1464 static void WINAPI IXAudio2Impl_UnregisterForCallbacks(IXAudio2 *iface,
1465 IXAudio2EngineCallback *pCallback)
1467 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1468 int i;
1470 TRACE("(%p)->(%p)\n", This, pCallback);
1472 EnterCriticalSection(&This->lock);
1474 if(This->ncbs == 0){
1475 LeaveCriticalSection(&This->lock);
1476 return;
1479 for(i = 0; i < This->ncbs; ++i){
1480 if(This->cbs[i] == pCallback)
1481 break;
1484 for(; i < This->ncbs - 1 && This->cbs[i + 1]; ++i)
1485 This->cbs[i] = This->cbs[i + 1];
1487 if(i < This->ncbs)
1488 This->cbs[i] = NULL;
1490 LeaveCriticalSection(&This->lock);
1493 static inline XA2VoiceImpl *create_voice(IXAudio2Impl *This)
1495 XA2VoiceImpl *voice;
1497 voice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*voice));
1498 if(!voice)
1499 return NULL;
1501 list_add_head(&This->voices, &voice->entry);
1503 voice->IXAudio2SourceVoice_iface.lpVtbl = &XAudio2SourceVoice_Vtbl;
1504 #if XAUDIO2_VER == 0
1505 voice->IXAudio20SourceVoice_iface.lpVtbl = &XAudio20SourceVoice_Vtbl;
1506 #elif XAUDIO2_VER <= 3
1507 voice->IXAudio23SourceVoice_iface.lpVtbl = &XAudio23SourceVoice_Vtbl;
1508 #elif XAUDIO2_VER <= 7
1509 voice->IXAudio27SourceVoice_iface.lpVtbl = &XAudio27SourceVoice_Vtbl;
1510 #endif
1512 voice->IXAudio2SubmixVoice_iface.lpVtbl = &XAudio2SubmixVoice_Vtbl;
1513 #if XAUDIO2_VER == 0
1514 voice->IXAudio20SubmixVoice_iface.lpVtbl = &XAudio20SubmixVoice_Vtbl;
1515 #elif XAUDIO2_VER <= 3
1516 voice->IXAudio23SubmixVoice_iface.lpVtbl = &XAudio23SubmixVoice_Vtbl;
1517 #elif XAUDIO2_VER <= 7
1518 voice->IXAudio27SubmixVoice_iface.lpVtbl = &XAudio27SubmixVoice_Vtbl;
1519 #endif
1521 voice->FAudioVoiceCallback_vtbl = FAudioVoiceCallback_Vtbl;
1523 InitializeCriticalSection(&voice->lock);
1524 voice->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2VoiceImpl.lock");
1526 return voice;
1529 static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
1530 IXAudio2SourceVoice **ppSourceVoice, const WAVEFORMATEX *pSourceFormat,
1531 UINT32 flags, float maxFrequencyRatio,
1532 IXAudio2VoiceCallback *pCallback, const XAUDIO2_VOICE_SENDS *pSendList,
1533 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1535 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1536 XA2VoiceImpl *src;
1537 HRESULT hr;
1538 FAudioVoiceSends *faudio_sends;
1540 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This, ppSourceVoice,
1541 pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
1542 pEffectChain);
1544 EnterCriticalSection(&This->lock);
1546 LIST_FOR_EACH_ENTRY(src, &This->voices, XA2VoiceImpl, entry){
1547 EnterCriticalSection(&src->lock);
1548 if(!src->in_use)
1549 break;
1550 LeaveCriticalSection(&src->lock);
1553 if(&src->entry == &This->voices){
1554 src = create_voice(This);
1555 EnterCriticalSection(&src->lock);
1558 LeaveCriticalSection(&This->lock);
1560 src->effect_chain = wrap_effect_chain(pEffectChain);
1561 faudio_sends = wrap_voice_sends(pSendList);
1563 hr = FAudio_CreateSourceVoice(This->faudio, &src->faudio_voice,
1564 (FAudioWaveFormatEx*)pSourceFormat, flags, maxFrequencyRatio,
1565 &src->FAudioVoiceCallback_vtbl, faudio_sends,
1566 src->effect_chain);
1567 free_voice_sends(faudio_sends);
1568 if(FAILED(hr)){
1569 LeaveCriticalSection(&This->lock);
1570 return hr;
1572 src->in_use = TRUE;
1573 src->cb = pCallback;
1575 LeaveCriticalSection(&src->lock);
1577 #if XAUDIO2_VER == 0
1578 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio20SourceVoice_iface;
1579 #elif XAUDIO2_VER <= 3
1580 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio23SourceVoice_iface;
1581 #elif XAUDIO2_VER <= 7
1582 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio27SourceVoice_iface;
1583 #else
1584 *ppSourceVoice = &src->IXAudio2SourceVoice_iface;
1585 #endif
1587 TRACE("Created source voice: %p\n", src);
1589 return S_OK;
1592 static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
1593 IXAudio2SubmixVoice **ppSubmixVoice, UINT32 inputChannels,
1594 UINT32 inputSampleRate, UINT32 flags, UINT32 processingStage,
1595 const XAUDIO2_VOICE_SENDS *pSendList,
1596 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1598 HRESULT hr;
1599 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1600 XA2VoiceImpl *sub;
1601 FAudioVoiceSends *faudio_sends;
1603 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This, ppSubmixVoice,
1604 inputChannels, inputSampleRate, flags, processingStage, pSendList,
1605 pEffectChain);
1607 EnterCriticalSection(&This->lock);
1609 LIST_FOR_EACH_ENTRY(sub, &This->voices, XA2VoiceImpl, entry){
1610 EnterCriticalSection(&sub->lock);
1611 if(!sub->in_use)
1612 break;
1613 LeaveCriticalSection(&sub->lock);
1616 if(&sub->entry == &This->voices){
1617 sub = create_voice(This);
1618 EnterCriticalSection(&sub->lock);
1621 LeaveCriticalSection(&This->lock);
1623 sub->effect_chain = wrap_effect_chain(pEffectChain);
1624 faudio_sends = wrap_voice_sends(pSendList);
1626 hr = FAudio_CreateSubmixVoice(This->faudio, &sub->faudio_voice, inputChannels,
1627 inputSampleRate, flags, processingStage, faudio_sends,
1628 sub->effect_chain);
1629 free_voice_sends(faudio_sends);
1630 if(FAILED(hr)){
1631 LeaveCriticalSection(&sub->lock);
1632 return hr;
1634 sub->in_use = TRUE;
1636 LeaveCriticalSection(&sub->lock);
1638 #if XAUDIO2_VER == 0
1639 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio20SubmixVoice_iface;
1640 #elif XAUDIO2_VER <= 3
1641 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio23SubmixVoice_iface;
1642 #elif XAUDIO2_VER <= 7
1643 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio27SubmixVoice_iface;
1644 #else
1645 *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
1646 #endif
1648 TRACE("Created submix voice: %p\n", sub);
1650 return S_OK;
1653 static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
1654 IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels,
1655 UINT32 inputSampleRate, UINT32 flags, const WCHAR *deviceId,
1656 const XAUDIO2_EFFECT_CHAIN *pEffectChain,
1657 AUDIO_STREAM_CATEGORY streamCategory)
1659 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1661 TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This,
1662 ppMasteringVoice, inputChannels, inputSampleRate, flags,
1663 wine_dbgstr_w(deviceId), pEffectChain, streamCategory);
1665 EnterCriticalSection(&This->lock);
1667 /* Note that we don't have paths for each XAUDIO2_VER here.
1668 * All versions < 8 have a very different CreateMasteringVoice, so we
1669 * implement those separately in compat.c.
1670 * -flibit
1672 *ppMasteringVoice = &This->mst.IXAudio2MasteringVoice_iface;
1674 EnterCriticalSection(&This->mst.lock);
1676 if(This->mst.in_use){
1677 LeaveCriticalSection(&This->mst.lock);
1678 LeaveCriticalSection(&This->lock);
1679 return COMPAT_E_INVALID_CALL;
1682 LeaveCriticalSection(&This->lock);
1684 This->mst.effect_chain = wrap_effect_chain(pEffectChain);
1686 FAudio_CreateMasteringVoice8(This->faudio, &This->mst.faudio_voice, inputChannels,
1687 inputSampleRate, flags, NULL /* TODO: (uint16_t*)deviceId */,
1688 This->mst.effect_chain, (FAudioStreamCategory)streamCategory);
1690 This->mst.in_use = TRUE;
1692 LeaveCriticalSection(&This->mst.lock);
1694 return S_OK;
1697 static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
1699 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1701 TRACE("(%p)->()\n", This);
1703 return FAudio_StartEngine(This->faudio);
1706 static void WINAPI IXAudio2Impl_StopEngine(IXAudio2 *iface)
1708 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1710 TRACE("(%p)->()\n", This);
1712 FAudio_StopEngine(This->faudio);
1715 static HRESULT WINAPI IXAudio2Impl_CommitChanges(IXAudio2 *iface,
1716 UINT32 operationSet)
1718 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1720 TRACE("(%p)->(0x%x)\n", This, operationSet);
1722 return FAudio_CommitOperationSet(This->faudio, operationSet);
1725 static void WINAPI IXAudio2Impl_GetPerformanceData(IXAudio2 *iface,
1726 XAUDIO2_PERFORMANCE_DATA *pPerfData)
1728 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1730 TRACE("(%p)->(%p)\n", This, pPerfData);
1732 FAudio_GetPerformanceData(This->faudio, (FAudioPerformanceData *)pPerfData);
1735 static void WINAPI IXAudio2Impl_SetDebugConfiguration(IXAudio2 *iface,
1736 const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
1737 void *pReserved)
1739 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1741 TRACE("(%p)->(%p, %p)\n", This, pDebugConfiguration, pReserved);
1743 FAudio_SetDebugConfiguration(This->faudio, (FAudioDebugConfiguration *)pDebugConfiguration, pReserved);
1746 /* XAudio2 2.8 */
1747 static const IXAudio2Vtbl XAudio2_Vtbl =
1749 IXAudio2Impl_QueryInterface,
1750 IXAudio2Impl_AddRef,
1751 IXAudio2Impl_Release,
1752 IXAudio2Impl_RegisterForCallbacks,
1753 IXAudio2Impl_UnregisterForCallbacks,
1754 IXAudio2Impl_CreateSourceVoice,
1755 IXAudio2Impl_CreateSubmixVoice,
1756 IXAudio2Impl_CreateMasteringVoice,
1757 IXAudio2Impl_StartEngine,
1758 IXAudio2Impl_StopEngine,
1759 IXAudio2Impl_CommitChanges,
1760 IXAudio2Impl_GetPerformanceData,
1761 IXAudio2Impl_SetDebugConfiguration
1764 /* XAudio2 ClassFactory */
1766 struct xaudio2_cf {
1767 IClassFactory IClassFactory_iface;
1768 LONG ref;
1771 static struct xaudio2_cf *impl_from_IClassFactory(IClassFactory *iface)
1773 return CONTAINING_RECORD(iface, struct xaudio2_cf, IClassFactory_iface);
1776 static HRESULT WINAPI XAudio2CF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1778 if(IsEqualGUID(riid, &IID_IUnknown)
1779 || IsEqualGUID(riid, &IID_IClassFactory))
1781 IClassFactory_AddRef(iface);
1782 *ppobj = iface;
1783 return S_OK;
1786 *ppobj = NULL;
1787 WARN("(%p)->(%s, %p): interface not found\n", iface, debugstr_guid(riid), ppobj);
1788 return E_NOINTERFACE;
1791 static ULONG WINAPI XAudio2CF_AddRef(IClassFactory *iface)
1793 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1794 ULONG ref = InterlockedIncrement(&This->ref);
1795 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1796 return ref;
1799 static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
1801 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1802 ULONG ref = InterlockedDecrement(&This->ref);
1803 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1804 if (!ref)
1805 HeapFree(GetProcessHeap(), 0, This);
1806 return ref;
1809 static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1810 REFIID riid, void **ppobj)
1812 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1813 HRESULT hr;
1814 IXAudio2Impl *object;
1816 TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
1818 *ppobj = NULL;
1820 if(pOuter)
1821 return CLASS_E_NOAGGREGATION;
1823 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1824 if(!object)
1825 return E_OUTOFMEMORY;
1827 object->IXAudio2_iface.lpVtbl = &XAudio2_Vtbl;
1829 #if XAUDIO2_VER == 0
1830 object->IXAudio20_iface.lpVtbl = &XAudio20_Vtbl;
1831 #elif XAUDIO2_VER <= 2
1832 object->IXAudio22_iface.lpVtbl = &XAudio22_Vtbl;
1833 #elif XAUDIO2_VER <= 3
1834 object->IXAudio23_iface.lpVtbl = &XAudio23_Vtbl;
1835 #elif XAUDIO2_VER <= 7
1836 object->IXAudio27_iface.lpVtbl = &XAudio27_Vtbl;
1837 #endif
1839 object->mst.IXAudio2MasteringVoice_iface.lpVtbl = &XAudio2MasteringVoice_Vtbl;
1841 #if XAUDIO2_VER == 0
1842 object->mst.IXAudio20MasteringVoice_iface.lpVtbl = &XAudio20MasteringVoice_Vtbl;
1843 #elif XAUDIO2_VER <= 3
1844 object->mst.IXAudio23MasteringVoice_iface.lpVtbl = &XAudio23MasteringVoice_Vtbl;
1845 #elif XAUDIO2_VER <= 7
1846 object->mst.IXAudio27MasteringVoice_iface.lpVtbl = &XAudio27MasteringVoice_Vtbl;
1847 #endif
1849 object->FAudioEngineCallback_vtbl = FAudioEngineCallback_Vtbl;
1851 list_init(&object->voices);
1853 InitializeCriticalSection(&object->lock);
1854 object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IXAudio2Impl.lock");
1856 InitializeCriticalSection(&object->mst.lock);
1857 object->mst.lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2MasteringVoice.lock");
1859 FAudioCOMConstructWithCustomAllocatorEXT(
1860 &object->faudio,
1861 XAUDIO2_VER,
1862 XAudio_Internal_Malloc,
1863 XAudio_Internal_Free,
1864 XAudio_Internal_Realloc
1867 FAudio_RegisterForCallbacks(object->faudio, &object->FAudioEngineCallback_vtbl);
1869 hr = IXAudio2_QueryInterface(&object->IXAudio2_iface, riid, ppobj);
1870 IXAudio2_Release(&object->IXAudio2_iface);
1871 if(FAILED(hr)){
1872 return hr;
1875 TRACE("Created XAudio version %u: %p\n", 20 + XAUDIO2_VER, object);
1877 return hr;
1880 static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock)
1882 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1883 FIXME("(%p)->(%d): stub!\n", This, dolock);
1884 return S_OK;
1887 static const IClassFactoryVtbl XAudio2CF_Vtbl =
1889 XAudio2CF_QueryInterface,
1890 XAudio2CF_AddRef,
1891 XAudio2CF_Release,
1892 XAudio2CF_CreateInstance,
1893 XAudio2CF_LockServer
1896 /* Engine Generators */
1898 static inline HRESULT make_xaudio2_factory(REFIID riid, void **ppv)
1900 HRESULT hr;
1901 struct xaudio2_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
1902 ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
1903 ret->ref = 0;
1904 hr = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
1905 if(FAILED(hr))
1906 HeapFree(GetProcessHeap(), 0, ret);
1907 return hr;
1910 HRESULT xaudio2_initialize(IXAudio2Impl *This, UINT32 flags, XAUDIO2_PROCESSOR proc)
1912 if(proc != XAUDIO2_ANY_PROCESSOR)
1913 WARN("Processor affinity not implemented in FAudio\n");
1914 return FAudio_Initialize(This->faudio, flags, FAUDIO_DEFAULT_PROCESSOR);
1917 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
1919 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1921 if(IsEqualGUID(rclsid, &CLSID_XAudio20) ||
1922 IsEqualGUID(rclsid, &CLSID_XAudio21) ||
1923 IsEqualGUID(rclsid, &CLSID_XAudio22) ||
1924 IsEqualGUID(rclsid, &CLSID_XAudio23) ||
1925 IsEqualGUID(rclsid, &CLSID_XAudio24) ||
1926 IsEqualGUID(rclsid, &CLSID_XAudio25) ||
1927 IsEqualGUID(rclsid, &CLSID_XAudio26) ||
1928 IsEqualGUID(rclsid, &CLSID_XAudio27))
1929 return make_xaudio2_factory(riid, ppv);
1931 if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter20) ||
1932 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter21) ||
1933 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter22) ||
1934 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter23) ||
1935 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter24) ||
1936 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter25) ||
1937 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter26) ||
1938 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter27))
1939 return make_xapo_factory(&CLSID_AudioVolumeMeter27, riid, ppv);
1941 if(IsEqualGUID(rclsid, &CLSID_AudioReverb20) ||
1942 IsEqualGUID(rclsid, &CLSID_AudioReverb21) ||
1943 IsEqualGUID(rclsid, &CLSID_AudioReverb22) ||
1944 IsEqualGUID(rclsid, &CLSID_AudioReverb23) ||
1945 IsEqualGUID(rclsid, &CLSID_AudioReverb24) ||
1946 IsEqualGUID(rclsid, &CLSID_AudioReverb25) ||
1947 IsEqualGUID(rclsid, &CLSID_AudioReverb26) ||
1948 IsEqualGUID(rclsid, &CLSID_AudioReverb27))
1949 return make_xapo_factory(&CLSID_AudioReverb27, riid, ppv);
1951 return CLASS_E_CLASSNOTAVAILABLE;
1954 #if XAUDIO2_VER >= 8
1955 HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR proc)
1957 HRESULT hr;
1958 IXAudio2 *xa2;
1959 IClassFactory *cf;
1961 TRACE("%p 0x%x 0x%x\n", ppxa2, flags, proc);
1963 hr = make_xaudio2_factory(&IID_IClassFactory, (void**)&cf);
1964 if(FAILED(hr))
1965 return hr;
1967 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IXAudio2, (void**)&xa2);
1968 IClassFactory_Release(cf);
1969 if(FAILED(hr))
1970 return hr;
1972 hr = xaudio2_initialize(impl_from_IXAudio2(xa2), flags, proc);
1973 if(FAILED(hr)){
1974 IXAudio2_Release(xa2);
1975 return hr;
1978 *ppxa2 = xa2;
1980 return S_OK;
1983 HRESULT WINAPI CreateAudioVolumeMeter(IUnknown **out)
1985 IClassFactory *cf;
1986 HRESULT hr;
1988 TRACE("%p\n", out);
1990 hr = make_xapo_factory(&CLSID_AudioVolumeMeter27, &IID_IClassFactory, (void**)&cf);
1991 if(FAILED(hr))
1992 return hr;
1994 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
1996 IClassFactory_Release(cf);
1998 return hr;
2001 HRESULT WINAPI CreateAudioReverb(IUnknown **out)
2003 IClassFactory *cf;
2004 HRESULT hr;
2006 TRACE("%p\n", out);
2008 hr = make_xapo_factory(&CLSID_AudioReverb27, &IID_IClassFactory, (void**)&cf);
2009 if(FAILED(hr))
2010 return hr;
2012 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
2014 IClassFactory_Release(cf);
2016 return hr;
2018 #endif /* XAUDIO2_VER >= 8 */