Release 6.15.
[wine.git] / dlls / xaudio2_7 / xaudio_dll.c
blobc9f5dd2f48e758c2054e64e8359b90949795f61f
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 XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface);
82 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved)
84 TRACE("(%p, %d, %p)\n", hinstDLL, reason, pReserved);
86 switch (reason)
88 case DLL_PROCESS_ATTACH:
89 DisableThreadLibraryCalls( hinstDLL );
90 #ifdef HAVE_FAUDIOLINKEDVERSION
91 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
92 #endif
93 break;
95 return TRUE;
98 /* Effect Wrapping */
100 static inline XA2XAPOImpl *impl_from_FAPO(FAPO *iface)
102 return CONTAINING_RECORD(iface, XA2XAPOImpl, FAPO_vtbl);
105 static int32_t FAPOCALL XAPO_AddRef(void *iface)
107 XA2XAPOImpl *This = impl_from_FAPO(iface);
108 TRACE("%p\n", This);
109 return InterlockedIncrement(&This->ref);
112 static int32_t FAPOCALL XAPO_Release(void *iface)
114 int32_t r;
115 XA2XAPOImpl *This = impl_from_FAPO(iface);
116 TRACE("%p\n", This);
117 r = InterlockedDecrement(&This->ref);
118 if(r == 0){
119 IXAPO_Release(This->xapo);
120 if(This->xapo_params)
121 IXAPOParameters_Release(This->xapo_params);
122 heap_free(This);
124 return r;
127 static uint32_t FAPOCALL XAPO_GetRegistrationProperties(void *iface,
128 FAPORegistrationProperties **ppRegistrationProperties)
130 XA2XAPOImpl *This = impl_from_FAPO(iface);
131 XAPO_REGISTRATION_PROPERTIES *xprops;
132 HRESULT hr;
134 TRACE("%p\n", This);
136 hr = IXAPO_GetRegistrationProperties(This->xapo, &xprops);
137 if(FAILED(hr))
138 return hr;
140 /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
141 *ppRegistrationProperties = (FAPORegistrationProperties*) xprops;
142 return 0;
145 static uint32_t FAPOCALL XAPO_IsInputFormatSupported(void *iface,
146 const FAudioWaveFormatEx *pOutputFormat, const FAudioWaveFormatEx *pRequestedInputFormat,
147 FAudioWaveFormatEx **ppSupportedInputFormat)
149 XA2XAPOImpl *This = impl_from_FAPO(iface);
150 TRACE("%p\n", This);
151 return IXAPO_IsInputFormatSupported(This->xapo, (const WAVEFORMATEX*)pOutputFormat,
152 (const WAVEFORMATEX*)pRequestedInputFormat, (WAVEFORMATEX**)ppSupportedInputFormat);
155 static uint32_t FAPOCALL XAPO_IsOutputFormatSupported(void *iface,
156 const FAudioWaveFormatEx *pInputFormat, const FAudioWaveFormatEx *pRequestedOutputFormat,
157 FAudioWaveFormatEx **ppSupportedOutputFormat)
159 XA2XAPOImpl *This = impl_from_FAPO(iface);
160 TRACE("%p\n", This);
161 return IXAPO_IsOutputFormatSupported(This->xapo, (const WAVEFORMATEX *)pInputFormat,
162 (const WAVEFORMATEX *)pRequestedOutputFormat, (WAVEFORMATEX**)ppSupportedOutputFormat);
165 static uint32_t FAPOCALL XAPO_Initialize(void *iface, const void *pData,
166 uint32_t DataByteSize)
168 XA2XAPOImpl *This = impl_from_FAPO(iface);
169 TRACE("%p\n", This);
170 return IXAPO_Initialize(This->xapo, pData, DataByteSize);
173 static void FAPOCALL XAPO_Reset(void *iface)
175 XA2XAPOImpl *This = impl_from_FAPO(iface);
176 TRACE("%p\n", This);
177 IXAPO_Reset(This->xapo);
180 static uint32_t FAPOCALL XAPO_LockForProcess(void *iface,
181 uint32_t InputLockedParameterCount,
182 const FAPOLockForProcessBufferParameters *pInputLockedParameters,
183 uint32_t OutputLockedParameterCount,
184 const FAPOLockForProcessBufferParameters *pOutputLockedParameters)
186 XA2XAPOImpl *This = impl_from_FAPO(iface);
187 TRACE("%p\n", This);
188 return IXAPO_LockForProcess(This->xapo,
189 InputLockedParameterCount,
190 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pInputLockedParameters,
191 OutputLockedParameterCount,
192 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pOutputLockedParameters);
195 static void FAPOCALL XAPO_UnlockForProcess(void *iface)
197 XA2XAPOImpl *This = impl_from_FAPO(iface);
198 TRACE("%p\n", This);
199 IXAPO_UnlockForProcess(This->xapo);
202 static void FAPOCALL XAPO_Process(void *iface,
203 uint32_t InputProcessParameterCount,
204 const FAPOProcessBufferParameters* pInputProcessParameters,
205 uint32_t OutputProcessParameterCount,
206 FAPOProcessBufferParameters* pOutputProcessParameters,
207 int32_t IsEnabled)
209 XA2XAPOImpl *This = impl_from_FAPO(iface);
210 TRACE("%p\n", This);
211 IXAPO_Process(This->xapo, InputProcessParameterCount,
212 (const XAPO_PROCESS_BUFFER_PARAMETERS *)pInputProcessParameters,
213 OutputProcessParameterCount,
214 (XAPO_PROCESS_BUFFER_PARAMETERS *)pOutputProcessParameters,
215 IsEnabled);
218 static uint32_t FAPOCALL XAPO_CalcInputFrames(void *iface,
219 uint32_t OutputFrameCount)
221 XA2XAPOImpl *This = impl_from_FAPO(iface);
222 TRACE("%p\n", This);
223 return IXAPO_CalcInputFrames(This->xapo, OutputFrameCount);
226 static uint32_t FAPOCALL XAPO_CalcOutputFrames(void *iface,
227 uint32_t InputFrameCount)
229 XA2XAPOImpl *This = impl_from_FAPO(iface);
230 TRACE("%p\n", This);
231 return IXAPO_CalcOutputFrames(This->xapo, InputFrameCount);
234 static void FAPOCALL XAPO_SetParameters(void *iface,
235 const void *pParameters, uint32_t ParametersByteSize)
237 XA2XAPOImpl *This = impl_from_FAPO(iface);
238 TRACE("%p\n", This);
239 if(This->xapo_params)
240 IXAPOParameters_SetParameters(This->xapo_params, pParameters, ParametersByteSize);
243 static void FAPOCALL XAPO_GetParameters(void *iface,
244 void *pParameters, uint32_t ParametersByteSize)
246 XA2XAPOImpl *This = impl_from_FAPO(iface);
247 TRACE("%p\n", This);
248 if(This->xapo_params)
249 IXAPOParameters_GetParameters(This->xapo_params, pParameters, ParametersByteSize);
250 else
251 memset(pParameters, 0, ParametersByteSize);
254 static const FAPO FAPO_Vtbl = {
255 XAPO_AddRef,
256 XAPO_Release,
257 XAPO_GetRegistrationProperties,
258 XAPO_IsInputFormatSupported,
259 XAPO_IsOutputFormatSupported,
260 XAPO_Initialize,
261 XAPO_Reset,
262 XAPO_LockForProcess,
263 XAPO_UnlockForProcess,
264 XAPO_Process,
265 XAPO_CalcInputFrames,
266 XAPO_CalcOutputFrames,
267 XAPO_SetParameters,
268 XAPO_GetParameters,
271 static XA2XAPOImpl *wrap_xapo(IUnknown *unk)
273 XA2XAPOImpl *ret;
274 IXAPO *xapo;
275 IXAPOParameters *xapo_params;
276 HRESULT hr;
278 #if XAUDIO2_VER <= 7
279 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27, (void**)&xapo);
280 #else
281 hr = IUnknown_QueryInterface(unk, &IID_IXAPO, (void**)&xapo);
282 #endif
283 if(FAILED(hr)){
284 WARN("XAPO doesn't support IXAPO? %p\n", unk);
285 return NULL;
288 #if XAUDIO2_VER <= 7
289 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27Parameters, (void**)&xapo_params);
290 #else
291 hr = IUnknown_QueryInterface(unk, &IID_IXAPOParameters, (void**)&xapo_params);
292 #endif
293 if(FAILED(hr)){
294 TRACE("XAPO doesn't support IXAPOParameters %p\n", unk);
295 xapo_params = NULL;
298 ret = heap_alloc(sizeof(*ret));
300 ret->xapo = xapo;
301 ret->xapo_params = xapo_params;
302 ret->FAPO_vtbl = FAPO_Vtbl;
303 ret->ref = 1;
305 TRACE("wrapped IXAPO %p with %p\n", xapo, ret);
307 return ret;
310 FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
312 FAudioEffectChain *ret;
313 int i;
315 if(!pEffectChain)
316 return NULL;
318 ret = heap_alloc(sizeof(*ret) + sizeof(FAudioEffectDescriptor) * pEffectChain->EffectCount);
320 ret->EffectCount = pEffectChain->EffectCount;
321 ret->pEffectDescriptors = (void*)(ret + 1);
323 for(i = 0; i < ret->EffectCount; ++i){
324 ret->pEffectDescriptors[i].pEffect = &wrap_xapo(pEffectChain->pEffectDescriptors[i].pEffect)->FAPO_vtbl;
325 ret->pEffectDescriptors[i].InitialState = pEffectChain->pEffectDescriptors[i].InitialState;
326 ret->pEffectDescriptors[i].OutputChannels = pEffectChain->pEffectDescriptors[i].OutputChannels;
329 return ret;
332 static void free_effect_chain(FAudioEffectChain *chain)
334 int i;
335 if(!chain)
336 return;
337 for(i = 0; i < chain->EffectCount; ++i)
338 XAPO_Release(chain->pEffectDescriptors[i].pEffect);
339 heap_free(chain);
342 /* Send Wrapping */
344 static FAudioVoiceSends *wrap_voice_sends(const XAUDIO2_VOICE_SENDS *sends)
346 FAudioVoiceSends *ret;
347 int i;
349 if(!sends)
350 return NULL;
352 ret = heap_alloc(sizeof(*ret) + sends->SendCount * sizeof(FAudioSendDescriptor));
353 ret->SendCount = sends->SendCount;
354 ret->pSends = (FAudioSendDescriptor*)(ret + 1);
355 for(i = 0; i < sends->SendCount; ++i){
356 XA2VoiceImpl *voice = impl_from_IXAudio2Voice(sends->pSends[i].pOutputVoice);
357 ret->pSends[i].pOutputVoice = voice->faudio_voice;
358 ret->pSends[i].Flags = sends->pSends[i].Flags;
360 return ret;
363 static void free_voice_sends(FAudioVoiceSends *sends)
365 if(!sends)
366 return;
367 heap_free(sends);
370 /* Voice Callbacks */
372 static inline XA2VoiceImpl *impl_from_FAudioVoiceCallback(FAudioVoiceCallback *iface)
374 return CONTAINING_RECORD(iface, XA2VoiceImpl, FAudioVoiceCallback_vtbl);
377 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassStart(FAudioVoiceCallback *iface,
378 UINT32 BytesRequired)
380 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
381 TRACE("%p\n", This);
382 if(This->cb)
383 #if XAUDIO2_VER == 0
384 IXAudio20VoiceCallback_OnVoiceProcessingPassStart((IXAudio20VoiceCallback*)This->cb);
385 #else
386 IXAudio2VoiceCallback_OnVoiceProcessingPassStart(This->cb, BytesRequired);
387 #endif
390 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassEnd(FAudioVoiceCallback *iface)
392 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
393 TRACE("%p\n", This);
394 if(This->cb)
395 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(This->cb);
398 static void FAUDIOCALL XA2VCB_OnStreamEnd(FAudioVoiceCallback *iface)
400 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
401 TRACE("%p\n", This);
402 if(This->cb)
403 IXAudio2VoiceCallback_OnStreamEnd(This->cb);
406 static void FAUDIOCALL XA2VCB_OnBufferStart(FAudioVoiceCallback *iface,
407 void *pBufferContext)
409 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
410 TRACE("%p\n", This);
411 if(This->cb)
412 IXAudio2VoiceCallback_OnBufferStart(This->cb, pBufferContext);
415 static void FAUDIOCALL XA2VCB_OnBufferEnd(FAudioVoiceCallback *iface,
416 void *pBufferContext)
418 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
419 TRACE("%p\n", This);
420 if(This->cb)
421 IXAudio2VoiceCallback_OnBufferEnd(This->cb, pBufferContext);
424 static void FAUDIOCALL XA2VCB_OnLoopEnd(FAudioVoiceCallback *iface,
425 void *pBufferContext)
427 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
428 TRACE("%p\n", This);
429 if(This->cb)
430 IXAudio2VoiceCallback_OnLoopEnd(This->cb, pBufferContext);
433 static void FAUDIOCALL XA2VCB_OnVoiceError(FAudioVoiceCallback *iface,
434 void *pBufferContext, unsigned int Error)
436 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
437 TRACE("%p\n", This);
438 if(This->cb)
439 IXAudio2VoiceCallback_OnVoiceError(This->cb, pBufferContext, (HRESULT)Error);
442 static const FAudioVoiceCallback FAudioVoiceCallback_Vtbl = {
443 XA2VCB_OnBufferEnd,
444 XA2VCB_OnBufferStart,
445 XA2VCB_OnLoopEnd,
446 XA2VCB_OnStreamEnd,
447 XA2VCB_OnVoiceError,
448 XA2VCB_OnVoiceProcessingPassEnd,
449 XA2VCB_OnVoiceProcessingPassStart
452 /* Engine Callbacks */
454 static inline IXAudio2Impl *impl_from_FAudioEngineCallback(FAudioEngineCallback *iface)
456 return CONTAINING_RECORD(iface, IXAudio2Impl, FAudioEngineCallback_vtbl);
459 static void FAUDIOCALL XA2ECB_OnProcessingPassStart(FAudioEngineCallback *iface)
461 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
462 int i;
463 TRACE("%p\n", This);
464 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
465 IXAudio2EngineCallback_OnProcessingPassStart(This->cbs[i]);
468 static void FAUDIOCALL XA2ECB_OnProcessingPassEnd(FAudioEngineCallback *iface)
470 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
471 int i;
472 TRACE("%p\n", This);
473 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
474 IXAudio2EngineCallback_OnProcessingPassEnd(This->cbs[i]);
477 static void FAUDIOCALL XA2ECB_OnCriticalError(FAudioEngineCallback *iface,
478 uint32_t error)
480 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
481 int i;
482 TRACE("%p\n", This);
483 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
484 IXAudio2EngineCallback_OnCriticalError(This->cbs[i], error);
487 static const FAudioEngineCallback FAudioEngineCallback_Vtbl = {
488 XA2ECB_OnCriticalError,
489 XA2ECB_OnProcessingPassEnd,
490 XA2ECB_OnProcessingPassStart
493 /* Common Voice Functions */
495 static inline void destroy_voice(XA2VoiceImpl *This)
497 FAudioVoice_DestroyVoice(This->faudio_voice);
498 free_effect_chain(This->effect_chain);
499 This->effect_chain = NULL;
500 This->in_use = FALSE;
503 /* Source Voices */
505 static inline XA2VoiceImpl *impl_from_IXAudio2SourceVoice(IXAudio2SourceVoice *iface)
507 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SourceVoice_iface);
510 static void WINAPI XA2SRC_GetVoiceDetails(IXAudio2SourceVoice *iface,
511 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
513 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
514 TRACE("%p, %p\n", This, pVoiceDetails);
515 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
518 static HRESULT WINAPI XA2SRC_SetOutputVoices(IXAudio2SourceVoice *iface,
519 const XAUDIO2_VOICE_SENDS *pSendList)
521 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
522 FAudioVoiceSends *faudio_sends;
523 HRESULT hr;
525 TRACE("%p, %p\n", This, pSendList);
527 faudio_sends = wrap_voice_sends(pSendList);
529 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
531 free_voice_sends(faudio_sends);
533 return hr;
536 static HRESULT WINAPI XA2SRC_SetEffectChain(IXAudio2SourceVoice *iface,
537 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
539 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
540 HRESULT hr;
542 TRACE("%p, %p\n", This, pEffectChain);
544 free_effect_chain(This->effect_chain);
545 This->effect_chain = wrap_effect_chain(pEffectChain);
547 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
549 return hr;
552 static HRESULT WINAPI XA2SRC_EnableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
553 UINT32 OperationSet)
555 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
556 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
557 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
560 static HRESULT WINAPI XA2SRC_DisableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
561 UINT32 OperationSet)
563 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
564 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
565 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
568 static void WINAPI XA2SRC_GetEffectState(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
569 BOOL *pEnabled)
571 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
572 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
573 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
576 static HRESULT WINAPI XA2SRC_SetEffectParameters(IXAudio2SourceVoice *iface,
577 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
578 UINT32 OperationSet)
580 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
581 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
582 ParametersByteSize, OperationSet);
583 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
584 pParameters, ParametersByteSize, OperationSet);
587 static HRESULT WINAPI XA2SRC_GetEffectParameters(IXAudio2SourceVoice *iface,
588 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
590 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
591 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
592 ParametersByteSize);
593 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
594 pParameters, ParametersByteSize);
597 static HRESULT WINAPI XA2SRC_SetFilterParameters(IXAudio2SourceVoice *iface,
598 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
600 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
601 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
602 return FAudioVoice_SetFilterParameters(This->faudio_voice,
603 (const FAudioFilterParameters *)pParameters, OperationSet);
606 static void WINAPI XA2SRC_GetFilterParameters(IXAudio2SourceVoice *iface,
607 XAUDIO2_FILTER_PARAMETERS *pParameters)
609 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
610 TRACE("%p, %p\n", This, pParameters);
611 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
614 static HRESULT WINAPI XA2SRC_SetOutputFilterParameters(IXAudio2SourceVoice *iface,
615 IXAudio2Voice *pDestinationVoice,
616 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
618 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
619 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
621 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
623 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
624 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
627 static void WINAPI XA2SRC_GetOutputFilterParameters(IXAudio2SourceVoice *iface,
628 IXAudio2Voice *pDestinationVoice,
629 XAUDIO2_FILTER_PARAMETERS *pParameters)
631 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
632 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
634 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
636 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
637 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
640 static HRESULT WINAPI XA2SRC_SetVolume(IXAudio2SourceVoice *iface, float Volume,
641 UINT32 OperationSet)
643 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
644 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
645 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
648 static void WINAPI XA2SRC_GetVolume(IXAudio2SourceVoice *iface, float *pVolume)
650 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
651 TRACE("%p, %p\n", This, pVolume);
652 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
655 static HRESULT WINAPI XA2SRC_SetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
656 const float *pVolumes, UINT32 OperationSet)
658 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
659 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
660 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
661 pVolumes, OperationSet);
664 static void WINAPI XA2SRC_GetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
665 float *pVolumes)
667 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
668 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
669 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
670 pVolumes);
673 static HRESULT WINAPI XA2SRC_SetOutputMatrix(IXAudio2SourceVoice *iface,
674 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
675 UINT32 DestinationChannels, const float *pLevelMatrix,
676 UINT32 OperationSet)
678 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
679 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
681 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
682 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
684 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
685 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
688 static void WINAPI XA2SRC_GetOutputMatrix(IXAudio2SourceVoice *iface,
689 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
690 UINT32 DestinationChannels, float *pLevelMatrix)
692 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
693 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
695 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
696 SourceChannels, DestinationChannels, pLevelMatrix);
698 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
699 SourceChannels, DestinationChannels, pLevelMatrix);
702 static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
704 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
706 TRACE("%p\n", This);
708 EnterCriticalSection(&This->lock);
710 destroy_voice(This);
712 LeaveCriticalSection(&This->lock);
715 static HRESULT WINAPI XA2SRC_Start(IXAudio2SourceVoice *iface, UINT32 Flags,
716 UINT32 OperationSet)
718 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
720 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
722 return FAudioSourceVoice_Start(This->faudio_voice, Flags, OperationSet);
725 static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
726 UINT32 OperationSet)
728 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
730 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
732 return FAudioSourceVoice_Stop(This->faudio_voice, Flags, OperationSet);
735 static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
736 const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
738 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
740 TRACE("%p, %p, %p\n", This, pBuffer, pBufferWMA);
742 return FAudioSourceVoice_SubmitSourceBuffer(This->faudio_voice, (FAudioBuffer*)pBuffer, (FAudioBufferWMA*)pBufferWMA);
745 static HRESULT WINAPI XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice *iface)
747 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
749 TRACE("%p\n", This);
751 return FAudioSourceVoice_FlushSourceBuffers(This->faudio_voice);
754 static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
756 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
758 TRACE("%p\n", This);
760 return FAudioSourceVoice_Discontinuity(This->faudio_voice);
763 static HRESULT WINAPI XA2SRC_ExitLoop(IXAudio2SourceVoice *iface, UINT32 OperationSet)
765 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
767 TRACE("%p, 0x%x\n", This, OperationSet);
769 return FAudioSourceVoice_ExitLoop(This->faudio_voice, OperationSet);
772 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface,
773 XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags)
775 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
777 TRACE("%p, %p, 0x%x\n", This, pVoiceState, Flags);
779 return FAudioSourceVoice_GetState(This->faudio_voice, (FAudioVoiceState*)pVoiceState, Flags);
782 static HRESULT WINAPI XA2SRC_SetFrequencyRatio(IXAudio2SourceVoice *iface,
783 float Ratio, UINT32 OperationSet)
785 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
787 TRACE("%p, %f, 0x%x\n", This, Ratio, OperationSet);
789 return FAudioSourceVoice_SetFrequencyRatio(This->faudio_voice, Ratio, OperationSet);
792 static void WINAPI XA2SRC_GetFrequencyRatio(IXAudio2SourceVoice *iface, float *pRatio)
794 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
796 TRACE("%p, %p\n", This, pRatio);
798 return FAudioSourceVoice_GetFrequencyRatio(This->faudio_voice, pRatio);
801 static HRESULT WINAPI XA2SRC_SetSourceSampleRate(
802 IXAudio2SourceVoice *iface,
803 UINT32 NewSourceSampleRate)
805 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
807 TRACE("%p, %u\n", This, NewSourceSampleRate);
809 return FAudioSourceVoice_SetSourceSampleRate(This->faudio_voice, NewSourceSampleRate);
812 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl = {
813 XA2SRC_GetVoiceDetails,
814 XA2SRC_SetOutputVoices,
815 XA2SRC_SetEffectChain,
816 XA2SRC_EnableEffect,
817 XA2SRC_DisableEffect,
818 XA2SRC_GetEffectState,
819 XA2SRC_SetEffectParameters,
820 XA2SRC_GetEffectParameters,
821 XA2SRC_SetFilterParameters,
822 XA2SRC_GetFilterParameters,
823 XA2SRC_SetOutputFilterParameters,
824 XA2SRC_GetOutputFilterParameters,
825 XA2SRC_SetVolume,
826 XA2SRC_GetVolume,
827 XA2SRC_SetChannelVolumes,
828 XA2SRC_GetChannelVolumes,
829 XA2SRC_SetOutputMatrix,
830 XA2SRC_GetOutputMatrix,
831 XA2SRC_DestroyVoice,
832 XA2SRC_Start,
833 XA2SRC_Stop,
834 XA2SRC_SubmitSourceBuffer,
835 XA2SRC_FlushSourceBuffers,
836 XA2SRC_Discontinuity,
837 XA2SRC_ExitLoop,
838 XA2SRC_GetState,
839 XA2SRC_SetFrequencyRatio,
840 XA2SRC_GetFrequencyRatio,
841 XA2SRC_SetSourceSampleRate
844 /* Submix Voices */
846 static inline XA2VoiceImpl *impl_from_IXAudio2SubmixVoice(IXAudio2SubmixVoice *iface)
848 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SubmixVoice_iface);
851 static void WINAPI XA2SUB_GetVoiceDetails(IXAudio2SubmixVoice *iface,
852 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
854 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
855 TRACE("%p, %p\n", This, pVoiceDetails);
856 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
859 static HRESULT WINAPI XA2SUB_SetOutputVoices(IXAudio2SubmixVoice *iface,
860 const XAUDIO2_VOICE_SENDS *pSendList)
862 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
863 FAudioVoiceSends *faudio_sends;
864 HRESULT hr;
866 TRACE("%p, %p\n", This, pSendList);
868 faudio_sends = wrap_voice_sends(pSendList);
870 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
872 free_voice_sends(faudio_sends);
874 return hr;
877 static HRESULT WINAPI XA2SUB_SetEffectChain(IXAudio2SubmixVoice *iface,
878 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
880 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
881 HRESULT hr;
883 TRACE("%p, %p\n", This, pEffectChain);
885 free_effect_chain(This->effect_chain);
886 This->effect_chain = wrap_effect_chain(pEffectChain);
888 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
890 return hr;
893 static HRESULT WINAPI XA2SUB_EnableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
894 UINT32 OperationSet)
896 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
897 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
898 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
901 static HRESULT WINAPI XA2SUB_DisableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
902 UINT32 OperationSet)
904 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
905 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
906 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
909 static void WINAPI XA2SUB_GetEffectState(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
910 BOOL *pEnabled)
912 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
913 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
914 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
917 static HRESULT WINAPI XA2SUB_SetEffectParameters(IXAudio2SubmixVoice *iface,
918 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
919 UINT32 OperationSet)
921 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
922 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
923 ParametersByteSize, OperationSet);
924 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
925 pParameters, ParametersByteSize, OperationSet);
928 static HRESULT WINAPI XA2SUB_GetEffectParameters(IXAudio2SubmixVoice *iface,
929 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
931 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
932 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
933 ParametersByteSize);
934 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
935 pParameters, ParametersByteSize);
938 static HRESULT WINAPI XA2SUB_SetFilterParameters(IXAudio2SubmixVoice *iface,
939 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
941 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
942 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
943 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
944 OperationSet);
947 static void WINAPI XA2SUB_GetFilterParameters(IXAudio2SubmixVoice *iface,
948 XAUDIO2_FILTER_PARAMETERS *pParameters)
950 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
951 TRACE("%p, %p\n", This, pParameters);
952 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
955 static HRESULT WINAPI XA2SUB_SetOutputFilterParameters(IXAudio2SubmixVoice *iface,
956 IXAudio2Voice *pDestinationVoice,
957 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
959 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
960 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
962 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
964 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
965 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
968 static void WINAPI XA2SUB_GetOutputFilterParameters(IXAudio2SubmixVoice *iface,
969 IXAudio2Voice *pDestinationVoice,
970 XAUDIO2_FILTER_PARAMETERS *pParameters)
972 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
973 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
975 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
977 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
978 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
981 static HRESULT WINAPI XA2SUB_SetVolume(IXAudio2SubmixVoice *iface, float Volume,
982 UINT32 OperationSet)
984 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
985 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
986 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
989 static void WINAPI XA2SUB_GetVolume(IXAudio2SubmixVoice *iface, float *pVolume)
991 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
992 TRACE("%p, %p\n", This, pVolume);
993 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
996 static HRESULT WINAPI XA2SUB_SetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
997 const float *pVolumes, UINT32 OperationSet)
999 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1000 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1001 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1002 pVolumes, OperationSet);
1005 static void WINAPI XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1006 float *pVolumes)
1008 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1009 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1010 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1011 pVolumes);
1014 static HRESULT WINAPI XA2SUB_SetOutputMatrix(IXAudio2SubmixVoice *iface,
1015 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1016 UINT32 DestinationChannels, const float *pLevelMatrix,
1017 UINT32 OperationSet)
1019 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1020 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1022 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1023 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1025 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1026 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1029 static void WINAPI XA2SUB_GetOutputMatrix(IXAudio2SubmixVoice *iface,
1030 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1031 UINT32 DestinationChannels, float *pLevelMatrix)
1033 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1034 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1036 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1037 SourceChannels, DestinationChannels, pLevelMatrix);
1039 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1040 SourceChannels, DestinationChannels, pLevelMatrix);
1043 static void WINAPI XA2SUB_DestroyVoice(IXAudio2SubmixVoice *iface)
1045 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1047 TRACE("%p\n", This);
1049 EnterCriticalSection(&This->lock);
1051 destroy_voice(This);
1053 LeaveCriticalSection(&This->lock);
1056 static const struct IXAudio2SubmixVoiceVtbl XAudio2SubmixVoice_Vtbl = {
1057 XA2SUB_GetVoiceDetails,
1058 XA2SUB_SetOutputVoices,
1059 XA2SUB_SetEffectChain,
1060 XA2SUB_EnableEffect,
1061 XA2SUB_DisableEffect,
1062 XA2SUB_GetEffectState,
1063 XA2SUB_SetEffectParameters,
1064 XA2SUB_GetEffectParameters,
1065 XA2SUB_SetFilterParameters,
1066 XA2SUB_GetFilterParameters,
1067 XA2SUB_SetOutputFilterParameters,
1068 XA2SUB_GetOutputFilterParameters,
1069 XA2SUB_SetVolume,
1070 XA2SUB_GetVolume,
1071 XA2SUB_SetChannelVolumes,
1072 XA2SUB_GetChannelVolumes,
1073 XA2SUB_SetOutputMatrix,
1074 XA2SUB_GetOutputMatrix,
1075 XA2SUB_DestroyVoice
1078 /* Mastering Voices */
1080 static inline XA2VoiceImpl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface)
1082 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2MasteringVoice_iface);
1085 static void WINAPI XA2M_GetVoiceDetails(IXAudio2MasteringVoice *iface,
1086 XAUDIO2_VOICE_DETAILS *pVoiceDetails)
1088 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1089 TRACE("%p, %p\n", This, pVoiceDetails);
1090 FAudioVoice_GetVoiceDetails(This->faudio_voice, (FAudioVoiceDetails *)pVoiceDetails);
1093 static HRESULT WINAPI XA2M_SetOutputVoices(IXAudio2MasteringVoice *iface,
1094 const XAUDIO2_VOICE_SENDS *pSendList)
1096 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1097 FAudioVoiceSends *faudio_sends;
1098 HRESULT hr;
1100 TRACE("%p, %p\n", This, pSendList);
1102 faudio_sends = wrap_voice_sends(pSendList);
1104 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
1106 free_voice_sends(faudio_sends);
1108 return hr;
1111 static HRESULT WINAPI XA2M_SetEffectChain(IXAudio2MasteringVoice *iface,
1112 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1114 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1115 HRESULT hr;
1117 TRACE("%p, %p\n", This, pEffectChain);
1119 free_effect_chain(This->effect_chain);
1120 This->effect_chain = wrap_effect_chain(pEffectChain);
1122 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
1124 return hr;
1127 static HRESULT WINAPI XA2M_EnableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1128 UINT32 OperationSet)
1130 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1131 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1132 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
1135 static HRESULT WINAPI XA2M_DisableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1136 UINT32 OperationSet)
1138 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1139 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1140 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
1143 static void WINAPI XA2M_GetEffectState(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1144 BOOL *pEnabled)
1146 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1147 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
1148 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
1151 static HRESULT WINAPI XA2M_SetEffectParameters(IXAudio2MasteringVoice *iface,
1152 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
1153 UINT32 OperationSet)
1155 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1156 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
1157 ParametersByteSize, OperationSet);
1158 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
1159 pParameters, ParametersByteSize, OperationSet);
1162 static HRESULT WINAPI XA2M_GetEffectParameters(IXAudio2MasteringVoice *iface,
1163 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
1165 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1166 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
1167 ParametersByteSize);
1168 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
1169 pParameters, ParametersByteSize);
1172 static HRESULT WINAPI XA2M_SetFilterParameters(IXAudio2MasteringVoice *iface,
1173 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1175 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1176 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
1177 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
1178 OperationSet);
1181 static void WINAPI XA2M_GetFilterParameters(IXAudio2MasteringVoice *iface,
1182 XAUDIO2_FILTER_PARAMETERS *pParameters)
1184 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1185 TRACE("%p, %p\n", This, pParameters);
1186 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
1189 static HRESULT WINAPI XA2M_SetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1190 IXAudio2Voice *pDestinationVoice,
1191 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1193 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1194 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1196 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
1198 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
1199 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
1202 static void WINAPI XA2M_GetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1203 IXAudio2Voice *pDestinationVoice,
1204 XAUDIO2_FILTER_PARAMETERS *pParameters)
1206 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1207 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1209 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
1211 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
1212 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1215 static HRESULT WINAPI XA2M_SetVolume(IXAudio2MasteringVoice *iface, float Volume,
1216 UINT32 OperationSet)
1218 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1219 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1220 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1223 static void WINAPI XA2M_GetVolume(IXAudio2MasteringVoice *iface, float *pVolume)
1225 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1226 TRACE("%p, %p\n", This, pVolume);
1227 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1230 static HRESULT WINAPI XA2M_SetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1231 const float *pVolumes, UINT32 OperationSet)
1233 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1234 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1235 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1236 pVolumes, OperationSet);
1239 static void WINAPI XA2M_GetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1240 float *pVolumes)
1242 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1243 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1244 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1245 pVolumes);
1248 static HRESULT WINAPI XA2M_SetOutputMatrix(IXAudio2MasteringVoice *iface,
1249 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1250 UINT32 DestinationChannels, const float *pLevelMatrix,
1251 UINT32 OperationSet)
1253 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1254 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1256 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1257 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1259 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1260 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1263 static void WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface,
1264 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1265 UINT32 DestinationChannels, float *pLevelMatrix)
1267 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1268 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1270 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1271 SourceChannels, DestinationChannels, pLevelMatrix);
1273 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1274 SourceChannels, DestinationChannels, pLevelMatrix);
1277 static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface)
1279 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1281 TRACE("%p\n", This);
1283 EnterCriticalSection(&This->lock);
1285 destroy_voice(This);
1286 pthread_mutex_lock(&This->engine_lock);
1287 This->engine_params.proc = NULL;
1288 pthread_cond_broadcast(&This->engine_ready);
1289 pthread_mutex_unlock(&This->engine_lock);
1291 WaitForSingleObject(This->engine_thread, INFINITE);
1292 This->engine_thread = NULL;
1294 LeaveCriticalSection(&This->lock);
1297 static void WINAPI XA2M_GetChannelMask(IXAudio2MasteringVoice *iface,
1298 DWORD *pChannelMask)
1300 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1302 TRACE("%p, %p\n", This, pChannelMask);
1304 FAudioMasteringVoice_GetChannelMask(This->faudio_voice, pChannelMask);
1307 static const struct IXAudio2MasteringVoiceVtbl XAudio2MasteringVoice_Vtbl = {
1308 XA2M_GetVoiceDetails,
1309 XA2M_SetOutputVoices,
1310 XA2M_SetEffectChain,
1311 XA2M_EnableEffect,
1312 XA2M_DisableEffect,
1313 XA2M_GetEffectState,
1314 XA2M_SetEffectParameters,
1315 XA2M_GetEffectParameters,
1316 XA2M_SetFilterParameters,
1317 XA2M_GetFilterParameters,
1318 XA2M_SetOutputFilterParameters,
1319 XA2M_GetOutputFilterParameters,
1320 XA2M_SetVolume,
1321 XA2M_GetVolume,
1322 XA2M_SetChannelVolumes,
1323 XA2M_GetChannelVolumes,
1324 XA2M_SetOutputMatrix,
1325 XA2M_GetOutputMatrix,
1326 XA2M_DestroyVoice,
1327 XA2M_GetChannelMask
1330 /* More Common Voice Functions */
1332 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface)
1334 if(iface->lpVtbl == (void*)&XAudio2SourceVoice_Vtbl)
1335 return impl_from_IXAudio2SourceVoice((IXAudio2SourceVoice*)iface);
1336 if(iface->lpVtbl == (void*)&XAudio2MasteringVoice_Vtbl)
1337 return impl_from_IXAudio2MasteringVoice((IXAudio2MasteringVoice*)iface);
1338 if(iface->lpVtbl == (void*)&XAudio2SubmixVoice_Vtbl)
1339 return impl_from_IXAudio2SubmixVoice((IXAudio2SubmixVoice*)iface);
1340 #if XAUDIO2_VER == 0
1341 if(iface->lpVtbl == (void*)&XAudio20SourceVoice_Vtbl)
1342 return impl_from_IXAudio20SourceVoice((IXAudio20SourceVoice*)iface);
1343 if(iface->lpVtbl == (void*)&XAudio20SubmixVoice_Vtbl)
1344 return impl_from_IXAudio20SubmixVoice((IXAudio20SubmixVoice*)iface);
1345 if(iface->lpVtbl == (void*)&XAudio20MasteringVoice_Vtbl)
1346 return impl_from_IXAudio20MasteringVoice((IXAudio20MasteringVoice*)iface);
1347 #elif XAUDIO2_VER <= 3
1348 if(iface->lpVtbl == (void*)&XAudio23SourceVoice_Vtbl)
1349 return impl_from_IXAudio23SourceVoice((IXAudio23SourceVoice*)iface);
1350 if(iface->lpVtbl == (void*)&XAudio23SubmixVoice_Vtbl)
1351 return impl_from_IXAudio23SubmixVoice((IXAudio23SubmixVoice*)iface);
1352 if(iface->lpVtbl == (void*)&XAudio23MasteringVoice_Vtbl)
1353 return impl_from_IXAudio23MasteringVoice((IXAudio23MasteringVoice*)iface);
1354 #elif XAUDIO2_VER <= 7
1355 if(iface->lpVtbl == (void*)&XAudio27SourceVoice_Vtbl)
1356 return impl_from_IXAudio27SourceVoice((IXAudio27SourceVoice*)iface);
1357 if(iface->lpVtbl == (void*)&XAudio27SubmixVoice_Vtbl)
1358 return impl_from_IXAudio27SubmixVoice((IXAudio27SubmixVoice*)iface);
1359 if(iface->lpVtbl == (void*)&XAudio27MasteringVoice_Vtbl)
1360 return impl_from_IXAudio27MasteringVoice((IXAudio27MasteringVoice*)iface);
1361 #endif
1362 ERR("invalid IXAudio2Voice pointer: %p\n", iface);
1363 return NULL;
1366 /* XAudio2 Engine Implementation */
1368 static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface)
1370 return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2_iface);
1373 static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
1374 void **ppvObject)
1376 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1378 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1380 if(IsEqualGUID(riid, &IID_IUnknown) ||
1381 #if XAUDIO2_VER == 8
1382 IsEqualGUID(riid, &IID_IXAudio28) ||
1383 #endif
1384 IsEqualGUID(riid, &IID_IXAudio2))
1385 *ppvObject = &This->IXAudio2_iface;
1386 else if(IsEqualGUID(riid, &IID_IXAudio27)){
1387 /* all xaudio versions before 28 share an IID */
1388 #if XAUDIO2_VER == 0
1389 *ppvObject = &This->IXAudio20_iface;
1390 #elif XAUDIO2_VER <= 2
1391 *ppvObject = &This->IXAudio22_iface;
1392 #elif XAUDIO2_VER <= 3
1393 *ppvObject = &This->IXAudio23_iface;
1394 #elif XAUDIO2_VER <= 7
1395 *ppvObject = &This->IXAudio27_iface;
1396 #else
1397 *ppvObject = NULL;
1398 #endif
1399 }else
1400 *ppvObject = NULL;
1402 if(*ppvObject){
1403 IUnknown_AddRef((IUnknown*)*ppvObject);
1404 return S_OK;
1407 FIXME("(%p)->(%s,%p), not found\n", This,debugstr_guid(riid), ppvObject);
1409 return E_NOINTERFACE;
1412 static ULONG WINAPI IXAudio2Impl_AddRef(IXAudio2 *iface)
1414 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1415 ULONG ref = FAudio_AddRef(This->faudio);
1416 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1417 return ref;
1420 static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
1422 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1423 ULONG ref = FAudio_Release(This->faudio);
1425 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1427 if (!ref) {
1428 XA2VoiceImpl *v, *v2;
1430 LIST_FOR_EACH_ENTRY_SAFE(v, v2, &This->voices, XA2VoiceImpl, entry){
1431 v->lock.DebugInfo->Spare[0] = 0;
1432 DeleteCriticalSection(&v->lock);
1433 HeapFree(GetProcessHeap(), 0, v);
1436 HeapFree(GetProcessHeap(), 0, This->cbs);
1438 This->lock.DebugInfo->Spare[0] = 0;
1439 DeleteCriticalSection(&This->lock);
1441 HeapFree(GetProcessHeap(), 0, This);
1443 return ref;
1446 static HRESULT WINAPI IXAudio2Impl_RegisterForCallbacks(IXAudio2 *iface,
1447 IXAudio2EngineCallback *pCallback)
1449 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1450 int i;
1452 TRACE("(%p)->(%p)\n", This, pCallback);
1454 EnterCriticalSection(&This->lock);
1456 for(i = 0; i < This->ncbs; ++i){
1457 if(!This->cbs[i] || This->cbs[i] == pCallback){
1458 This->cbs[i] = pCallback;
1459 LeaveCriticalSection(&This->lock);
1460 return S_OK;
1464 This->ncbs++;
1465 This->cbs = heap_realloc(This->cbs, This->ncbs * sizeof(*This->cbs));
1467 This->cbs[i] = pCallback;
1469 LeaveCriticalSection(&This->lock);
1471 return S_OK;
1474 static void WINAPI IXAudio2Impl_UnregisterForCallbacks(IXAudio2 *iface,
1475 IXAudio2EngineCallback *pCallback)
1477 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1478 int i;
1480 TRACE("(%p)->(%p)\n", This, pCallback);
1482 EnterCriticalSection(&This->lock);
1484 if(This->ncbs == 0){
1485 LeaveCriticalSection(&This->lock);
1486 return;
1489 for(i = 0; i < This->ncbs; ++i){
1490 if(This->cbs[i] == pCallback)
1491 break;
1494 for(; i < This->ncbs - 1 && This->cbs[i + 1]; ++i)
1495 This->cbs[i] = This->cbs[i + 1];
1497 if(i < This->ncbs)
1498 This->cbs[i] = NULL;
1500 LeaveCriticalSection(&This->lock);
1503 static inline XA2VoiceImpl *create_voice(IXAudio2Impl *This)
1505 XA2VoiceImpl *voice;
1507 voice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*voice));
1508 if(!voice)
1509 return NULL;
1511 list_add_head(&This->voices, &voice->entry);
1513 voice->IXAudio2SourceVoice_iface.lpVtbl = &XAudio2SourceVoice_Vtbl;
1514 #if XAUDIO2_VER == 0
1515 voice->IXAudio20SourceVoice_iface.lpVtbl = &XAudio20SourceVoice_Vtbl;
1516 #elif XAUDIO2_VER <= 3
1517 voice->IXAudio23SourceVoice_iface.lpVtbl = &XAudio23SourceVoice_Vtbl;
1518 #elif XAUDIO2_VER <= 7
1519 voice->IXAudio27SourceVoice_iface.lpVtbl = &XAudio27SourceVoice_Vtbl;
1520 #endif
1522 voice->IXAudio2SubmixVoice_iface.lpVtbl = &XAudio2SubmixVoice_Vtbl;
1523 #if XAUDIO2_VER == 0
1524 voice->IXAudio20SubmixVoice_iface.lpVtbl = &XAudio20SubmixVoice_Vtbl;
1525 #elif XAUDIO2_VER <= 3
1526 voice->IXAudio23SubmixVoice_iface.lpVtbl = &XAudio23SubmixVoice_Vtbl;
1527 #elif XAUDIO2_VER <= 7
1528 voice->IXAudio27SubmixVoice_iface.lpVtbl = &XAudio27SubmixVoice_Vtbl;
1529 #endif
1531 voice->FAudioVoiceCallback_vtbl = FAudioVoiceCallback_Vtbl;
1533 InitializeCriticalSection(&voice->lock);
1534 voice->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2VoiceImpl.lock");
1536 return voice;
1539 static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
1540 IXAudio2SourceVoice **ppSourceVoice, const WAVEFORMATEX *pSourceFormat,
1541 UINT32 flags, float maxFrequencyRatio,
1542 IXAudio2VoiceCallback *pCallback, const XAUDIO2_VOICE_SENDS *pSendList,
1543 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1545 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1546 XA2VoiceImpl *src;
1547 HRESULT hr;
1548 FAudioVoiceSends *faudio_sends;
1550 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This, ppSourceVoice,
1551 pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
1552 pEffectChain);
1554 EnterCriticalSection(&This->lock);
1556 LIST_FOR_EACH_ENTRY(src, &This->voices, XA2VoiceImpl, entry){
1557 EnterCriticalSection(&src->lock);
1558 if(!src->in_use)
1559 break;
1560 LeaveCriticalSection(&src->lock);
1563 if(&src->entry == &This->voices){
1564 src = create_voice(This);
1565 EnterCriticalSection(&src->lock);
1568 LeaveCriticalSection(&This->lock);
1570 src->effect_chain = wrap_effect_chain(pEffectChain);
1571 faudio_sends = wrap_voice_sends(pSendList);
1573 hr = FAudio_CreateSourceVoice(This->faudio, &src->faudio_voice,
1574 (FAudioWaveFormatEx*)pSourceFormat, flags, maxFrequencyRatio,
1575 &src->FAudioVoiceCallback_vtbl, faudio_sends,
1576 src->effect_chain);
1577 free_voice_sends(faudio_sends);
1578 if(FAILED(hr)){
1579 LeaveCriticalSection(&This->lock);
1580 return hr;
1582 src->in_use = TRUE;
1583 src->cb = pCallback;
1585 LeaveCriticalSection(&src->lock);
1587 #if XAUDIO2_VER == 0
1588 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio20SourceVoice_iface;
1589 #elif XAUDIO2_VER <= 3
1590 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio23SourceVoice_iface;
1591 #elif XAUDIO2_VER <= 7
1592 *ppSourceVoice = (IXAudio2SourceVoice*)&src->IXAudio27SourceVoice_iface;
1593 #else
1594 *ppSourceVoice = &src->IXAudio2SourceVoice_iface;
1595 #endif
1597 TRACE("Created source voice: %p\n", src);
1599 return S_OK;
1602 static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
1603 IXAudio2SubmixVoice **ppSubmixVoice, UINT32 inputChannels,
1604 UINT32 inputSampleRate, UINT32 flags, UINT32 processingStage,
1605 const XAUDIO2_VOICE_SENDS *pSendList,
1606 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1608 HRESULT hr;
1609 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1610 XA2VoiceImpl *sub;
1611 FAudioVoiceSends *faudio_sends;
1613 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This, ppSubmixVoice,
1614 inputChannels, inputSampleRate, flags, processingStage, pSendList,
1615 pEffectChain);
1617 EnterCriticalSection(&This->lock);
1619 LIST_FOR_EACH_ENTRY(sub, &This->voices, XA2VoiceImpl, entry){
1620 EnterCriticalSection(&sub->lock);
1621 if(!sub->in_use)
1622 break;
1623 LeaveCriticalSection(&sub->lock);
1626 if(&sub->entry == &This->voices){
1627 sub = create_voice(This);
1628 EnterCriticalSection(&sub->lock);
1631 LeaveCriticalSection(&This->lock);
1633 sub->effect_chain = wrap_effect_chain(pEffectChain);
1634 faudio_sends = wrap_voice_sends(pSendList);
1636 hr = FAudio_CreateSubmixVoice(This->faudio, &sub->faudio_voice, inputChannels,
1637 inputSampleRate, flags, processingStage, faudio_sends,
1638 sub->effect_chain);
1639 free_voice_sends(faudio_sends);
1640 if(FAILED(hr)){
1641 LeaveCriticalSection(&sub->lock);
1642 return hr;
1644 sub->in_use = TRUE;
1646 LeaveCriticalSection(&sub->lock);
1648 #if XAUDIO2_VER == 0
1649 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio20SubmixVoice_iface;
1650 #elif XAUDIO2_VER <= 3
1651 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio23SubmixVoice_iface;
1652 #elif XAUDIO2_VER <= 7
1653 *ppSubmixVoice = (IXAudio2SubmixVoice*)&sub->IXAudio27SubmixVoice_iface;
1654 #else
1655 *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
1656 #endif
1658 TRACE("Created submix voice: %p\n", sub);
1660 return S_OK;
1663 /* called thread created by SDL, must not access Wine TEB */
1664 void engine_cb(FAudioEngineCallEXT proc, FAudio *faudio, float *stream, void *user)
1666 XA2VoiceImpl *This = user;
1668 pthread_mutex_lock(&This->engine_lock);
1670 This->engine_params.proc = proc;
1671 This->engine_params.stream = stream;
1672 This->engine_params.faudio = faudio;
1674 pthread_cond_broadcast(&This->engine_ready);
1676 while(This->engine_params.proc)
1677 pthread_cond_wait(&This->engine_done, &This->engine_lock);
1679 pthread_mutex_unlock(&This->engine_lock);
1682 /* wine thread, OK to access TEB, invoke client code, etc */
1683 DWORD WINAPI engine_thread(void *user)
1685 XA2VoiceImpl *This = user;
1687 pthread_mutex_lock(&This->engine_lock);
1689 pthread_cond_broadcast(&This->engine_done);
1692 pthread_cond_wait(&This->engine_ready, &This->engine_lock);
1694 if(This->engine_params.proc){
1695 This->engine_params.proc(This->engine_params.faudio, This->engine_params.stream);
1696 This->engine_params.proc = NULL;
1697 pthread_cond_broadcast(&This->engine_done);
1699 }while(This->in_use);
1701 pthread_mutex_unlock(&This->engine_lock);
1703 return 0;
1706 static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
1707 IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels,
1708 UINT32 inputSampleRate, UINT32 flags, const WCHAR *deviceId,
1709 const XAUDIO2_EFFECT_CHAIN *pEffectChain,
1710 AUDIO_STREAM_CATEGORY streamCategory)
1712 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1714 TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This,
1715 ppMasteringVoice, inputChannels, inputSampleRate, flags,
1716 wine_dbgstr_w(deviceId), pEffectChain, streamCategory);
1718 EnterCriticalSection(&This->lock);
1720 /* Note that we don't have paths for each XAUDIO2_VER here.
1721 * All versions < 8 have a very different CreateMasteringVoice, so we
1722 * implement those separately in compat.c.
1723 * -flibit
1725 *ppMasteringVoice = &This->mst.IXAudio2MasteringVoice_iface;
1727 EnterCriticalSection(&This->mst.lock);
1729 if(This->mst.in_use){
1730 LeaveCriticalSection(&This->mst.lock);
1731 LeaveCriticalSection(&This->lock);
1732 return COMPAT_E_INVALID_CALL;
1735 LeaveCriticalSection(&This->lock);
1737 This->mst.effect_chain = wrap_effect_chain(pEffectChain);
1739 pthread_mutex_lock(&This->mst.engine_lock);
1741 This->mst.engine_thread = CreateThread(NULL, 0, &engine_thread, &This->mst, 0, NULL);
1743 pthread_cond_wait(&This->mst.engine_done, &This->mst.engine_lock);
1745 pthread_mutex_unlock(&This->mst.engine_lock);
1747 FAudio_SetEngineProcedureEXT(This->faudio, &engine_cb, &This->mst);
1749 FAudio_CreateMasteringVoice8(This->faudio, &This->mst.faudio_voice, inputChannels,
1750 inputSampleRate, flags, NULL /* TODO: (uint16_t*)deviceId */,
1751 This->mst.effect_chain, (FAudioStreamCategory)streamCategory);
1753 This->mst.in_use = TRUE;
1755 LeaveCriticalSection(&This->mst.lock);
1757 return S_OK;
1760 static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
1762 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1764 TRACE("(%p)->()\n", This);
1766 return FAudio_StartEngine(This->faudio);
1769 static void WINAPI IXAudio2Impl_StopEngine(IXAudio2 *iface)
1771 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1773 TRACE("(%p)->()\n", This);
1775 FAudio_StopEngine(This->faudio);
1778 static HRESULT WINAPI IXAudio2Impl_CommitChanges(IXAudio2 *iface,
1779 UINT32 operationSet)
1781 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1783 TRACE("(%p)->(0x%x)\n", This, operationSet);
1785 #ifdef HAVE_FAUDIO_COMMITOPERATIONSET
1786 return FAudio_CommitOperationSet(This->faudio, operationSet);
1787 #else
1788 return FAudio_CommitChanges(This->faudio);
1789 #endif
1792 static void WINAPI IXAudio2Impl_GetPerformanceData(IXAudio2 *iface,
1793 XAUDIO2_PERFORMANCE_DATA *pPerfData)
1795 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1797 TRACE("(%p)->(%p)\n", This, pPerfData);
1799 FAudio_GetPerformanceData(This->faudio, (FAudioPerformanceData *)pPerfData);
1802 static void WINAPI IXAudio2Impl_SetDebugConfiguration(IXAudio2 *iface,
1803 const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
1804 void *pReserved)
1806 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1808 TRACE("(%p)->(%p, %p)\n", This, pDebugConfiguration, pReserved);
1810 FAudio_SetDebugConfiguration(This->faudio, (FAudioDebugConfiguration *)pDebugConfiguration, pReserved);
1813 /* XAudio2 2.8 */
1814 static const IXAudio2Vtbl XAudio2_Vtbl =
1816 IXAudio2Impl_QueryInterface,
1817 IXAudio2Impl_AddRef,
1818 IXAudio2Impl_Release,
1819 IXAudio2Impl_RegisterForCallbacks,
1820 IXAudio2Impl_UnregisterForCallbacks,
1821 IXAudio2Impl_CreateSourceVoice,
1822 IXAudio2Impl_CreateSubmixVoice,
1823 IXAudio2Impl_CreateMasteringVoice,
1824 IXAudio2Impl_StartEngine,
1825 IXAudio2Impl_StopEngine,
1826 IXAudio2Impl_CommitChanges,
1827 IXAudio2Impl_GetPerformanceData,
1828 IXAudio2Impl_SetDebugConfiguration
1831 /* XAudio2 ClassFactory */
1833 struct xaudio2_cf {
1834 IClassFactory IClassFactory_iface;
1835 LONG ref;
1838 static struct xaudio2_cf *impl_from_IClassFactory(IClassFactory *iface)
1840 return CONTAINING_RECORD(iface, struct xaudio2_cf, IClassFactory_iface);
1843 static HRESULT WINAPI XAudio2CF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1845 if(IsEqualGUID(riid, &IID_IUnknown)
1846 || IsEqualGUID(riid, &IID_IClassFactory))
1848 IClassFactory_AddRef(iface);
1849 *ppobj = iface;
1850 return S_OK;
1853 *ppobj = NULL;
1854 WARN("(%p)->(%s, %p): interface not found\n", iface, debugstr_guid(riid), ppobj);
1855 return E_NOINTERFACE;
1858 static ULONG WINAPI XAudio2CF_AddRef(IClassFactory *iface)
1860 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1861 ULONG ref = InterlockedIncrement(&This->ref);
1862 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1863 return ref;
1866 static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
1868 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1869 ULONG ref = InterlockedDecrement(&This->ref);
1870 TRACE("(%p)->(): Refcount now %u\n", This, ref);
1871 if (!ref)
1872 HeapFree(GetProcessHeap(), 0, This);
1873 return ref;
1876 static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1877 REFIID riid, void **ppobj)
1879 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1880 HRESULT hr;
1881 IXAudio2Impl *object;
1883 TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
1885 *ppobj = NULL;
1887 if(pOuter)
1888 return CLASS_E_NOAGGREGATION;
1890 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
1891 if(!object)
1892 return E_OUTOFMEMORY;
1894 object->IXAudio2_iface.lpVtbl = &XAudio2_Vtbl;
1896 #if XAUDIO2_VER == 0
1897 object->IXAudio20_iface.lpVtbl = &XAudio20_Vtbl;
1898 #elif XAUDIO2_VER <= 2
1899 object->IXAudio22_iface.lpVtbl = &XAudio22_Vtbl;
1900 #elif XAUDIO2_VER <= 3
1901 object->IXAudio23_iface.lpVtbl = &XAudio23_Vtbl;
1902 #elif XAUDIO2_VER <= 7
1903 object->IXAudio27_iface.lpVtbl = &XAudio27_Vtbl;
1904 #endif
1906 object->mst.IXAudio2MasteringVoice_iface.lpVtbl = &XAudio2MasteringVoice_Vtbl;
1908 #if XAUDIO2_VER == 0
1909 object->mst.IXAudio20MasteringVoice_iface.lpVtbl = &XAudio20MasteringVoice_Vtbl;
1910 #elif XAUDIO2_VER <= 3
1911 object->mst.IXAudio23MasteringVoice_iface.lpVtbl = &XAudio23MasteringVoice_Vtbl;
1912 #elif XAUDIO2_VER <= 7
1913 object->mst.IXAudio27MasteringVoice_iface.lpVtbl = &XAudio27MasteringVoice_Vtbl;
1914 #endif
1916 object->FAudioEngineCallback_vtbl = FAudioEngineCallback_Vtbl;
1918 list_init(&object->voices);
1920 InitializeCriticalSection(&object->lock);
1921 object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IXAudio2Impl.lock");
1923 InitializeCriticalSection(&object->mst.lock);
1924 object->mst.lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2MasteringVoice.lock");
1926 pthread_mutex_init(&object->mst.engine_lock, NULL);
1927 pthread_cond_init(&object->mst.engine_done, NULL);
1928 pthread_cond_init(&object->mst.engine_ready, NULL);
1930 FAudioCOMConstructWithCustomAllocatorEXT(
1931 &object->faudio,
1932 XAUDIO2_VER,
1933 XAudio_Internal_Malloc,
1934 XAudio_Internal_Free,
1935 XAudio_Internal_Realloc
1938 FAudio_RegisterForCallbacks(object->faudio, &object->FAudioEngineCallback_vtbl);
1940 hr = IXAudio2_QueryInterface(&object->IXAudio2_iface, riid, ppobj);
1941 IXAudio2_Release(&object->IXAudio2_iface);
1942 if(FAILED(hr)){
1943 return hr;
1946 TRACE("Created XAudio version %u: %p\n", 20 + XAUDIO2_VER, object);
1948 return hr;
1951 static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock)
1953 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1954 FIXME("(%p)->(%d): stub!\n", This, dolock);
1955 return S_OK;
1958 static const IClassFactoryVtbl XAudio2CF_Vtbl =
1960 XAudio2CF_QueryInterface,
1961 XAudio2CF_AddRef,
1962 XAudio2CF_Release,
1963 XAudio2CF_CreateInstance,
1964 XAudio2CF_LockServer
1967 /* Engine Generators */
1969 static inline HRESULT make_xaudio2_factory(REFIID riid, void **ppv)
1971 HRESULT hr;
1972 struct xaudio2_cf *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct xaudio2_cf));
1973 ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
1974 ret->ref = 0;
1975 hr = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
1976 if(FAILED(hr))
1977 HeapFree(GetProcessHeap(), 0, ret);
1978 return hr;
1981 HRESULT xaudio2_initialize(IXAudio2Impl *This, UINT32 flags, XAUDIO2_PROCESSOR proc)
1983 if(proc != XAUDIO2_ANY_PROCESSOR)
1984 WARN("Processor affinity not implemented in FAudio\n");
1985 return FAudio_Initialize(This->faudio, flags, FAUDIO_DEFAULT_PROCESSOR);
1988 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
1990 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1992 if(IsEqualGUID(rclsid, &CLSID_XAudio20) ||
1993 IsEqualGUID(rclsid, &CLSID_XAudio21) ||
1994 IsEqualGUID(rclsid, &CLSID_XAudio22) ||
1995 IsEqualGUID(rclsid, &CLSID_XAudio23) ||
1996 IsEqualGUID(rclsid, &CLSID_XAudio24) ||
1997 IsEqualGUID(rclsid, &CLSID_XAudio25) ||
1998 IsEqualGUID(rclsid, &CLSID_XAudio26) ||
1999 IsEqualGUID(rclsid, &CLSID_XAudio27))
2000 return make_xaudio2_factory(riid, ppv);
2002 if(IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter20) ||
2003 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter21) ||
2004 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter22) ||
2005 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter23) ||
2006 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter24) ||
2007 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter25) ||
2008 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter26) ||
2009 IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter27))
2010 return make_xapo_factory(&CLSID_AudioVolumeMeter27, riid, ppv);
2012 if(IsEqualGUID(rclsid, &CLSID_AudioReverb20) ||
2013 IsEqualGUID(rclsid, &CLSID_AudioReverb21) ||
2014 IsEqualGUID(rclsid, &CLSID_AudioReverb22) ||
2015 IsEqualGUID(rclsid, &CLSID_AudioReverb23) ||
2016 IsEqualGUID(rclsid, &CLSID_AudioReverb24) ||
2017 IsEqualGUID(rclsid, &CLSID_AudioReverb25) ||
2018 IsEqualGUID(rclsid, &CLSID_AudioReverb26) ||
2019 IsEqualGUID(rclsid, &CLSID_AudioReverb27))
2020 return make_xapo_factory(&CLSID_AudioReverb27, riid, ppv);
2022 return CLASS_E_CLASSNOTAVAILABLE;
2025 #if XAUDIO2_VER >= 8
2026 HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR proc)
2028 HRESULT hr;
2029 IXAudio2 *xa2;
2030 IClassFactory *cf;
2032 TRACE("%p 0x%x 0x%x\n", ppxa2, flags, proc);
2034 hr = make_xaudio2_factory(&IID_IClassFactory, (void**)&cf);
2035 if(FAILED(hr))
2036 return hr;
2038 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IXAudio2, (void**)&xa2);
2039 IClassFactory_Release(cf);
2040 if(FAILED(hr))
2041 return hr;
2043 hr = xaudio2_initialize(impl_from_IXAudio2(xa2), flags, proc);
2044 if(FAILED(hr)){
2045 IXAudio2_Release(xa2);
2046 return hr;
2049 *ppxa2 = xa2;
2051 return S_OK;
2054 HRESULT WINAPI CreateAudioVolumeMeter(IUnknown **out)
2056 IClassFactory *cf;
2057 HRESULT hr;
2059 TRACE("%p\n", out);
2061 hr = make_xapo_factory(&CLSID_AudioVolumeMeter27, &IID_IClassFactory, (void**)&cf);
2062 if(FAILED(hr))
2063 return hr;
2065 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
2067 IClassFactory_Release(cf);
2069 return hr;
2072 HRESULT WINAPI CreateAudioReverb(IUnknown **out)
2074 IClassFactory *cf;
2075 HRESULT hr;
2077 TRACE("%p\n", out);
2079 hr = make_xapo_factory(&CLSID_AudioReverb27, &IID_IClassFactory, (void**)&cf);
2080 if(FAILED(hr))
2081 return hr;
2083 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void**)out);
2085 IClassFactory_Release(cf);
2087 return hr;
2089 #endif /* XAUDIO2_VER >= 8 */