dwrite: Always initialize output glyph count in GetGlyphs().
[wine.git] / dlls / xaudio2_7 / xaudio_dll.c
blobe8b81b125a09661ae4eeb95be5697795cb51bff9
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 "config.h"
23 #include <stdarg.h>
25 #define NONAMELESSUNION
26 #define COBJMACROS
28 #include "initguid.h"
29 #include "xaudio_private.h"
30 #include "xaudio2fx.h"
31 #if XAUDIO2_VER >= 8
32 #include "xapofx.h"
33 #endif
35 #include "ole2.h"
36 #include "rpcproxy.h"
38 #include "wine/asm.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
44 #if XAUDIO2_VER != 0 && defined(__i386__)
45 /* EVE Online uses an OnVoiceProcessingPassStart callback which corrupts %esi;
46 * League of Legends uses a callback which corrupts %ebx. */
47 #define IXAudio2VoiceCallback_OnVoiceProcessingPassStart(a, b) call_on_voice_processing_pass_start(a, b)
48 extern void call_on_voice_processing_pass_start(IXAudio2VoiceCallback *This, UINT32 BytesRequired);
49 __ASM_GLOBAL_FUNC( call_on_voice_processing_pass_start,
50 "pushl %ebp\n\t"
51 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
52 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
53 "movl %esp,%ebp\n\t"
54 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
55 "pushl %esi\n\t"
56 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
57 "pushl %edi\n\t"
58 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
59 "pushl %ebx\n\t"
60 __ASM_CFI(".cfi_rel_offset %ebx,-12\n\t")
61 "subl $4,%esp\n\t"
62 "pushl 12(%ebp)\n\t" /* BytesRequired */
63 "pushl 8(%ebp)\n\t" /* This */
64 "movl 8(%ebp),%eax\n\t"
65 "movl 0(%eax),%eax\n\t"
66 "call *0(%eax)\n\t" /* This->lpVtbl->OnVoiceProcessingPassStart */
67 "leal -12(%ebp),%esp\n\t"
68 "popl %ebx\n\t"
69 __ASM_CFI(".cfi_same_value %ebx\n\t")
70 "popl %edi\n\t"
71 __ASM_CFI(".cfi_same_value %edi\n\t")
72 "popl %esi\n\t"
73 __ASM_CFI(".cfi_same_value %esi\n\t")
74 "popl %ebp\n\t"
75 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
76 __ASM_CFI(".cfi_same_value %ebp\n\t")
77 "ret" )
78 #endif
80 static HINSTANCE instance;
82 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface);
84 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved)
86 TRACE("(%p, %d, %p)\n", hinstDLL, reason, pReserved);
88 switch (reason)
90 case DLL_PROCESS_ATTACH:
91 instance = hinstDLL;
92 DisableThreadLibraryCalls( hinstDLL );
93 #ifdef HAVE_FAUDIOLINKEDVERSION
94 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
95 #endif
96 break;
98 return TRUE;
101 HRESULT WINAPI DllCanUnloadNow(void)
103 return S_FALSE;
106 HRESULT WINAPI DllRegisterServer(void)
108 TRACE("\n");
109 return __wine_register_resources(instance);
112 HRESULT WINAPI DllUnregisterServer(void)
114 TRACE("\n");
115 return __wine_unregister_resources(instance);
118 /* Effect Wrapping */
120 static inline XA2XAPOImpl *impl_from_FAPO(FAPO *iface)
122 return CONTAINING_RECORD(iface, XA2XAPOImpl, FAPO_vtbl);
125 static int32_t FAPOCALL XAPO_AddRef(void *iface)
127 XA2XAPOImpl *This = impl_from_FAPO(iface);
128 TRACE("%p\n", This);
129 return InterlockedIncrement(&This->ref);
132 static int32_t FAPOCALL XAPO_Release(void *iface)
134 int32_t r;
135 XA2XAPOImpl *This = impl_from_FAPO(iface);
136 TRACE("%p\n", This);
137 r = InterlockedDecrement(&This->ref);
138 if(r == 0){
139 IXAPO_Release(This->xapo);
140 if(This->xapo_params)
141 IXAPOParameters_Release(This->xapo_params);
142 heap_free(This);
144 return r;
147 static uint32_t FAPOCALL XAPO_GetRegistrationProperties(void *iface,
148 FAPORegistrationProperties **ppRegistrationProperties)
150 XA2XAPOImpl *This = impl_from_FAPO(iface);
151 XAPO_REGISTRATION_PROPERTIES *xprops;
152 HRESULT hr;
154 TRACE("%p\n", This);
156 hr = IXAPO_GetRegistrationProperties(This->xapo, &xprops);
157 if(FAILED(hr))
158 return hr;
160 /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
161 *ppRegistrationProperties = (FAPORegistrationProperties*) xprops;
162 return 0;
165 static uint32_t FAPOCALL XAPO_IsInputFormatSupported(void *iface,
166 const FAudioWaveFormatEx *pOutputFormat, const FAudioWaveFormatEx *pRequestedInputFormat,
167 FAudioWaveFormatEx **ppSupportedInputFormat)
169 XA2XAPOImpl *This = impl_from_FAPO(iface);
170 TRACE("%p\n", This);
171 return IXAPO_IsInputFormatSupported(This->xapo, (const WAVEFORMATEX*)pOutputFormat,
172 (const WAVEFORMATEX*)pRequestedInputFormat, (WAVEFORMATEX**)ppSupportedInputFormat);
175 static uint32_t FAPOCALL XAPO_IsOutputFormatSupported(void *iface,
176 const FAudioWaveFormatEx *pInputFormat, const FAudioWaveFormatEx *pRequestedOutputFormat,
177 FAudioWaveFormatEx **ppSupportedOutputFormat)
179 XA2XAPOImpl *This = impl_from_FAPO(iface);
180 TRACE("%p\n", This);
181 return IXAPO_IsOutputFormatSupported(This->xapo, (const WAVEFORMATEX *)pInputFormat,
182 (const WAVEFORMATEX *)pRequestedOutputFormat, (WAVEFORMATEX**)ppSupportedOutputFormat);
185 static uint32_t FAPOCALL XAPO_Initialize(void *iface, const void *pData,
186 uint32_t DataByteSize)
188 XA2XAPOImpl *This = impl_from_FAPO(iface);
189 TRACE("%p\n", This);
190 return IXAPO_Initialize(This->xapo, pData, DataByteSize);
193 static void FAPOCALL XAPO_Reset(void *iface)
195 XA2XAPOImpl *This = impl_from_FAPO(iface);
196 TRACE("%p\n", This);
197 IXAPO_Reset(This->xapo);
200 static uint32_t FAPOCALL XAPO_LockForProcess(void *iface,
201 uint32_t InputLockedParameterCount,
202 const FAPOLockForProcessBufferParameters *pInputLockedParameters,
203 uint32_t OutputLockedParameterCount,
204 const FAPOLockForProcessBufferParameters *pOutputLockedParameters)
206 XA2XAPOImpl *This = impl_from_FAPO(iface);
207 TRACE("%p\n", This);
208 return IXAPO_LockForProcess(This->xapo,
209 InputLockedParameterCount,
210 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pInputLockedParameters,
211 OutputLockedParameterCount,
212 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pOutputLockedParameters);
215 static void FAPOCALL XAPO_UnlockForProcess(void *iface)
217 XA2XAPOImpl *This = impl_from_FAPO(iface);
218 TRACE("%p\n", This);
219 IXAPO_UnlockForProcess(This->xapo);
222 static void FAPOCALL XAPO_Process(void *iface,
223 uint32_t InputProcessParameterCount,
224 const FAPOProcessBufferParameters* pInputProcessParameters,
225 uint32_t OutputProcessParameterCount,
226 FAPOProcessBufferParameters* pOutputProcessParameters,
227 int32_t IsEnabled)
229 XA2XAPOImpl *This = impl_from_FAPO(iface);
230 TRACE("%p\n", This);
231 IXAPO_Process(This->xapo, InputProcessParameterCount,
232 (const XAPO_PROCESS_BUFFER_PARAMETERS *)pInputProcessParameters,
233 OutputProcessParameterCount,
234 (XAPO_PROCESS_BUFFER_PARAMETERS *)pOutputProcessParameters,
235 IsEnabled);
238 static uint32_t FAPOCALL XAPO_CalcInputFrames(void *iface,
239 uint32_t OutputFrameCount)
241 XA2XAPOImpl *This = impl_from_FAPO(iface);
242 TRACE("%p\n", This);
243 return IXAPO_CalcInputFrames(This->xapo, OutputFrameCount);
246 static uint32_t FAPOCALL XAPO_CalcOutputFrames(void *iface,
247 uint32_t InputFrameCount)
249 XA2XAPOImpl *This = impl_from_FAPO(iface);
250 TRACE("%p\n", This);
251 return IXAPO_CalcOutputFrames(This->xapo, InputFrameCount);
254 static void FAPOCALL XAPO_SetParameters(void *iface,
255 const void *pParameters, uint32_t ParametersByteSize)
257 XA2XAPOImpl *This = impl_from_FAPO(iface);
258 TRACE("%p\n", This);
259 if(This->xapo_params)
260 IXAPOParameters_SetParameters(This->xapo_params, pParameters, ParametersByteSize);
263 static void FAPOCALL XAPO_GetParameters(void *iface,
264 void *pParameters, uint32_t ParametersByteSize)
266 XA2XAPOImpl *This = impl_from_FAPO(iface);
267 TRACE("%p\n", This);
268 if(This->xapo_params)
269 IXAPOParameters_GetParameters(This->xapo_params, pParameters, ParametersByteSize);
270 else
271 memset(pParameters, 0, ParametersByteSize);
274 static const FAPO FAPO_Vtbl = {
275 XAPO_AddRef,
276 XAPO_Release,
277 XAPO_GetRegistrationProperties,
278 XAPO_IsInputFormatSupported,
279 XAPO_IsOutputFormatSupported,
280 XAPO_Initialize,
281 XAPO_Reset,
282 XAPO_LockForProcess,
283 XAPO_UnlockForProcess,
284 XAPO_Process,
285 XAPO_CalcInputFrames,
286 XAPO_CalcOutputFrames,
287 XAPO_SetParameters,
288 XAPO_GetParameters,
291 static XA2XAPOImpl *wrap_xapo(IUnknown *unk)
293 XA2XAPOImpl *ret;
294 IXAPO *xapo;
295 IXAPOParameters *xapo_params;
296 HRESULT hr;
298 #if XAUDIO2_VER <= 7
299 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27, (void**)&xapo);
300 #else
301 hr = IUnknown_QueryInterface(unk, &IID_IXAPO, (void**)&xapo);
302 #endif
303 if(FAILED(hr)){
304 WARN("XAPO doesn't support IXAPO? %p\n", unk);
305 return NULL;
308 #if XAUDIO2_VER <= 7
309 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27Parameters, (void**)&xapo_params);
310 #else
311 hr = IUnknown_QueryInterface(unk, &IID_IXAPOParameters, (void**)&xapo_params);
312 #endif
313 if(FAILED(hr)){
314 TRACE("XAPO doesn't support IXAPOParameters %p\n", unk);
315 xapo_params = NULL;
318 ret = heap_alloc(sizeof(*ret));
320 ret->xapo = xapo;
321 ret->xapo_params = xapo_params;
322 ret->FAPO_vtbl = FAPO_Vtbl;
323 ret->ref = 1;
325 TRACE("wrapped IXAPO %p with %p\n", xapo, ret);
327 return ret;
330 FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
332 FAudioEffectChain *ret;
333 int i;
335 if(!pEffectChain)
336 return NULL;
338 ret = heap_alloc(sizeof(*ret) + sizeof(FAudioEffectDescriptor) * pEffectChain->EffectCount);
340 ret->EffectCount = pEffectChain->EffectCount;
341 ret->pEffectDescriptors = (void*)(ret + 1);
343 for(i = 0; i < ret->EffectCount; ++i){
344 ret->pEffectDescriptors[i].pEffect = &wrap_xapo(pEffectChain->pEffectDescriptors[i].pEffect)->FAPO_vtbl;
345 ret->pEffectDescriptors[i].InitialState = pEffectChain->pEffectDescriptors[i].InitialState;
346 ret->pEffectDescriptors[i].OutputChannels = pEffectChain->pEffectDescriptors[i].OutputChannels;
349 return ret;
352 static void free_effect_chain(FAudioEffectChain *chain)
354 int i;
355 if(!chain)
356 return;
357 for(i = 0; i < chain->EffectCount; ++i)
358 XAPO_Release(chain->pEffectDescriptors[i].pEffect);
359 heap_free(chain);
362 /* Send Wrapping */
364 static FAudioVoiceSends *wrap_voice_sends(const XAUDIO2_VOICE_SENDS *sends)
366 FAudioVoiceSends *ret;
367 int i;
369 if(!sends)
370 return NULL;
372 ret = heap_alloc(sizeof(*ret) + sends->SendCount * sizeof(FAudioSendDescriptor));
373 ret->SendCount = sends->SendCount;
374 ret->pSends = (FAudioSendDescriptor*)(ret + 1);
375 for(i = 0; i < sends->SendCount; ++i){
376 XA2VoiceImpl *voice = impl_from_IXAudio2Voice(sends->pSends[i].pOutputVoice);
377 ret->pSends[i].pOutputVoice = voice->faudio_voice;
378 ret->pSends[i].Flags = sends->pSends[i].Flags;
380 return ret;
383 static void free_voice_sends(FAudioVoiceSends *sends)
385 if(!sends)
386 return;
387 heap_free(sends);
390 /* Voice Callbacks */
392 static inline XA2VoiceImpl *impl_from_FAudioVoiceCallback(FAudioVoiceCallback *iface)
394 return CONTAINING_RECORD(iface, XA2VoiceImpl, FAudioVoiceCallback_vtbl);
397 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassStart(FAudioVoiceCallback *iface,
398 UINT32 BytesRequired)
400 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
401 TRACE("%p\n", This);
402 if(This->cb)
403 #if XAUDIO2_VER == 0
404 IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)This->cb);
405 #else
406 IXAudio2VoiceCallback_OnVoiceProcessingPassStart(This->cb, BytesRequired);
407 #endif
410 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassEnd(FAudioVoiceCallback *iface)
412 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
413 TRACE("%p\n", This);
414 if(This->cb)
415 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(This->cb);
418 static void FAUDIOCALL XA2VCB_OnStreamEnd(FAudioVoiceCallback *iface)
420 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
421 TRACE("%p\n", This);
422 if(This->cb)
423 IXAudio2VoiceCallback_OnStreamEnd(This->cb);
426 static void FAUDIOCALL XA2VCB_OnBufferStart(FAudioVoiceCallback *iface,
427 void *pBufferContext)
429 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
430 TRACE("%p\n", This);
431 if(This->cb)
432 IXAudio2VoiceCallback_OnBufferStart(This->cb, pBufferContext);
435 static void FAUDIOCALL XA2VCB_OnBufferEnd(FAudioVoiceCallback *iface,
436 void *pBufferContext)
438 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
439 TRACE("%p\n", This);
440 if(This->cb)
441 IXAudio2VoiceCallback_OnBufferEnd(This->cb, pBufferContext);
444 static void FAUDIOCALL XA2VCB_OnLoopEnd(FAudioVoiceCallback *iface,
445 void *pBufferContext)
447 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
448 TRACE("%p\n", This);
449 if(This->cb)
450 IXAudio2VoiceCallback_OnLoopEnd(This->cb, pBufferContext);
453 static void FAUDIOCALL XA2VCB_OnVoiceError(FAudioVoiceCallback *iface,
454 void *pBufferContext, unsigned int Error)
456 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
457 TRACE("%p\n", This);
458 if(This->cb)
459 IXAudio2VoiceCallback_OnVoiceError(This->cb, pBufferContext, (HRESULT)Error);
462 static const FAudioVoiceCallback FAudioVoiceCallback_Vtbl = {
463 XA2VCB_OnBufferEnd,
464 XA2VCB_OnBufferStart,
465 XA2VCB_OnLoopEnd,
466 XA2VCB_OnStreamEnd,
467 XA2VCB_OnVoiceError,
468 XA2VCB_OnVoiceProcessingPassEnd,
469 XA2VCB_OnVoiceProcessingPassStart
472 /* Engine Callbacks */
474 static inline IXAudio2Impl *impl_from_FAudioEngineCallback(FAudioEngineCallback *iface)
476 return CONTAINING_RECORD(iface, IXAudio2Impl, FAudioEngineCallback_vtbl);
479 static void FAUDIOCALL XA2ECB_OnProcessingPassStart(FAudioEngineCallback *iface)
481 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
482 int i;
483 TRACE("%p\n", This);
484 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
485 IXAudio2EngineCallback_OnProcessingPassStart(This->cbs[i]);
488 static void FAUDIOCALL XA2ECB_OnProcessingPassEnd(FAudioEngineCallback *iface)
490 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
491 int i;
492 TRACE("%p\n", This);
493 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
494 IXAudio2EngineCallback_OnProcessingPassEnd(This->cbs[i]);
497 static void FAUDIOCALL XA2ECB_OnCriticalError(FAudioEngineCallback *iface,
498 uint32_t error)
500 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
501 int i;
502 TRACE("%p\n", This);
503 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
504 IXAudio2EngineCallback_OnCriticalError(This->cbs[i], error);
507 static const FAudioEngineCallback FAudioEngineCallback_Vtbl = {
508 XA2ECB_OnCriticalError,
509 XA2ECB_OnProcessingPassEnd,
510 XA2ECB_OnProcessingPassStart
513 /* Common Voice Functions */
515 static inline void destroy_voice(XA2VoiceImpl *This)
517 FAudioVoice_DestroyVoice(This->faudio_voice);
518 free_effect_chain(This->effect_chain);
519 This->effect_chain = NULL;
520 This->in_use = FALSE;
523 /* Source Voices */
525 static inline XA2VoiceImpl *impl_from_IXAudio2SourceVoice(IXAudio2SourceVoice *iface)
527 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SourceVoice_iface);
530 static void WINAPI XA2SRC_GetVoiceDetails(IXAudio2SourceVoice *iface,
531 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
533 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
534 TRACE("%p, %p\n", This, pVoiceDetails);
535 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
538 static HRESULT WINAPI XA2SRC_SetOutputVoices(IXAudio2SourceVoice *iface,
539 const XAUDIO2_VOICE_SENDS *pSendList)
541 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
542 FAudioVoiceSends *faudio_sends;
543 HRESULT hr;
545 TRACE("%p, %p\n", This, pSendList);
547 faudio_sends = wrap_voice_sends(pSendList);
549 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
551 free_voice_sends(faudio_sends);
553 return hr;
556 static HRESULT WINAPI XA2SRC_SetEffectChain(IXAudio2SourceVoice *iface,
557 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
559 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
560 HRESULT hr;
562 TRACE("%p, %p\n", This, pEffectChain);
564 free_effect_chain(This->effect_chain);
565 This->effect_chain = wrap_effect_chain(pEffectChain);
567 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
569 return hr;
572 static HRESULT WINAPI XA2SRC_EnableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
573 UINT32 OperationSet)
575 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
576 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
577 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
580 static HRESULT WINAPI XA2SRC_DisableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
581 UINT32 OperationSet)
583 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
584 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
585 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
588 static void WINAPI XA2SRC_GetEffectState(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
589 BOOL *pEnabled)
591 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
592 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
593 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
596 static HRESULT WINAPI XA2SRC_SetEffectParameters(IXAudio2SourceVoice *iface,
597 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
598 UINT32 OperationSet)
600 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
601 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
602 ParametersByteSize, OperationSet);
603 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
604 pParameters, ParametersByteSize, OperationSet);
607 static HRESULT WINAPI XA2SRC_GetEffectParameters(IXAudio2SourceVoice *iface,
608 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
610 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
611 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
612 ParametersByteSize);
613 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
614 pParameters, ParametersByteSize);
617 static HRESULT WINAPI XA2SRC_SetFilterParameters(IXAudio2SourceVoice *iface,
618 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
620 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
621 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
622 return FAudioVoice_SetFilterParameters(This->faudio_voice,
623 (const FAudioFilterParameters *)pParameters, OperationSet);
626 static void WINAPI XA2SRC_GetFilterParameters(IXAudio2SourceVoice *iface,
627 XAUDIO2_FILTER_PARAMETERS *pParameters)
629 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
630 TRACE("%p, %p\n", This, pParameters);
631 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
634 static HRESULT WINAPI XA2SRC_SetOutputFilterParameters(IXAudio2SourceVoice *iface,
635 IXAudio2Voice *pDestinationVoice,
636 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
638 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
639 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
641 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
643 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
644 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
647 static void WINAPI XA2SRC_GetOutputFilterParameters(IXAudio2SourceVoice *iface,
648 IXAudio2Voice *pDestinationVoice,
649 XAUDIO2_FILTER_PARAMETERS *pParameters)
651 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
652 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
654 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
656 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
657 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
660 static HRESULT WINAPI XA2SRC_SetVolume(IXAudio2SourceVoice *iface, float Volume,
661 UINT32 OperationSet)
663 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
664 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
665 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
668 static void WINAPI XA2SRC_GetVolume(IXAudio2SourceVoice *iface, float *pVolume)
670 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
671 TRACE("%p, %p\n", This, pVolume);
672 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
675 static HRESULT WINAPI XA2SRC_SetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
676 const float *pVolumes, UINT32 OperationSet)
678 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
679 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
680 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
681 pVolumes, OperationSet);
684 static void WINAPI XA2SRC_GetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
685 float *pVolumes)
687 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
688 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
689 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
690 pVolumes);
693 static HRESULT WINAPI XA2SRC_SetOutputMatrix(IXAudio2SourceVoice *iface,
694 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
695 UINT32 DestinationChannels, const float *pLevelMatrix,
696 UINT32 OperationSet)
698 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
699 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
701 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
702 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
704 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
705 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
708 static void WINAPI XA2SRC_GetOutputMatrix(IXAudio2SourceVoice *iface,
709 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
710 UINT32 DestinationChannels, float *pLevelMatrix)
712 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
713 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
715 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
716 SourceChannels, DestinationChannels, pLevelMatrix);
718 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
719 SourceChannels, DestinationChannels, pLevelMatrix);
722 static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
724 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
726 TRACE("%p\n", This);
728 EnterCriticalSection(&This->lock);
730 destroy_voice(This);
732 LeaveCriticalSection(&This->lock);
735 static HRESULT WINAPI XA2SRC_Start(IXAudio2SourceVoice *iface, UINT32 Flags,
736 UINT32 OperationSet)
738 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
740 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
742 return FAudioSourceVoice_Start(This->faudio_voice, Flags, OperationSet);
745 static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
746 UINT32 OperationSet)
748 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
750 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
752 return FAudioSourceVoice_Stop(This->faudio_voice, Flags, OperationSet);
755 static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
756 const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
758 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
760 TRACE("%p, %p, %p\n", This, pBuffer, pBufferWMA);
762 return FAudioSourceVoice_SubmitSourceBuffer(This->faudio_voice, (FAudioBuffer*)pBuffer, (FAudioBufferWMA*)pBufferWMA);
765 static HRESULT WINAPI XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice *iface)
767 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
769 TRACE("%p\n", This);
771 return FAudioSourceVoice_FlushSourceBuffers(This->faudio_voice);
774 static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
776 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
778 TRACE("%p\n", This);
780 return FAudioSourceVoice_Discontinuity(This->faudio_voice);
783 static HRESULT WINAPI XA2SRC_ExitLoop(IXAudio2SourceVoice *iface, UINT32 OperationSet)
785 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
787 TRACE("%p, 0x%x\n", This, OperationSet);
789 return FAudioSourceVoice_ExitLoop(This->faudio_voice, OperationSet);
792 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface,
793 XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags)
795 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
797 TRACE("%p, %p, 0x%x\n", This, pVoiceState, Flags);
799 return FAudioSourceVoice_GetState(This->faudio_voice, (FAudioVoiceState*)pVoiceState, Flags);
802 static HRESULT WINAPI XA2SRC_SetFrequencyRatio(IXAudio2SourceVoice *iface,
803 float Ratio, UINT32 OperationSet)
805 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
807 TRACE("%p, %f, 0x%x\n", This, Ratio, OperationSet);
809 return FAudioSourceVoice_SetFrequencyRatio(This->faudio_voice, Ratio, OperationSet);
812 static void WINAPI XA2SRC_GetFrequencyRatio(IXAudio2SourceVoice *iface, float *pRatio)
814 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
816 TRACE("%p, %p\n", This, pRatio);
818 return FAudioSourceVoice_GetFrequencyRatio(This->faudio_voice, pRatio);
821 static HRESULT WINAPI XA2SRC_SetSourceSampleRate(
822 IXAudio2SourceVoice *iface,
823 UINT32 NewSourceSampleRate)
825 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
827 TRACE("%p, %u\n", This, NewSourceSampleRate);
829 return FAudioSourceVoice_SetSourceSampleRate(This->faudio_voice, NewSourceSampleRate);
832 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl = {
833 XA2SRC_GetVoiceDetails,
834 XA2SRC_SetOutputVoices,
835 XA2SRC_SetEffectChain,
836 XA2SRC_EnableEffect,
837 XA2SRC_DisableEffect,
838 XA2SRC_GetEffectState,
839 XA2SRC_SetEffectParameters,
840 XA2SRC_GetEffectParameters,
841 XA2SRC_SetFilterParameters,
842 XA2SRC_GetFilterParameters,
843 XA2SRC_SetOutputFilterParameters,
844 XA2SRC_GetOutputFilterParameters,
845 XA2SRC_SetVolume,
846 XA2SRC_GetVolume,
847 XA2SRC_SetChannelVolumes,
848 XA2SRC_GetChannelVolumes,
849 XA2SRC_SetOutputMatrix,
850 XA2SRC_GetOutputMatrix,
851 XA2SRC_DestroyVoice,
852 XA2SRC_Start,
853 XA2SRC_Stop,
854 XA2SRC_SubmitSourceBuffer,
855 XA2SRC_FlushSourceBuffers,
856 XA2SRC_Discontinuity,
857 XA2SRC_ExitLoop,
858 XA2SRC_GetState,
859 XA2SRC_SetFrequencyRatio,
860 XA2SRC_GetFrequencyRatio,
861 XA2SRC_SetSourceSampleRate
864 /* Submix Voices */
866 static inline XA2VoiceImpl *impl_from_IXAudio2SubmixVoice(IXAudio2SubmixVoice *iface)
868 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SubmixVoice_iface);
871 static void WINAPI XA2SUB_GetVoiceDetails(IXAudio2SubmixVoice *iface,
872 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
874 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
875 TRACE("%p, %p\n", This, pVoiceDetails);
876 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
879 static HRESULT WINAPI XA2SUB_SetOutputVoices(IXAudio2SubmixVoice *iface,
880 const XAUDIO2_VOICE_SENDS *pSendList)
882 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
883 FAudioVoiceSends *faudio_sends;
884 HRESULT hr;
886 TRACE("%p, %p\n", This, pSendList);
888 faudio_sends = wrap_voice_sends(pSendList);
890 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
892 free_voice_sends(faudio_sends);
894 return hr;
897 static HRESULT WINAPI XA2SUB_SetEffectChain(IXAudio2SubmixVoice *iface,
898 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
900 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
901 HRESULT hr;
903 TRACE("%p, %p\n", This, pEffectChain);
905 free_effect_chain(This->effect_chain);
906 This->effect_chain = wrap_effect_chain(pEffectChain);
908 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
910 return hr;
913 static HRESULT WINAPI XA2SUB_EnableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
914 UINT32 OperationSet)
916 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
917 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
918 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
921 static HRESULT WINAPI XA2SUB_DisableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
922 UINT32 OperationSet)
924 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
925 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
926 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
929 static void WINAPI XA2SUB_GetEffectState(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
930 BOOL *pEnabled)
932 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
933 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
934 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
937 static HRESULT WINAPI XA2SUB_SetEffectParameters(IXAudio2SubmixVoice *iface,
938 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
939 UINT32 OperationSet)
941 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
942 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
943 ParametersByteSize, OperationSet);
944 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
945 pParameters, ParametersByteSize, OperationSet);
948 static HRESULT WINAPI XA2SUB_GetEffectParameters(IXAudio2SubmixVoice *iface,
949 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
951 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
952 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
953 ParametersByteSize);
954 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
955 pParameters, ParametersByteSize);
958 static HRESULT WINAPI XA2SUB_SetFilterParameters(IXAudio2SubmixVoice *iface,
959 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
961 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
962 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
963 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
964 OperationSet);
967 static void WINAPI XA2SUB_GetFilterParameters(IXAudio2SubmixVoice *iface,
968 XAUDIO2_FILTER_PARAMETERS *pParameters)
970 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
971 TRACE("%p, %p\n", This, pParameters);
972 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
975 static HRESULT WINAPI XA2SUB_SetOutputFilterParameters(IXAudio2SubmixVoice *iface,
976 IXAudio2Voice *pDestinationVoice,
977 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
979 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
980 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
982 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
984 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
985 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
988 static void WINAPI XA2SUB_GetOutputFilterParameters(IXAudio2SubmixVoice *iface,
989 IXAudio2Voice *pDestinationVoice,
990 XAUDIO2_FILTER_PARAMETERS *pParameters)
992 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
993 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
995 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
997 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
998 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1001 static HRESULT WINAPI XA2SUB_SetVolume(IXAudio2SubmixVoice *iface, float Volume,
1002 UINT32 OperationSet)
1004 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1005 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1006 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1009 static void WINAPI XA2SUB_GetVolume(IXAudio2SubmixVoice *iface, float *pVolume)
1011 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1012 TRACE("%p, %p\n", This, pVolume);
1013 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1016 static HRESULT WINAPI XA2SUB_SetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1017 const float *pVolumes, UINT32 OperationSet)
1019 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1020 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1021 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1022 pVolumes, OperationSet);
1025 static void WINAPI XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1026 float *pVolumes)
1028 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1029 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1030 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1031 pVolumes);
1034 static HRESULT WINAPI XA2SUB_SetOutputMatrix(IXAudio2SubmixVoice *iface,
1035 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1036 UINT32 DestinationChannels, const float *pLevelMatrix,
1037 UINT32 OperationSet)
1039 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1040 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1042 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1043 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1045 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1046 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1049 static void WINAPI XA2SUB_GetOutputMatrix(IXAudio2SubmixVoice *iface,
1050 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1051 UINT32 DestinationChannels, float *pLevelMatrix)
1053 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1054 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1056 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1057 SourceChannels, DestinationChannels, pLevelMatrix);
1059 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1060 SourceChannels, DestinationChannels, pLevelMatrix);
1063 static void WINAPI XA2SUB_DestroyVoice(IXAudio2SubmixVoice *iface)
1065 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1067 TRACE("%p\n", This);
1069 EnterCriticalSection(&This->lock);
1071 destroy_voice(This);
1073 LeaveCriticalSection(&This->lock);
1076 static const struct IXAudio2SubmixVoiceVtbl XAudio2SubmixVoice_Vtbl = {
1077 XA2SUB_GetVoiceDetails,
1078 XA2SUB_SetOutputVoices,
1079 XA2SUB_SetEffectChain,
1080 XA2SUB_EnableEffect,
1081 XA2SUB_DisableEffect,
1082 XA2SUB_GetEffectState,
1083 XA2SUB_SetEffectParameters,
1084 XA2SUB_GetEffectParameters,
1085 XA2SUB_SetFilterParameters,
1086 XA2SUB_GetFilterParameters,
1087 XA2SUB_SetOutputFilterParameters,
1088 XA2SUB_GetOutputFilterParameters,
1089 XA2SUB_SetVolume,
1090 XA2SUB_GetVolume,
1091 XA2SUB_SetChannelVolumes,
1092 XA2SUB_GetChannelVolumes,
1093 XA2SUB_SetOutputMatrix,
1094 XA2SUB_GetOutputMatrix,
1095 XA2SUB_DestroyVoice
1098 /* Mastering Voices */
1100 static inline XA2VoiceImpl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface)
1102 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2MasteringVoice_iface);
1105 static void WINAPI XA2M_GetVoiceDetails(IXAudio2MasteringVoice *iface,
1106 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
1108 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1109 TRACE("%p, %p\n", This, pVoiceDetails);
1110 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
1113 static HRESULT WINAPI XA2M_SetOutputVoices(IXAudio2MasteringVoice *iface,
1114 const XAUDIO2_VOICE_SENDS *pSendList)
1116 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1117 FAudioVoiceSends *faudio_sends;
1118 HRESULT hr;
1120 TRACE("%p, %p\n", This, pSendList);
1122 faudio_sends = wrap_voice_sends(pSendList);
1124 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
1126 free_voice_sends(faudio_sends);
1128 return hr;
1131 static HRESULT WINAPI XA2M_SetEffectChain(IXAudio2MasteringVoice *iface,
1132 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1134 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1135 HRESULT hr;
1137 TRACE("%p, %p\n", This, pEffectChain);
1139 free_effect_chain(This->effect_chain);
1140 This->effect_chain = wrap_effect_chain(pEffectChain);
1142 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
1144 return hr;
1147 static HRESULT WINAPI XA2M_EnableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1148 UINT32 OperationSet)
1150 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1151 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1152 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
1155 static HRESULT WINAPI XA2M_DisableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1156 UINT32 OperationSet)
1158 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1159 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1160 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
1163 static void WINAPI XA2M_GetEffectState(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1164 BOOL *pEnabled)
1166 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1167 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
1168 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
1171 static HRESULT WINAPI XA2M_SetEffectParameters(IXAudio2MasteringVoice *iface,
1172 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
1173 UINT32 OperationSet)
1175 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1176 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
1177 ParametersByteSize, OperationSet);
1178 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
1179 pParameters, ParametersByteSize, OperationSet);
1182 static HRESULT WINAPI XA2M_GetEffectParameters(IXAudio2MasteringVoice *iface,
1183 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
1185 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1186 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
1187 ParametersByteSize);
1188 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
1189 pParameters, ParametersByteSize);
1192 static HRESULT WINAPI XA2M_SetFilterParameters(IXAudio2MasteringVoice *iface,
1193 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1195 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1196 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
1197 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
1198 OperationSet);
1201 static void WINAPI XA2M_GetFilterParameters(IXAudio2MasteringVoice *iface,
1202 XAUDIO2_FILTER_PARAMETERS *pParameters)
1204 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1205 TRACE("%p, %p\n", This, pParameters);
1206 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
1209 static HRESULT WINAPI XA2M_SetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1210 IXAudio2Voice *pDestinationVoice,
1211 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1213 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1214 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1216 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
1218 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
1219 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
1222 static void WINAPI XA2M_GetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1223 IXAudio2Voice *pDestinationVoice,
1224 XAUDIO2_FILTER_PARAMETERS *pParameters)
1226 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1227 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1229 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
1231 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
1232 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1235 static HRESULT WINAPI XA2M_SetVolume(IXAudio2MasteringVoice *iface, float Volume,
1236 UINT32 OperationSet)
1238 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1239 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1240 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1243 static void WINAPI XA2M_GetVolume(IXAudio2MasteringVoice *iface, float *pVolume)
1245 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1246 TRACE("%p, %p\n", This, pVolume);
1247 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1250 static HRESULT WINAPI XA2M_SetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1251 const float *pVolumes, UINT32 OperationSet)
1253 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1254 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1255 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1256 pVolumes, OperationSet);
1259 static void WINAPI XA2M_GetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1260 float *pVolumes)
1262 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1263 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1264 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1265 pVolumes);
1268 static HRESULT WINAPI XA2M_SetOutputMatrix(IXAudio2MasteringVoice *iface,
1269 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1270 UINT32 DestinationChannels, const float *pLevelMatrix,
1271 UINT32 OperationSet)
1273 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1274 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1276 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1277 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1279 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1280 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1283 static void WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface,
1284 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1285 UINT32 DestinationChannels, float *pLevelMatrix)
1287 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1288 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1290 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1291 SourceChannels, DestinationChannels, pLevelMatrix);
1293 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1294 SourceChannels, DestinationChannels, pLevelMatrix);
1297 static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface)
1299 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1301 TRACE("%p\n", This);
1303 EnterCriticalSection(&This->lock);
1305 destroy_voice(This);
1306 pthread_mutex_lock(&This->engine_lock);
1307 This->engine_params.proc = NULL;
1308 pthread_cond_broadcast(&This->engine_ready);
1309 pthread_mutex_unlock(&This->engine_lock);
1311 WaitForSingleObject(This->engine_thread, INFINITE);
1312 This->engine_thread = NULL;
1314 LeaveCriticalSection(&This->lock);
1317 static void WINAPI XA2M_GetChannelMask(IXAudio2MasteringVoice *iface,
1318 DWORD *pChannelMask)
1320 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1322 TRACE("%p, %p\n", This, pChannelMask);
1324 FAudioMasteringVoice_GetChannelMask(This->faudio_voice, pChannelMask);
1327 static const struct IXAudio2MasteringVoiceVtbl XAudio2MasteringVoice_Vtbl = {
1328 XA2M_GetVoiceDetails,
1329 XA2M_SetOutputVoices,
1330 XA2M_SetEffectChain,
1331 XA2M_EnableEffect,
1332 XA2M_DisableEffect,
1333 XA2M_GetEffectState,
1334 XA2M_SetEffectParameters,
1335 XA2M_GetEffectParameters,
1336 XA2M_SetFilterParameters,
1337 XA2M_GetFilterParameters,
1338 XA2M_SetOutputFilterParameters,
1339 XA2M_GetOutputFilterParameters,
1340 XA2M_SetVolume,
1341 XA2M_GetVolume,
1342 XA2M_SetChannelVolumes,
1343 XA2M_GetChannelVolumes,
1344 XA2M_SetOutputMatrix,
1345 XA2M_GetOutputMatrix,
1346 XA2M_DestroyVoice,
1347 XA2M_GetChannelMask
1350 /* More Common Voice Functions */
1352 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface)
1354 if(iface->lpVtbl == (void*)&XAudio2SourceVoice_Vtbl)
1355 return impl_from_IXAudio2SourceVoice((IXAudio2SourceVoice*)iface);
1356 if(iface->lpVtbl == (void*)&XAudio2MasteringVoice_Vtbl)
1357 return impl_from_IXAudio2MasteringVoice((IXAudio2MasteringVoice*)iface);
1358 if(iface->lpVtbl == (void*)&XAudio2SubmixVoice_Vtbl)
1359 return impl_from_IXAudio2SubmixVoice((IXAudio2SubmixVoice*)iface);
1360 #if XAUDIO2_VER == 0
1361 if(iface->lpVtbl == (void*)&XAudio20SourceVoice_Vtbl)
1362 return impl_from_IXAudio20SourceVoice((IXAudio20SourceVoice*)iface);
1363 if(iface->lpVtbl == (void*)&XAudio20SubmixVoice_Vtbl)
1364 return impl_from_IXAudio20SubmixVoice((IXAudio20SubmixVoice*)iface);
1365 if(iface->lpVtbl == (void*)&XAudio20MasteringVoice_Vtbl)
1366 return impl_from_IXAudio20MasteringVoice((IXAudio20MasteringVoice*)iface);
1367 #elif XAUDIO2_VER <= 3
1368 if(iface->lpVtbl == (void*)&XAudio23SourceVoice_Vtbl)
1369 return impl_from_IXAudio23SourceVoice((IXAudio23SourceVoice*)iface);
1370 if(iface->lpVtbl == (void*)&XAudio23SubmixVoice_Vtbl)
1371 return impl_from_IXAudio23SubmixVoice((IXAudio23SubmixVoice*)iface);
1372 if(iface->lpVtbl == (void*)&XAudio23MasteringVoice_Vtbl)
1373 return impl_from_IXAudio23MasteringVoice((IXAudio23MasteringVoice*)iface);
1374 #elif XAUDIO2_VER <= 7
1375 if(iface->lpVtbl == (void*)&XAudio27SourceVoice_Vtbl)
1376 return impl_from_IXAudio27SourceVoice((IXAudio27SourceVoice*)iface);
1377 if(iface->lpVtbl == (void*)&XAudio27SubmixVoice_Vtbl)
1378 return impl_from_IXAudio27SubmixVoice((IXAudio27SubmixVoice*)iface);
1379 if(iface->lpVtbl == (void*)&XAudio27MasteringVoice_Vtbl)
1380 return impl_from_IXAudio27MasteringVoice((IXAudio27MasteringVoice*)iface);
1381 #endif
1382 ERR("invalid IXAudio2Voice pointer: %p\n", iface);
1383 return NULL;
1386 /* XAudio2 Engine Implementation */
1388 static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface)
1390 return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2_iface);
1393 static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
1394 void **ppvObject)
1396 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1398 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1400 if(IsEqualGUID(riid, &IID_IUnknown) ||
1401 #if XAUDIO2_VER == 8
1402 IsEqualGUID(riid, &IID_IXAudio28) ||
1403 #endif
1404 IsEqualGUID(riid, &IID_IXAudio2))
1405 *ppvObject = &This->IXAudio2_iface;
1406 else if(IsEqualGUID(riid, &IID_IXAudio27)){
1407 /* all xaudio versions before 28 share an IID */
1408 #if XAUDIO2_VER == 0
1409 *ppvObject = &This->IXAudio20_iface;
1410 #elif XAUDIO2_VER <= 2
1411 *ppvObject = &This->IXAudio22_iface;
1412 #elif XAUDIO2_VER <= 3
1413 *ppvObject = &This->IXAudio23_iface;
1414 #elif XAUDIO2_VER <= 7
1415 *ppvObject = &This->IXAudio27_iface;
1416 #else
1417 *ppvObject = NULL;
1418 #endif
1419 }else
1420 *ppvObject = NULL;
1422 if(*ppvObject){
1423 IUnknown_AddRef((IUnknown*)*ppvObject);
1424 return S_OK;
1427 FIXME("(%p)->(%s,%p), not found\n", This,debugstr_guid(riid), ppvObject);
1429 return E_NOINTERFACE;
1432 static ULONG WINAPI IXAudio2Impl_AddRef(IXAudio2 *iface)
1434 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1435 ULONG ref = FAudio_AddRef(This->faudio);
1436 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1437 return ref;
1440 static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
1442 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1443 ULONG ref = FAudio_Release(This->faudio);
1445 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1447 if (!ref) {
1448 XA2VoiceImpl *v, *v2;
1450 LIST_FOR_EACH_ENTRY_SAFE(v, v2, &This->voices, XA2VoiceImpl, entry){
1451 v->lock.DebugInfo->Spare[0] = 0;
1452 DeleteCriticalSection(&v->lock);
1453 HeapFree(GetProcessHeap(), 0, v);
1456 HeapFree(GetProcessHeap(), 0, This->cbs);
1458 This->lock.DebugInfo->Spare[0] = 0;
1459 DeleteCriticalSection(&This->lock);
1461 HeapFree(GetProcessHeap(), 0, This);
1463 return ref;
1466 static HRESULT WINAPI IXAudio2Impl_RegisterForCallbacks(IXAudio2 *iface,
1467 IXAudio2EngineCallback *pCallback)
1469 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1470 int i;
1472 TRACE("(%p)->(%p)\n", This, pCallback);
1474 EnterCriticalSection(&This->lock);
1476 for(i = 0; i < This->ncbs; ++i){
1477 if(!This->cbs[i] || This->cbs[i] == pCallback){
1478 This->cbs[i] = pCallback;
1479 LeaveCriticalSection(&This->lock);
1480 return S_OK;
1484 This->ncbs++;
1485 This->cbs = heap_realloc(This->cbs, This->ncbs * sizeof(*This->cbs));
1487 This->cbs[i] = pCallback;
1489 LeaveCriticalSection(&This->lock);
1491 return S_OK;
1494 static void WINAPI IXAudio2Impl_UnregisterForCallbacks(IXAudio2 *iface,
1495 IXAudio2EngineCallback *pCallback)
1497 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1498 int i;
1500 TRACE("(%p)->(%p)\n", This, pCallback);
1502 EnterCriticalSection(&This->lock);
1504 if(This->ncbs == 0){
1505 LeaveCriticalSection(&This->lock);
1506 return;
1509 for(i = 0; i < This->ncbs; ++i){
1510 if(This->cbs[i] == pCallback)
1511 break;
1514 for(; i < This->ncbs - 1 && This->cbs[i + 1]; ++i)
1515 This->cbs[i] = This->cbs[i + 1];
1517 if(i < This->ncbs)
1518 This->cbs[i] = NULL;
1520 LeaveCriticalSection(&This->lock);
1523 static inline XA2VoiceImpl *create_voice(IXAudio2Impl *This)
1525 XA2VoiceImpl *voice;
1527 voice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*voice));
1528 if(!voice)
1529 return NULL;
1531 list_add_head(&This->voices, &voice->entry);
1533 voice->IXAudio2SourceVoice_iface.lpVtbl = &XAudio2SourceVoice_Vtbl;
1534 #if XAUDIO2_VER == 0
1535 voice->IXAudio20SourceVoice_iface.lpVtbl = &XAudio20SourceVoice_Vtbl;
1536 #elif XAUDIO2_VER <= 3
1537 voice->IXAudio23SourceVoice_iface.lpVtbl = &XAudio23SourceVoice_Vtbl;
1538 #elif XAUDIO2_VER <= 7
1539 voice->IXAudio27SourceVoice_iface.lpVtbl = &XAudio27SourceVoice_Vtbl;
1540 #endif
1542 voice->IXAudio2SubmixVoice_iface.lpVtbl = &XAudio2SubmixVoice_Vtbl;
1543 #if XAUDIO2_VER == 0
1544 voice->IXAudio20SubmixVoice_iface.lpVtbl = &XAudio20SubmixVoice_Vtbl;
1545 #elif XAUDIO2_VER <= 3
1546 voice->IXAudio23SubmixVoice_iface.lpVtbl = &XAudio23SubmixVoice_Vtbl;
1547 #elif XAUDIO2_VER <= 7
1548 voice->IXAudio27SubmixVoice_iface.lpVtbl = &XAudio27SubmixVoice_Vtbl;
1549 #endif
1551 voice->FAudioVoiceCallback_vtbl = FAudioVoiceCallback_Vtbl;
1553 InitializeCriticalSection(&voice->lock);
1554 voice->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2VoiceImpl.lock");
1556 return voice;
1559 static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
1560 IXAudio2SourceVoice **ppSourceVoice, const WAVEFORMATEX *pSourceFormat,
1561 UINT32 flags, float maxFrequencyRatio,
1562 IXAudio2VoiceCallback *pCallback, const XAUDIO2_VOICE_SENDS *pSendList,
1563 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1565 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1566 XA2VoiceImpl *src;
1567 HRESULT hr;
1568 FAudioVoiceSends *faudio_sends;
1570 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This, ppSourceVoice,
1571 pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
1572 pEffectChain);
1574 EnterCriticalSection(&This->lock);
1576 LIST_FOR_EACH_ENTRY(src, &This->voices, XA2VoiceImpl, entry){
1577 EnterCriticalSection(&src->lock);
1578 if(!src->in_use)
1579 break;
1580 LeaveCriticalSection(&src->lock);
1583 if(&src->entry == &This->voices){
1584 src = create_voice(This);
1585 EnterCriticalSection(&src->lock);
1588 LeaveCriticalSection(&This->lock);
1590 src->effect_chain = wrap_effect_chain(pEffectChain);
1591 faudio_sends = wrap_voice_sends(pSendList);
1593 hr = FAudio_CreateSourceVoice(This->faudio, &src->faudio_voice,
1594 (FAudioWaveFormatEx*)pSourceFormat, flags, maxFrequencyRatio,
1595 &src->FAudioVoiceCallback_vtbl, faudio_sends,
1596 src->effect_chain);
1597 free_voice_sends(faudio_sends);
1598 if(FAILED(hr)){
1599 LeaveCriticalSection(&This->lock);
1600 return hr;
1602 src->in_use = TRUE;
1603 src->cb = pCallback;
1605 LeaveCriticalSection(&src->lock);
1607 #if XAUDIO2_VER == 0
1608 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio20SourceVoice_iface;
1609 #elif XAUDIO2_VER <= 3
1610 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio23SourceVoice_iface;
1611 #elif XAUDIO2_VER <= 7
1612 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio27SourceVoice_iface;
1613 #else
1614 *ppSourceVoice = &src->IXAudio2SourceVoice_iface;
1615 #endif
1617 TRACE("Created source voice: %p\n", src);
1619 return S_OK;
1622 static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
1623 IXAudio2SubmixVoice **ppSubmixVoice, UINT32 inputChannels,
1624 UINT32 inputSampleRate, UINT32 flags, UINT32 processingStage,
1625 const XAUDIO2_VOICE_SENDS *pSendList,
1626 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1628 HRESULT hr;
1629 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1630 XA2VoiceImpl *sub;
1631 FAudioVoiceSends *faudio_sends;
1633 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This, ppSubmixVoice,
1634 inputChannels, inputSampleRate, flags, processingStage, pSendList,
1635 pEffectChain);
1637 EnterCriticalSection(&This->lock);
1639 LIST_FOR_EACH_ENTRY(sub, &This->voices, XA2VoiceImpl, entry){
1640 EnterCriticalSection(&sub->lock);
1641 if(!sub->in_use)
1642 break;
1643 LeaveCriticalSection(&sub->lock);
1646 if(&sub->entry == &This->voices){
1647 sub = create_voice(This);
1648 EnterCriticalSection(&sub->lock);
1651 LeaveCriticalSection(&This->lock);
1653 sub->effect_chain = wrap_effect_chain(pEffectChain);
1654 faudio_sends = wrap_voice_sends(pSendList);
1656 hr = FAudio_CreateSubmixVoice(This->faudio, &sub->faudio_voice, inputChannels,
1657 inputSampleRate, flags, processingStage, faudio_sends,
1658 sub->effect_chain);
1659 free_voice_sends(faudio_sends);
1660 if(FAILED(hr)){
1661 LeaveCriticalSection(&sub->lock);
1662 return hr;
1664 sub->in_use = TRUE;
1666 LeaveCriticalSection(&sub->lock);
1668 #if XAUDIO2_VER == 0
1669 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio20SubmixVoice_iface;
1670 #elif XAUDIO2_VER <= 3
1671 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio23SubmixVoice_iface;
1672 #elif XAUDIO2_VER <= 7
1673 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio27SubmixVoice_iface;
1674 #else
1675 *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
1676 #endif
1678 TRACE("Created submix voice: %p\n", sub);
1680 return S_OK;
1683 /* called thread created by SDL, must not access Wine TEB */
1684 void engine_cb(FAudioEngineCallEXT proc, FAudio *faudio, float *stream, void *user)
1686 XA2VoiceImpl *This = user;
1688 pthread_mutex_lock(&This->engine_lock);
1690 This->engine_params.proc = proc;
1691 This->engine_params.stream = stream;
1692 This->engine_params.faudio = faudio;
1694 pthread_cond_broadcast(&This->engine_ready);
1696 while(This->engine_params.proc)
1697 pthread_cond_wait(&This->engine_done, &This->engine_lock);
1699 pthread_mutex_unlock(&This->engine_lock);
1702 /* wine thread, OK to access TEB, invoke client code, etc */
1703 DWORD WINAPI engine_thread(void *user)
1705 XA2VoiceImpl *This = user;
1707 pthread_mutex_lock(&This->engine_lock);
1709 pthread_cond_broadcast(&This->engine_done);
1712 pthread_cond_wait(&This->engine_ready, &This->engine_lock);
1714 if(This->engine_params.proc){
1715 This->engine_params.proc(This->engine_params.faudio, This->engine_params.stream);
1716 This->engine_params.proc = NULL;
1717 pthread_cond_broadcast(&This->engine_done);
1719 }while(This->in_use);
1721 pthread_mutex_unlock(&This->engine_lock);
1723 return 0;
1726 static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
1727 IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels,
1728 UINT32 inputSampleRate, UINT32 flags, const WCHAR *deviceId,
1729 const XAUDIO2_EFFECT_CHAIN *pEffectChain,
1730 AUDIO_STREAM_CATEGORY streamCategory)
1732 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1734 TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This,
1735 ppMasteringVoice, inputChannels, inputSampleRate, flags,
1736 wine_dbgstr_w(deviceId), pEffectChain, streamCategory);
1738 EnterCriticalSection(&This->lock);
1740 /* Note that we don't have paths for each XAUDIO2_VER here.
1741 * All versions < 8 have a very different CreateMasteringVoice, so we
1742 * implement those separately in compat.c.
1743 * -flibit
1745 *ppMasteringVoice = &This->mst.IXAudio2MasteringVoice_iface;
1747 EnterCriticalSection(&This->mst.lock);
1749 if(This->mst.in_use){
1750 LeaveCriticalSection(&This->mst.lock);
1751 LeaveCriticalSection(&This->lock);
1752 return COMPAT_E_INVALID_CALL;
1755 LeaveCriticalSection(&This->lock);
1757 This->mst.effect_chain = wrap_effect_chain(pEffectChain);
1759 pthread_mutex_lock(&This->mst.engine_lock);
1761 This->mst.engine_thread = CreateThread(NULL, 0, &engine_thread, &This->mst, 0, NULL);
1763 pthread_cond_wait(&This->mst.engine_done, &This->mst.engine_lock);
1765 pthread_mutex_unlock(&This->mst.engine_lock);
1767 FAudio_SetEngineProcedureEXT(This->faudio, &engine_cb, &This->mst);
1769 FAudio_CreateMasteringVoice8(This->faudio, &This->mst.faudio_voice, inputChannels,
1770 inputSampleRate, flags, NULL /* TODO: (uint16_t*)deviceId */,
1771 This->mst.effect_chain, (FAudioStreamCategory)streamCategory);
1773 This->mst.in_use = TRUE;
1775 LeaveCriticalSection(&This->mst.lock);
1777 return S_OK;
1780 static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
1782 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1784 TRACE("(%p)->()\n", This);
1786 return FAudio_StartEngine(This->faudio);
1789 static void WINAPI IXAudio2Impl_StopEngine(IXAudio2 *iface)
1791 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1793 TRACE("(%p)->()\n", This);
1795 FAudio_StopEngine(This->faudio);
1798 static HRESULT WINAPI IXAudio2Impl_CommitChanges(IXAudio2 *iface,
1799 UINT32 operationSet)
1801 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1803 TRACE("(%p)->(0x%x)\n", This, operationSet);
1805 #ifdef HAVE_FAUDIO_COMMITOPERATIONSET
1806 return FAudio_CommitOperationSet(This->faudio, operationSet);
1807 #else
1808 return FAudio_CommitChanges(This->faudio);
1809 #endif
1812 static void WINAPI IXAudio2Impl_GetPerformanceData(IXAudio2 *iface,
1813 XAUDIO2_PERFORMANCE_DATA *pPerfData)
1815 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1817 TRACE("(%p)->(%p)\n", This, pPerfData);
1819 FAudio_GetPerformanceData(This->faudio, (FAudioPerformanceData *)pPerfData);
1822 static void WINAPI IXAudio2Impl_SetDebugConfiguration(IXAudio2 *iface,
1823 const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
1824 void *pReserved)
1826 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1828 TRACE("(%p)->(%p, %p)\n", This, pDebugConfiguration, pReserved);
1830 FAudio_SetDebugConfiguration(This->faudio, (FAudioDebugConfiguration *)pDebugConfiguration, pReserved);
1833 /* XAudio2 2.8 */
1834 static const IXAudio2Vtbl XAudio2_Vtbl =
1836 IXAudio2Impl_QueryInterface,
1837 IXAudio2Impl_AddRef,
1838 IXAudio2Impl_Release,
1839 IXAudio2Impl_RegisterForCallbacks,
1840 IXAudio2Impl_UnregisterForCallbacks,
1841 IXAudio2Impl_CreateSourceVoice,
1842 IXAudio2Impl_CreateSubmixVoice,
1843 IXAudio2Impl_CreateMasteringVoice,
1844 IXAudio2Impl_StartEngine,
1845 IXAudio2Impl_StopEngine,
1846 IXAudio2Impl_CommitChanges,
1847 IXAudio2Impl_GetPerformanceData,
1848 IXAudio2Impl_SetDebugConfiguration
1851 /* XAudio2 ClassFactory */
1853 struct xaudio2_cf {
1854 IClassFactory IClassFactory_iface;
1855 LONG ref;
1858 static struct xaudio2_cf *impl_from_IClassFactory(IClassFactory *iface)
1860 return CONTAINING_RECORD(iface, struct xaudio2_cf, IClassFactory_iface);
1863 static HRESULT WINAPI XAudio2CF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1865 if(IsEqualGUID(riid, &IID_IUnknown)
1866 || IsEqualGUID(riid, &IID_IClassFactory))
1868 IClassFactory_AddRef(iface);
1869 *ppobj = iface;
1870 return S_OK;
1873 *ppobj = NULL;
1874 WARN("(%p)->(%s, %p): interface not found\n", iface, debugstr_guid(riid), ppobj);
1875 return E_NOINTERFACE;
1878 static ULONG WINAPI XAudio2CF_AddRef(IClassFactory *iface)
1880 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1881 ULONG ref = InterlockedIncrement(&This->ref);
1882 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1883 return ref;
1886 static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
1888 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1889 ULONG ref = InterlockedDecrement(&This->ref);
1890 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1891 if (!ref)
1892 HeapFree(GetProcessHeap(), 0, This);
1893 return ref;
1896 static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1897 REFIID riid, void **ppobj)
1899 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1900 HRESULT hr;
1901 IXAudio2Impl *object;
1903 TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
1905 *ppobj = NULL;
1907 if(pOuter)
1908 return CLASS_E_NOAGGREGATION;
1910 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1911 if(!object)
1912 return E_OUTOFMEMORY;
1914 object->IXAudio2_iface.lpVtbl = &XAudio2_Vtbl;
1916 #if XAUDIO2_VER == 0
1917 object->IXAudio20_iface.lpVtbl = &XAudio20_Vtbl;
1918 #elif XAUDIO2_VER <= 2
1919 object->IXAudio22_iface.lpVtbl = &XAudio22_Vtbl;
1920 #elif XAUDIO2_VER <= 3
1921 object->IXAudio23_iface.lpVtbl = &XAudio23_Vtbl;
1922 #elif XAUDIO2_VER <= 7
1923 object->IXAudio27_iface.lpVtbl = &XAudio27_Vtbl;
1924 #endif
1926 object->mst.IXAudio2MasteringVoice_iface.lpVtbl = &XAudio2MasteringVoice_Vtbl;
1928 #if XAUDIO2_VER == 0
1929 object->mst.IXAudio20MasteringVoice_iface.lpVtbl = &XAudio20MasteringVoice_Vtbl;
1930 #elif XAUDIO2_VER <= 3
1931 object->mst.IXAudio23MasteringVoice_iface.lpVtbl = &XAudio23MasteringVoice_Vtbl;
1932 #elif XAUDIO2_VER <= 7
1933 object->mst.IXAudio27MasteringVoice_iface.lpVtbl = &XAudio27MasteringVoice_Vtbl;
1934 #endif
1936 object->FAudioEngineCallback_vtbl = FAudioEngineCallback_Vtbl;
1938 list_init(&object->voices);
1940 InitializeCriticalSection(&object->lock);
1941 object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IXAudio2Impl.lock");
1943 InitializeCriticalSection(&object->mst.lock);
1944 object->mst.lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2MasteringVoice.lock");
1946 pthread_mutex_init(&object->mst.engine_lock, NULL);
1947 pthread_cond_init(&object->mst.engine_done, NULL);
1948 pthread_cond_init(&object->mst.engine_ready, NULL);
1950 FAudioCOMConstructWithCustomAllocatorEXT(
1951 &object->faudio,
1952 XAUDIO2_VER,
1953 XAudio_Internal_Malloc,
1954 XAudio_Internal_Free,
1955 XAudio_Internal_Realloc
1958 FAudio_RegisterForCallbacks(object->faudio, &object->FAudioEngineCallback_vtbl);
1960 hr = IXAudio2_QueryInterface(&object->IXAudio2_iface, riid, ppobj);
1961 IXAudio2_Release(&object->IXAudio2_iface);
1962 if(FAILED(hr)){
1963 return hr;
1966 TRACE("Created XAudio version %u: %p\n", 20 + XAUDIO2_VER, object);
1968 return hr;
1971 static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock)
1973 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1974 FIXME("(%p)->(%d): stub!\n", This, dolock);
1975 return S_OK;
1978 static const IClassFactoryVtbl XAudio2CF_Vtbl =
1980 XAudio2CF_QueryInterface,
1981 XAudio2CF_AddRef,
1982 XAudio2CF_Release,
1983 XAudio2CF_CreateInstance,
1984 XAudio2CF_LockServer
1987 /* Engine Generators */
1989 static inline HRESULT make_xaudio2_factory(REFIID riid, void **ppv)
1991 HRESULT hr;
1992 struct xaudio2_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
1993 ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
1994 ret->ref = 0;
1995 hr = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
1996 if(FAILED(hr))
1997 HeapFree(GetProcessHeap(), 0, ret);
1998 return hr;
2001 HRESULT xaudio2_initialize(IXAudio2Impl *This, UINT32 flags, XAUDIO2_PROCESSOR proc)
2003 if(proc != XAUDIO2_ANY_PROCESSOR)
2004 WARN("Processor affinity not implemented in FAudio\n");
2005 return FAudio_Initialize(This->faudio, flags, FAUDIO_DEFAULT_PROCESSOR);
2008 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
2010 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
2012 if(IsEqualGUID(rclsid, &CLSID_XAudio20) ||
2013 IsEqualGUID(rclsid, &CLSID_XAudio21) ||
2014 IsEqualGUID(rclsid, &CLSID_XAudio22) ||
2015 IsEqualGUID(rclsid, &CLSID_XAudio23) ||
2016 IsEqualGUID(rclsid, &CLSID_XAudio24) ||
2017 IsEqualGUID(rclsid, &CLSID_XAudio25) ||
2018 IsEqualGUID(rclsid, &CLSID_XAudio26) ||
2019 IsEqualGUID(rclsid, &CLSID_XAudio27))
2020 return make_xaudio2_factory(riid, ppv);
2022 if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter20) ||
2023 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter21) ||
2024 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter22) ||
2025 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter23) ||
2026 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter24) ||
2027 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter25) ||
2028 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter26) ||
2029 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter27))
2030 return make_xapo_factory(&CLSID_AudioVolumeMeter27, riid, ppv);
2032 if(IsEqualGUID(rclsid, &CLSID_AudioReverb20) ||
2033 IsEqualGUID(rclsid, &CLSID_AudioReverb21) ||
2034 IsEqualGUID(rclsid, &CLSID_AudioReverb22) ||
2035 IsEqualGUID(rclsid, &CLSID_AudioReverb23) ||
2036 IsEqualGUID(rclsid, &CLSID_AudioReverb24) ||
2037 IsEqualGUID(rclsid, &CLSID_AudioReverb25) ||
2038 IsEqualGUID(rclsid, &CLSID_AudioReverb26) ||
2039 IsEqualGUID(rclsid, &CLSID_AudioReverb27))
2040 return make_xapo_factory(&CLSID_AudioReverb27, riid, ppv);
2042 return CLASS_E_CLASSNOTAVAILABLE;
2045 #if XAUDIO2_VER >= 8
2046 HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR proc)
2048 HRESULT hr;
2049 IXAudio2 *xa2;
2050 IClassFactory *cf;
2052 TRACE("%p 0x%x 0x%x\n", ppxa2, flags, proc);
2054 hr = make_xaudio2_factory(&IID_IClassFactory, (void**)&cf);
2055 if(FAILED(hr))
2056 return hr;
2058 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IXAudio2, (void**)&xa2);
2059 IClassFactory_Release(cf);
2060 if(FAILED(hr))
2061 return hr;
2063 hr = xaudio2_initialize(impl_from_IXAudio2(xa2), flags, proc);
2064 if(FAILED(hr)){
2065 IXAudio2_Release(xa2);
2066 return hr;
2069 *ppxa2 = xa2;
2071 return S_OK;
2074 HRESULT WINAPI CreateAudioVolumeMeter(IUnknown **out)
2076 IClassFactory *cf;
2077 HRESULT hr;
2079 TRACE("%p\n", out);
2081 hr = make_xapo_factory(&CLSID_AudioVolumeMeter27, &IID_IClassFactory, (void**)&cf);
2082 if(FAILED(hr))
2083 return hr;
2085 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
2087 IClassFactory_Release(cf);
2089 return hr;
2092 HRESULT WINAPI CreateAudioReverb(IUnknown **out)
2094 IClassFactory *cf;
2095 HRESULT hr;
2097 TRACE("%p\n", out);
2099 hr = make_xapo_factory(&CLSID_AudioReverb27, &IID_IClassFactory, (void**)&cf);
2100 if(FAILED(hr))
2101 return hr;
2103 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
2105 IClassFactory_Release(cf);
2107 return hr;
2109 #endif /* XAUDIO2_VER >= 8 */