Release 8.16.
[wine.git] / dlls / xaudio2_7 / xaudio_dll.c
blobb821e9667b76f49e1eb43920a3557aec065b28cd
1 /*
2 * Copyright (c) 2015 Mark Harmstone
3 * Copyright (c) 2015 Andrew Eikum for CodeWeavers
4 * Copyright (c) 2018 Ethan Lee for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windows.h"
26 #include "objbase.h"
27 #include "mmdeviceapi.h"
29 #include "initguid.h"
30 #include "xaudio_private.h"
31 #if XAUDIO2_VER >= 8
32 #include "xapofx.h"
33 #endif
35 #include "wine/asm.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2);
40 #if XAUDIO2_VER != 0 && defined(__i386__)
41 /* EVE Online uses an OnVoiceProcessingPassStart callback which corrupts %esi;
42 * League of Legends uses a callback which corrupts %ebx. */
43 #define IXAudio2VoiceCallback_OnVoiceProcessingPassStart(a, b) call_on_voice_processing_pass_start(a, b)
44 extern void call_on_voice_processing_pass_start(IXAudio2VoiceCallback *This, UINT32 BytesRequired);
45 __ASM_GLOBAL_FUNC( call_on_voice_processing_pass_start,
46 "pushl %ebp\n\t"
47 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
48 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
49 "movl %esp,%ebp\n\t"
50 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
51 "pushl %esi\n\t"
52 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
53 "pushl %edi\n\t"
54 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
55 "pushl %ebx\n\t"
56 __ASM_CFI(".cfi_rel_offset %ebx,-12\n\t")
57 "subl $4,%esp\n\t"
58 "pushl 12(%ebp)\n\t" /* BytesRequired */
59 "pushl 8(%ebp)\n\t" /* This */
60 "movl 8(%ebp),%eax\n\t"
61 "movl 0(%eax),%eax\n\t"
62 "call *0(%eax)\n\t" /* This->lpVtbl->OnVoiceProcessingPassStart */
63 "leal -12(%ebp),%esp\n\t"
64 "popl %ebx\n\t"
65 __ASM_CFI(".cfi_same_value %ebx\n\t")
66 "popl %edi\n\t"
67 __ASM_CFI(".cfi_same_value %edi\n\t")
68 "popl %esi\n\t"
69 __ASM_CFI(".cfi_same_value %esi\n\t")
70 "popl %ebp\n\t"
71 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
72 __ASM_CFI(".cfi_same_value %ebp\n\t")
73 "ret" )
74 #endif
76 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface);
78 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, void *pReserved)
80 TRACE("(%p, %ld, %p)\n", hinstDLL, reason, pReserved);
82 switch (reason)
84 case DLL_PROCESS_ATTACH:
85 DisableThreadLibraryCalls( hinstDLL );
86 TRACE("Using FAudio version %d\n", FAudioLinkedVersion() );
87 break;
89 return TRUE;
92 /* Effect Wrapping */
94 static inline XA2XAPOImpl *impl_from_FAPO(FAPO *iface)
96 return CONTAINING_RECORD(iface, XA2XAPOImpl, FAPO_vtbl);
99 static int32_t FAPOCALL XAPO_AddRef(void *iface)
101 XA2XAPOImpl *This = impl_from_FAPO(iface);
102 TRACE("%p\n", This);
103 return InterlockedIncrement(&This->ref);
106 static int32_t FAPOCALL XAPO_Release(void *iface)
108 int32_t r;
109 XA2XAPOImpl *This = impl_from_FAPO(iface);
110 TRACE("%p\n", This);
111 r = InterlockedDecrement(&This->ref);
112 if(r == 0){
113 IXAPO_Release(This->xapo);
114 if(This->xapo_params)
115 IXAPOParameters_Release(This->xapo_params);
116 free(This);
118 return r;
121 static uint32_t FAPOCALL XAPO_GetRegistrationProperties(void *iface,
122 FAPORegistrationProperties **ppRegistrationProperties)
124 XA2XAPOImpl *This = impl_from_FAPO(iface);
125 XAPO_REGISTRATION_PROPERTIES *xprops;
126 HRESULT hr;
128 TRACE("%p\n", This);
130 hr = IXAPO_GetRegistrationProperties(This->xapo, &xprops);
131 if(FAILED(hr))
132 return hr;
134 /* TODO: check for version == 20 and use XAPO20_REGISTRATION_PROPERTIES */
135 *ppRegistrationProperties = (FAPORegistrationProperties*) xprops;
136 return 0;
139 static uint32_t FAPOCALL XAPO_IsInputFormatSupported(void *iface,
140 const FAudioWaveFormatEx *pOutputFormat, const FAudioWaveFormatEx *pRequestedInputFormat,
141 FAudioWaveFormatEx **ppSupportedInputFormat)
143 XA2XAPOImpl *This = impl_from_FAPO(iface);
144 TRACE("%p\n", This);
145 return IXAPO_IsInputFormatSupported(This->xapo, (const WAVEFORMATEX*)pOutputFormat,
146 (const WAVEFORMATEX*)pRequestedInputFormat, (WAVEFORMATEX**)ppSupportedInputFormat);
149 static uint32_t FAPOCALL XAPO_IsOutputFormatSupported(void *iface,
150 const FAudioWaveFormatEx *pInputFormat, const FAudioWaveFormatEx *pRequestedOutputFormat,
151 FAudioWaveFormatEx **ppSupportedOutputFormat)
153 XA2XAPOImpl *This = impl_from_FAPO(iface);
154 TRACE("%p\n", This);
155 return IXAPO_IsOutputFormatSupported(This->xapo, (const WAVEFORMATEX *)pInputFormat,
156 (const WAVEFORMATEX *)pRequestedOutputFormat, (WAVEFORMATEX**)ppSupportedOutputFormat);
159 static uint32_t FAPOCALL XAPO_Initialize(void *iface, const void *pData,
160 uint32_t DataByteSize)
162 XA2XAPOImpl *This = impl_from_FAPO(iface);
163 TRACE("%p\n", This);
164 return IXAPO_Initialize(This->xapo, pData, DataByteSize);
167 static void FAPOCALL XAPO_Reset(void *iface)
169 XA2XAPOImpl *This = impl_from_FAPO(iface);
170 TRACE("%p\n", This);
171 IXAPO_Reset(This->xapo);
174 static uint32_t FAPOCALL XAPO_LockForProcess(void *iface,
175 uint32_t InputLockedParameterCount,
176 const FAPOLockForProcessBufferParameters *pInputLockedParameters,
177 uint32_t OutputLockedParameterCount,
178 const FAPOLockForProcessBufferParameters *pOutputLockedParameters)
180 XA2XAPOImpl *This = impl_from_FAPO(iface);
181 TRACE("%p\n", This);
182 return IXAPO_LockForProcess(This->xapo,
183 InputLockedParameterCount,
184 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pInputLockedParameters,
185 OutputLockedParameterCount,
186 (const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS *)pOutputLockedParameters);
189 static void FAPOCALL XAPO_UnlockForProcess(void *iface)
191 XA2XAPOImpl *This = impl_from_FAPO(iface);
192 TRACE("%p\n", This);
193 IXAPO_UnlockForProcess(This->xapo);
196 static void FAPOCALL XAPO_Process(void *iface,
197 uint32_t InputProcessParameterCount,
198 const FAPOProcessBufferParameters* pInputProcessParameters,
199 uint32_t OutputProcessParameterCount,
200 FAPOProcessBufferParameters* pOutputProcessParameters,
201 int32_t IsEnabled)
203 XA2XAPOImpl *This = impl_from_FAPO(iface);
204 TRACE("%p\n", This);
205 IXAPO_Process(This->xapo, InputProcessParameterCount,
206 (const XAPO_PROCESS_BUFFER_PARAMETERS *)pInputProcessParameters,
207 OutputProcessParameterCount,
208 (XAPO_PROCESS_BUFFER_PARAMETERS *)pOutputProcessParameters,
209 IsEnabled);
212 static uint32_t FAPOCALL XAPO_CalcInputFrames(void *iface,
213 uint32_t OutputFrameCount)
215 XA2XAPOImpl *This = impl_from_FAPO(iface);
216 TRACE("%p\n", This);
217 return IXAPO_CalcInputFrames(This->xapo, OutputFrameCount);
220 static uint32_t FAPOCALL XAPO_CalcOutputFrames(void *iface,
221 uint32_t InputFrameCount)
223 XA2XAPOImpl *This = impl_from_FAPO(iface);
224 TRACE("%p\n", This);
225 return IXAPO_CalcOutputFrames(This->xapo, InputFrameCount);
228 static void FAPOCALL XAPO_SetParameters(void *iface,
229 const void *pParameters, uint32_t ParametersByteSize)
231 XA2XAPOImpl *This = impl_from_FAPO(iface);
232 TRACE("%p\n", This);
233 if(This->xapo_params)
234 IXAPOParameters_SetParameters(This->xapo_params, pParameters, ParametersByteSize);
237 static void FAPOCALL XAPO_GetParameters(void *iface,
238 void *pParameters, uint32_t ParametersByteSize)
240 XA2XAPOImpl *This = impl_from_FAPO(iface);
241 TRACE("%p\n", This);
242 if(This->xapo_params)
243 IXAPOParameters_GetParameters(This->xapo_params, pParameters, ParametersByteSize);
244 else
245 memset(pParameters, 0, ParametersByteSize);
248 static const FAPO FAPO_Vtbl = {
249 XAPO_AddRef,
250 XAPO_Release,
251 XAPO_GetRegistrationProperties,
252 XAPO_IsInputFormatSupported,
253 XAPO_IsOutputFormatSupported,
254 XAPO_Initialize,
255 XAPO_Reset,
256 XAPO_LockForProcess,
257 XAPO_UnlockForProcess,
258 XAPO_Process,
259 XAPO_CalcInputFrames,
260 XAPO_CalcOutputFrames,
261 XAPO_SetParameters,
262 XAPO_GetParameters,
265 static XA2XAPOImpl *wrap_xapo(IUnknown *unk)
267 XA2XAPOImpl *ret;
268 IXAPO *xapo;
269 IXAPOParameters *xapo_params;
270 HRESULT hr;
272 #if XAUDIO2_VER <= 7
273 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27, (void**)&xapo);
274 #else
275 hr = IUnknown_QueryInterface(unk, &IID_IXAPO, (void**)&xapo);
276 #endif
277 if(FAILED(hr)){
278 WARN("XAPO doesn't support IXAPO? %p\n", unk);
279 return NULL;
282 #if XAUDIO2_VER <= 7
283 hr = IUnknown_QueryInterface(unk, &IID_IXAPO27Parameters, (void**)&xapo_params);
284 #else
285 hr = IUnknown_QueryInterface(unk, &IID_IXAPOParameters, (void**)&xapo_params);
286 #endif
287 if(FAILED(hr)){
288 TRACE("XAPO doesn't support IXAPOParameters %p\n", unk);
289 xapo_params = NULL;
292 ret = malloc(sizeof(*ret));
294 ret->xapo = xapo;
295 ret->xapo_params = xapo_params;
296 ret->FAPO_vtbl = FAPO_Vtbl;
297 ret->ref = 1;
299 TRACE("wrapped IXAPO %p with %p\n", xapo, ret);
301 return ret;
304 FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
306 FAudioEffectChain *ret;
307 int i;
309 if(!pEffectChain)
310 return NULL;
312 ret = malloc(sizeof(*ret) + sizeof(FAudioEffectDescriptor) * pEffectChain->EffectCount);
314 ret->EffectCount = pEffectChain->EffectCount;
315 ret->pEffectDescriptors = (void*)(ret + 1);
317 for(i = 0; i < ret->EffectCount; ++i){
318 ret->pEffectDescriptors[i].pEffect = &wrap_xapo(pEffectChain->pEffectDescriptors[i].pEffect)->FAPO_vtbl;
319 ret->pEffectDescriptors[i].InitialState = pEffectChain->pEffectDescriptors[i].InitialState;
320 ret->pEffectDescriptors[i].OutputChannels = pEffectChain->pEffectDescriptors[i].OutputChannels;
323 return ret;
326 static void free_effect_chain(FAudioEffectChain *chain)
328 int i;
329 if(!chain)
330 return;
331 for(i = 0; i < chain->EffectCount; ++i)
332 XAPO_Release(chain->pEffectDescriptors[i].pEffect);
333 free(chain);
336 /* Send Wrapping */
338 static FAudioVoiceSends *wrap_voice_sends(const XAUDIO2_VOICE_SENDS *sends)
340 FAudioVoiceSends *ret;
341 int i;
343 if(!sends)
344 return NULL;
346 #if XAUDIO2_VER <= 3
347 ret = malloc(sizeof(*ret) + sends->OutputCount * sizeof(FAudioSendDescriptor));
348 ret->SendCount = sends->OutputCount;
349 ret->pSends = (FAudioSendDescriptor*)(ret + 1);
350 for(i = 0; i < sends->OutputCount; ++i){
351 XA2VoiceImpl *voice = impl_from_IXAudio2Voice(sends->pOutputVoices[i]);
352 ret->pSends[i].pOutputVoice = voice->faudio_voice;
353 ret->pSends[i].Flags = 0;
355 #else
356 ret = malloc(sizeof(*ret) + sends->SendCount * sizeof(FAudioSendDescriptor));
357 ret->SendCount = sends->SendCount;
358 ret->pSends = (FAudioSendDescriptor*)(ret + 1);
359 for(i = 0; i < sends->SendCount; ++i){
360 XA2VoiceImpl *voice = impl_from_IXAudio2Voice(sends->pSends[i].pOutputVoice);
361 ret->pSends[i].pOutputVoice = voice->faudio_voice;
362 ret->pSends[i].Flags = sends->pSends[i].Flags;
364 #endif
365 return ret;
368 static void free_voice_sends(FAudioVoiceSends *sends)
370 if(!sends)
371 return;
372 free(sends);
375 /* Voice Callbacks */
377 static inline XA2VoiceImpl *impl_from_FAudioVoiceCallback(FAudioVoiceCallback *iface)
379 return CONTAINING_RECORD(iface, XA2VoiceImpl, FAudioVoiceCallback_vtbl);
382 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassStart(FAudioVoiceCallback *iface,
383 UINT32 BytesRequired)
385 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
386 TRACE("%p\n", This);
387 if(This->cb)
388 IXAudio2VoiceCallback_OnVoiceProcessingPassStart(This->cb
389 #if XAUDIO2_VER > 0
390 , BytesRequired
391 #endif
395 static void FAUDIOCALL XA2VCB_OnVoiceProcessingPassEnd(FAudioVoiceCallback *iface)
397 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
398 TRACE("%p\n", This);
399 if(This->cb)
400 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(This->cb);
403 static void FAUDIOCALL XA2VCB_OnStreamEnd(FAudioVoiceCallback *iface)
405 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
406 TRACE("%p\n", This);
407 if(This->cb)
408 IXAudio2VoiceCallback_OnStreamEnd(This->cb);
411 static void FAUDIOCALL XA2VCB_OnBufferStart(FAudioVoiceCallback *iface,
412 void *pBufferContext)
414 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
415 TRACE("%p\n", This);
416 if(This->cb)
417 IXAudio2VoiceCallback_OnBufferStart(This->cb, pBufferContext);
420 static void FAUDIOCALL XA2VCB_OnBufferEnd(FAudioVoiceCallback *iface,
421 void *pBufferContext)
423 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
424 TRACE("%p\n", This);
425 if(This->cb)
426 IXAudio2VoiceCallback_OnBufferEnd(This->cb, pBufferContext);
429 static void FAUDIOCALL XA2VCB_OnLoopEnd(FAudioVoiceCallback *iface,
430 void *pBufferContext)
432 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
433 TRACE("%p\n", This);
434 if(This->cb)
435 IXAudio2VoiceCallback_OnLoopEnd(This->cb, pBufferContext);
438 static void FAUDIOCALL XA2VCB_OnVoiceError(FAudioVoiceCallback *iface,
439 void *pBufferContext, unsigned int Error)
441 XA2VoiceImpl *This = impl_from_FAudioVoiceCallback(iface);
442 TRACE("%p\n", This);
443 if(This->cb)
444 IXAudio2VoiceCallback_OnVoiceError(This->cb, pBufferContext, (HRESULT)Error);
447 static const FAudioVoiceCallback FAudioVoiceCallback_Vtbl = {
448 XA2VCB_OnBufferEnd,
449 XA2VCB_OnBufferStart,
450 XA2VCB_OnLoopEnd,
451 XA2VCB_OnStreamEnd,
452 XA2VCB_OnVoiceError,
453 XA2VCB_OnVoiceProcessingPassEnd,
454 XA2VCB_OnVoiceProcessingPassStart
457 /* Engine Callbacks */
459 static inline IXAudio2Impl *impl_from_FAudioEngineCallback(FAudioEngineCallback *iface)
461 return CONTAINING_RECORD(iface, IXAudio2Impl, FAudioEngineCallback_vtbl);
464 static void FAUDIOCALL XA2ECB_OnProcessingPassStart(FAudioEngineCallback *iface)
466 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
467 int i;
468 TRACE("%p\n", This);
469 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
470 IXAudio2EngineCallback_OnProcessingPassStart(This->cbs[i]);
473 static void FAUDIOCALL XA2ECB_OnProcessingPassEnd(FAudioEngineCallback *iface)
475 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
476 int i;
477 TRACE("%p\n", This);
478 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
479 IXAudio2EngineCallback_OnProcessingPassEnd(This->cbs[i]);
482 static void FAUDIOCALL XA2ECB_OnCriticalError(FAudioEngineCallback *iface,
483 uint32_t error)
485 IXAudio2Impl *This = impl_from_FAudioEngineCallback(iface);
486 int i;
487 TRACE("%p\n", This);
488 for(i = 0; i < This->ncbs && This->cbs[i]; ++i)
489 IXAudio2EngineCallback_OnCriticalError(This->cbs[i], error);
492 static const FAudioEngineCallback FAudioEngineCallback_Vtbl = {
493 XA2ECB_OnCriticalError,
494 XA2ECB_OnProcessingPassEnd,
495 XA2ECB_OnProcessingPassStart
498 /* Common Voice Functions */
500 static inline void destroy_voice(XA2VoiceImpl *This)
502 FAudioVoice_DestroyVoice(This->faudio_voice);
503 free_effect_chain(This->effect_chain);
504 This->effect_chain = NULL;
505 This->in_use = FALSE;
508 static void get_voice_details(XA2VoiceImpl *voice, XAUDIO2_VOICE_DETAILS *details)
510 FAudioVoiceDetails faudio_details;
512 TRACE("%p, %p\n", voice, details);
514 FAudioVoice_GetVoiceDetails(voice->faudio_voice, &faudio_details);
515 details->CreationFlags = faudio_details.CreationFlags;
516 #if XAUDIO2_VER >= 8
517 details->ActiveFlags = faudio_details.ActiveFlags;
518 #endif
519 details->InputChannels = faudio_details.InputChannels;
520 details->InputSampleRate = faudio_details.InputSampleRate;
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, XAUDIO2_VOICE_DETAILS *details)
532 XA2VoiceImpl *voice = impl_from_IXAudio2SourceVoice(iface);
534 get_voice_details(voice, details);
537 static HRESULT WINAPI XA2SRC_SetOutputVoices(IXAudio2SourceVoice *iface,
538 const XAUDIO2_VOICE_SENDS *pSendList)
540 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
541 FAudioVoiceSends *faudio_sends;
542 HRESULT hr;
544 TRACE("%p, %p\n", This, pSendList);
546 faudio_sends = wrap_voice_sends(pSendList);
548 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
550 free_voice_sends(faudio_sends);
552 return hr;
555 static HRESULT WINAPI XA2SRC_SetEffectChain(IXAudio2SourceVoice *iface,
556 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
558 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
559 HRESULT hr;
561 TRACE("%p, %p\n", This, pEffectChain);
563 free_effect_chain(This->effect_chain);
564 This->effect_chain = wrap_effect_chain(pEffectChain);
566 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
568 return hr;
571 static HRESULT WINAPI XA2SRC_EnableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
572 UINT32 OperationSet)
574 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
575 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
576 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
579 static HRESULT WINAPI XA2SRC_DisableEffect(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
580 UINT32 OperationSet)
582 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
583 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
584 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
587 static void WINAPI XA2SRC_GetEffectState(IXAudio2SourceVoice *iface, UINT32 EffectIndex,
588 BOOL *pEnabled)
590 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
591 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
592 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
595 static HRESULT WINAPI XA2SRC_SetEffectParameters(IXAudio2SourceVoice *iface,
596 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
597 UINT32 OperationSet)
599 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
600 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
601 ParametersByteSize, OperationSet);
602 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
603 pParameters, ParametersByteSize, OperationSet);
606 static HRESULT WINAPI XA2SRC_GetEffectParameters(IXAudio2SourceVoice *iface,
607 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
609 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
610 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
611 ParametersByteSize);
612 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
613 pParameters, ParametersByteSize);
616 static HRESULT WINAPI XA2SRC_SetFilterParameters(IXAudio2SourceVoice *iface,
617 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
619 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
620 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
621 return FAudioVoice_SetFilterParameters(This->faudio_voice,
622 (const FAudioFilterParameters *)pParameters, OperationSet);
625 static void WINAPI XA2SRC_GetFilterParameters(IXAudio2SourceVoice *iface,
626 XAUDIO2_FILTER_PARAMETERS *pParameters)
628 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
629 TRACE("%p, %p\n", This, pParameters);
630 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
633 #if XAUDIO2_VER >= 4
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);
659 #endif
661 static HRESULT WINAPI XA2SRC_SetVolume(IXAudio2SourceVoice *iface, float Volume,
662 UINT32 OperationSet)
664 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
665 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
666 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
669 static void WINAPI XA2SRC_GetVolume(IXAudio2SourceVoice *iface, float *pVolume)
671 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
672 TRACE("%p, %p\n", This, pVolume);
673 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
676 static HRESULT WINAPI XA2SRC_SetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
677 const float *pVolumes, UINT32 OperationSet)
679 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
680 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
681 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
682 pVolumes, OperationSet);
685 static void WINAPI XA2SRC_GetChannelVolumes(IXAudio2SourceVoice *iface, UINT32 Channels,
686 float *pVolumes)
688 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
689 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
690 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
691 pVolumes);
694 static HRESULT WINAPI XA2SRC_SetOutputMatrix(IXAudio2SourceVoice *iface,
695 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
696 UINT32 DestinationChannels, const float *pLevelMatrix,
697 UINT32 OperationSet)
699 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
700 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
702 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
703 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
705 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
706 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
709 #if XAUDIO2_VER == 0
710 static HRESULT
711 #else
712 static void
713 #endif
714 WINAPI XA2SRC_GetOutputMatrix(IXAudio2SourceVoice *iface,
715 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
716 UINT32 DestinationChannels, float *pLevelMatrix)
718 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
719 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
721 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
722 SourceChannels, DestinationChannels, pLevelMatrix);
724 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
725 SourceChannels, DestinationChannels, pLevelMatrix);
726 #if XAUDIO2_VER == 0
727 return S_OK;
728 #endif
731 static void WINAPI XA2SRC_DestroyVoice(IXAudio2SourceVoice *iface)
733 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
735 TRACE("%p\n", This);
737 EnterCriticalSection(&This->lock);
739 destroy_voice(This);
741 LeaveCriticalSection(&This->lock);
744 static HRESULT WINAPI XA2SRC_Start(IXAudio2SourceVoice *iface, UINT32 Flags,
745 UINT32 OperationSet)
747 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
749 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
751 return FAudioSourceVoice_Start(This->faudio_voice, Flags, OperationSet);
754 static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
755 UINT32 OperationSet)
757 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
759 TRACE("%p, 0x%x, 0x%x\n", This, Flags, OperationSet);
761 return FAudioSourceVoice_Stop(This->faudio_voice, Flags, OperationSet);
764 static HRESULT WINAPI XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice *iface,
765 const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA)
767 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
769 TRACE("%p, %p, %p\n", This, pBuffer, pBufferWMA);
771 return FAudioSourceVoice_SubmitSourceBuffer(This->faudio_voice, (FAudioBuffer*)pBuffer, (FAudioBufferWMA*)pBufferWMA);
774 static HRESULT WINAPI XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice *iface)
776 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
778 TRACE("%p\n", This);
780 return FAudioSourceVoice_FlushSourceBuffers(This->faudio_voice);
783 static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
785 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
787 TRACE("%p\n", This);
789 return FAudioSourceVoice_Discontinuity(This->faudio_voice);
792 static HRESULT WINAPI XA2SRC_ExitLoop(IXAudio2SourceVoice *iface, UINT32 OperationSet)
794 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
796 TRACE("%p, 0x%x\n", This, OperationSet);
798 return FAudioSourceVoice_ExitLoop(This->faudio_voice, OperationSet);
801 #if XAUDIO2_VER >= 8
802 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface, XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags)
803 #else
804 static void WINAPI XA2SRC_GetState(IXAudio2SourceVoice *iface, XAUDIO2_VOICE_STATE *pVoiceState)
805 #endif
807 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
808 #if XAUDIO2_VER < 8
809 UINT32 Flags = 0;
810 #endif
812 TRACE("%p, %p, 0x%x\n", This, pVoiceState, Flags);
814 return FAudioSourceVoice_GetState(This->faudio_voice, (FAudioVoiceState*)pVoiceState, Flags);
817 static HRESULT WINAPI XA2SRC_SetFrequencyRatio(IXAudio2SourceVoice *iface,
818 float Ratio, UINT32 OperationSet)
820 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
822 TRACE("%p, %f, 0x%x\n", This, Ratio, OperationSet);
824 return FAudioSourceVoice_SetFrequencyRatio(This->faudio_voice, Ratio, OperationSet);
827 static void WINAPI XA2SRC_GetFrequencyRatio(IXAudio2SourceVoice *iface, float *pRatio)
829 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
831 TRACE("%p, %p\n", This, pRatio);
833 return FAudioSourceVoice_GetFrequencyRatio(This->faudio_voice, pRatio);
836 #if XAUDIO2_VER >= 4
837 static HRESULT WINAPI XA2SRC_SetSourceSampleRate(
838 IXAudio2SourceVoice *iface,
839 UINT32 NewSourceSampleRate)
841 XA2VoiceImpl *This = impl_from_IXAudio2SourceVoice(iface);
843 TRACE("%p, %u\n", This, NewSourceSampleRate);
845 return FAudioSourceVoice_SetSourceSampleRate(This->faudio_voice, NewSourceSampleRate);
847 #endif
849 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl = {
850 XA2SRC_GetVoiceDetails,
851 XA2SRC_SetOutputVoices,
852 XA2SRC_SetEffectChain,
853 XA2SRC_EnableEffect,
854 XA2SRC_DisableEffect,
855 XA2SRC_GetEffectState,
856 XA2SRC_SetEffectParameters,
857 XA2SRC_GetEffectParameters,
858 XA2SRC_SetFilterParameters,
859 XA2SRC_GetFilterParameters,
860 #if XAUDIO2_VER >= 4
861 XA2SRC_SetOutputFilterParameters,
862 XA2SRC_GetOutputFilterParameters,
863 #endif
864 XA2SRC_SetVolume,
865 XA2SRC_GetVolume,
866 XA2SRC_SetChannelVolumes,
867 XA2SRC_GetChannelVolumes,
868 XA2SRC_SetOutputMatrix,
869 XA2SRC_GetOutputMatrix,
870 XA2SRC_DestroyVoice,
871 XA2SRC_Start,
872 XA2SRC_Stop,
873 XA2SRC_SubmitSourceBuffer,
874 XA2SRC_FlushSourceBuffers,
875 XA2SRC_Discontinuity,
876 XA2SRC_ExitLoop,
877 XA2SRC_GetState,
878 XA2SRC_SetFrequencyRatio,
879 XA2SRC_GetFrequencyRatio,
880 #if XAUDIO2_VER >= 4
881 XA2SRC_SetSourceSampleRate
882 #endif
885 /* Submix Voices */
887 static inline XA2VoiceImpl *impl_from_IXAudio2SubmixVoice(IXAudio2SubmixVoice *iface)
889 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2SubmixVoice_iface);
892 static void WINAPI XA2SUB_GetVoiceDetails(IXAudio2SubmixVoice *iface, XAUDIO2_VOICE_DETAILS *details)
894 XA2VoiceImpl *voice = impl_from_IXAudio2SubmixVoice(iface);
896 get_voice_details(voice, details);
899 static HRESULT WINAPI XA2SUB_SetOutputVoices(IXAudio2SubmixVoice *iface,
900 const XAUDIO2_VOICE_SENDS *pSendList)
902 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
903 FAudioVoiceSends *faudio_sends;
904 HRESULT hr;
906 TRACE("%p, %p\n", This, pSendList);
908 faudio_sends = wrap_voice_sends(pSendList);
910 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
912 free_voice_sends(faudio_sends);
914 return hr;
917 static HRESULT WINAPI XA2SUB_SetEffectChain(IXAudio2SubmixVoice *iface,
918 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
920 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
921 HRESULT hr;
923 TRACE("%p, %p\n", This, pEffectChain);
925 free_effect_chain(This->effect_chain);
926 This->effect_chain = wrap_effect_chain(pEffectChain);
928 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
930 return hr;
933 static HRESULT WINAPI XA2SUB_EnableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
934 UINT32 OperationSet)
936 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
937 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
938 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
941 static HRESULT WINAPI XA2SUB_DisableEffect(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
942 UINT32 OperationSet)
944 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
945 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
946 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
949 static void WINAPI XA2SUB_GetEffectState(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
950 BOOL *pEnabled)
952 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
953 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
954 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
957 static HRESULT WINAPI XA2SUB_SetEffectParameters(IXAudio2SubmixVoice *iface,
958 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
959 UINT32 OperationSet)
961 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
962 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
963 ParametersByteSize, OperationSet);
964 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
965 pParameters, ParametersByteSize, OperationSet);
968 static HRESULT WINAPI XA2SUB_GetEffectParameters(IXAudio2SubmixVoice *iface,
969 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
971 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
972 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
973 ParametersByteSize);
974 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
975 pParameters, ParametersByteSize);
978 static HRESULT WINAPI XA2SUB_SetFilterParameters(IXAudio2SubmixVoice *iface,
979 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
981 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
982 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
983 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
984 OperationSet);
987 static void WINAPI XA2SUB_GetFilterParameters(IXAudio2SubmixVoice *iface,
988 XAUDIO2_FILTER_PARAMETERS *pParameters)
990 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
991 TRACE("%p, %p\n", This, pParameters);
992 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
995 #if XAUDIO2_VER >= 4
996 static HRESULT WINAPI XA2SUB_SetOutputFilterParameters(IXAudio2SubmixVoice *iface,
997 IXAudio2Voice *pDestinationVoice,
998 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1000 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1001 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1003 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
1005 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
1006 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
1009 static void WINAPI XA2SUB_GetOutputFilterParameters(IXAudio2SubmixVoice *iface,
1010 IXAudio2Voice *pDestinationVoice,
1011 XAUDIO2_FILTER_PARAMETERS *pParameters)
1013 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1014 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1016 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
1018 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
1019 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1021 #endif
1023 static HRESULT WINAPI XA2SUB_SetVolume(IXAudio2SubmixVoice *iface, float Volume,
1024 UINT32 OperationSet)
1026 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1027 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1028 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1031 static void WINAPI XA2SUB_GetVolume(IXAudio2SubmixVoice *iface, float *pVolume)
1033 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1034 TRACE("%p, %p\n", This, pVolume);
1035 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1038 static HRESULT WINAPI XA2SUB_SetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1039 const float *pVolumes, UINT32 OperationSet)
1041 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1042 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1043 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1044 pVolumes, OperationSet);
1047 static void WINAPI XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1048 float *pVolumes)
1050 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1051 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1052 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1053 pVolumes);
1056 static HRESULT WINAPI XA2SUB_SetOutputMatrix(IXAudio2SubmixVoice *iface,
1057 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1058 UINT32 DestinationChannels, const float *pLevelMatrix,
1059 UINT32 OperationSet)
1061 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1062 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1064 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1065 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1067 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1068 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1071 #if XAUDIO2_VER == 0
1072 static HRESULT
1073 #else
1074 static void
1075 #endif
1076 WINAPI XA2SUB_GetOutputMatrix(IXAudio2SubmixVoice *iface,
1077 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1078 UINT32 DestinationChannels, float *pLevelMatrix)
1080 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1081 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1083 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1084 SourceChannels, DestinationChannels, pLevelMatrix);
1086 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1087 SourceChannels, DestinationChannels, pLevelMatrix);
1088 #if XAUDIO2_VER == 0
1089 return S_OK;
1090 #endif
1093 static void WINAPI XA2SUB_DestroyVoice(IXAudio2SubmixVoice *iface)
1095 XA2VoiceImpl *This = impl_from_IXAudio2SubmixVoice(iface);
1097 TRACE("%p\n", This);
1099 EnterCriticalSection(&This->lock);
1101 destroy_voice(This);
1103 LeaveCriticalSection(&This->lock);
1106 static const struct IXAudio2SubmixVoiceVtbl XAudio2SubmixVoice_Vtbl = {
1107 XA2SUB_GetVoiceDetails,
1108 XA2SUB_SetOutputVoices,
1109 XA2SUB_SetEffectChain,
1110 XA2SUB_EnableEffect,
1111 XA2SUB_DisableEffect,
1112 XA2SUB_GetEffectState,
1113 XA2SUB_SetEffectParameters,
1114 XA2SUB_GetEffectParameters,
1115 XA2SUB_SetFilterParameters,
1116 XA2SUB_GetFilterParameters,
1117 #if XAUDIO2_VER >= 4
1118 XA2SUB_SetOutputFilterParameters,
1119 XA2SUB_GetOutputFilterParameters,
1120 #endif
1121 XA2SUB_SetVolume,
1122 XA2SUB_GetVolume,
1123 XA2SUB_SetChannelVolumes,
1124 XA2SUB_GetChannelVolumes,
1125 XA2SUB_SetOutputMatrix,
1126 XA2SUB_GetOutputMatrix,
1127 XA2SUB_DestroyVoice
1130 /* Mastering Voices */
1132 static inline XA2VoiceImpl *impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice *iface)
1134 return CONTAINING_RECORD(iface, XA2VoiceImpl, IXAudio2MasteringVoice_iface);
1137 static void WINAPI XA2M_GetVoiceDetails(IXAudio2MasteringVoice *iface, XAUDIO2_VOICE_DETAILS *details)
1139 XA2VoiceImpl *voice = impl_from_IXAudio2MasteringVoice(iface);
1141 get_voice_details(voice, details);
1144 static HRESULT WINAPI XA2M_SetOutputVoices(IXAudio2MasteringVoice *iface,
1145 const XAUDIO2_VOICE_SENDS *pSendList)
1147 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1148 FAudioVoiceSends *faudio_sends;
1149 HRESULT hr;
1151 TRACE("%p, %p\n", This, pSendList);
1153 faudio_sends = wrap_voice_sends(pSendList);
1155 hr = FAudioVoice_SetOutputVoices(This->faudio_voice, faudio_sends);
1157 free_voice_sends(faudio_sends);
1159 return hr;
1162 static HRESULT WINAPI XA2M_SetEffectChain(IXAudio2MasteringVoice *iface,
1163 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1165 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1166 HRESULT hr;
1168 TRACE("%p, %p\n", This, pEffectChain);
1170 free_effect_chain(This->effect_chain);
1171 This->effect_chain = wrap_effect_chain(pEffectChain);
1173 hr = FAudioVoice_SetEffectChain(This->faudio_voice, This->effect_chain);
1175 return hr;
1178 static HRESULT WINAPI XA2M_EnableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1179 UINT32 OperationSet)
1181 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1182 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1183 return FAudioVoice_EnableEffect(This->faudio_voice, EffectIndex, OperationSet);
1186 static HRESULT WINAPI XA2M_DisableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1187 UINT32 OperationSet)
1189 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1190 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1191 return FAudioVoice_DisableEffect(This->faudio_voice, EffectIndex, OperationSet);
1194 static void WINAPI XA2M_GetEffectState(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1195 BOOL *pEnabled)
1197 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1198 TRACE("%p, %u, %p\n", This, EffectIndex, pEnabled);
1199 FAudioVoice_GetEffectState(This->faudio_voice, EffectIndex, (int32_t*)pEnabled);
1202 static HRESULT WINAPI XA2M_SetEffectParameters(IXAudio2MasteringVoice *iface,
1203 UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize,
1204 UINT32 OperationSet)
1206 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1207 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
1208 ParametersByteSize, OperationSet);
1209 return FAudioVoice_SetEffectParameters(This->faudio_voice, EffectIndex,
1210 pParameters, ParametersByteSize, OperationSet);
1213 static HRESULT WINAPI XA2M_GetEffectParameters(IXAudio2MasteringVoice *iface,
1214 UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize)
1216 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1217 TRACE("%p, %u, %p, 0x%x\n", This, EffectIndex, pParameters,
1218 ParametersByteSize);
1219 return FAudioVoice_GetEffectParameters(This->faudio_voice, EffectIndex,
1220 pParameters, ParametersByteSize);
1223 static HRESULT WINAPI XA2M_SetFilterParameters(IXAudio2MasteringVoice *iface,
1224 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1226 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1227 TRACE("%p, %p, 0x%x\n", This, pParameters, OperationSet);
1228 return FAudioVoice_SetFilterParameters(This->faudio_voice, (const FAudioFilterParameters *)pParameters,
1229 OperationSet);
1232 static void WINAPI XA2M_GetFilterParameters(IXAudio2MasteringVoice *iface,
1233 XAUDIO2_FILTER_PARAMETERS *pParameters)
1235 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1236 TRACE("%p, %p\n", This, pParameters);
1237 FAudioVoice_GetFilterParameters(This->faudio_voice, (FAudioFilterParameters *)pParameters);
1240 #if XAUDIO2_VER >= 4
1241 static HRESULT WINAPI XA2M_SetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1242 IXAudio2Voice *pDestinationVoice,
1243 const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet)
1245 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1246 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1248 TRACE("%p, %p, %p, 0x%x\n", This, pDestinationVoice, pParameters, OperationSet);
1250 return FAudioVoice_SetOutputFilterParameters(This->faudio_voice,
1251 dst ? dst->faudio_voice : NULL, (const FAudioFilterParameters *)pParameters, OperationSet);
1254 static void WINAPI XA2M_GetOutputFilterParameters(IXAudio2MasteringVoice *iface,
1255 IXAudio2Voice *pDestinationVoice,
1256 XAUDIO2_FILTER_PARAMETERS *pParameters)
1258 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1259 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1261 TRACE("%p, %p, %p\n", This, pDestinationVoice, pParameters);
1263 FAudioVoice_GetOutputFilterParameters(This->faudio_voice,
1264 dst ? dst->faudio_voice : NULL, (FAudioFilterParameters *)pParameters);
1266 #endif
1268 static HRESULT WINAPI XA2M_SetVolume(IXAudio2MasteringVoice *iface, float Volume,
1269 UINT32 OperationSet)
1271 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1272 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
1273 return FAudioVoice_SetVolume(This->faudio_voice, Volume, OperationSet);
1276 static void WINAPI XA2M_GetVolume(IXAudio2MasteringVoice *iface, float *pVolume)
1278 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1279 TRACE("%p, %p\n", This, pVolume);
1280 return FAudioVoice_GetVolume(This->faudio_voice, pVolume);
1283 static HRESULT WINAPI XA2M_SetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1284 const float *pVolumes, UINT32 OperationSet)
1286 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1287 TRACE("%p, %u, %p, 0x%x\n", This, Channels, pVolumes, OperationSet);
1288 return FAudioVoice_SetChannelVolumes(This->faudio_voice, Channels,
1289 pVolumes, OperationSet);
1292 static void WINAPI XA2M_GetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1293 float *pVolumes)
1295 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1296 TRACE("%p, %u, %p\n", This, Channels, pVolumes);
1297 return FAudioVoice_GetChannelVolumes(This->faudio_voice, Channels,
1298 pVolumes);
1301 static HRESULT WINAPI XA2M_SetOutputMatrix(IXAudio2MasteringVoice *iface,
1302 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1303 UINT32 DestinationChannels, const float *pLevelMatrix,
1304 UINT32 OperationSet)
1306 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1307 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1309 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
1310 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1312 return FAudioVoice_SetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1313 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
1316 #if XAUDIO2_VER == 0
1317 static HRESULT
1318 #else
1319 static void
1320 #endif
1321 WINAPI XA2M_GetOutputMatrix(IXAudio2MasteringVoice *iface,
1322 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
1323 UINT32 DestinationChannels, float *pLevelMatrix)
1325 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1326 XA2VoiceImpl *dst = pDestinationVoice ? impl_from_IXAudio2Voice(pDestinationVoice) : NULL;
1328 TRACE("%p, %p, %u, %u, %p\n", This, pDestinationVoice,
1329 SourceChannels, DestinationChannels, pLevelMatrix);
1331 FAudioVoice_GetOutputMatrix(This->faudio_voice, dst ? dst->faudio_voice : NULL,
1332 SourceChannels, DestinationChannels, pLevelMatrix);
1333 #if XAUDIO2_VER == 0
1334 return S_OK;
1335 #endif
1338 static void WINAPI XA2M_DestroyVoice(IXAudio2MasteringVoice *iface)
1340 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1342 TRACE("%p\n", This);
1344 EnterCriticalSection(&This->lock);
1346 destroy_voice(This);
1348 LeaveCriticalSection(&This->lock);
1351 #if XAUDIO2_VER >= 8
1352 static void WINAPI XA2M_GetChannelMask(IXAudio2MasteringVoice *iface,
1353 DWORD *pChannelMask)
1355 XA2VoiceImpl *This = impl_from_IXAudio2MasteringVoice(iface);
1357 TRACE("%p, %p\n", This, pChannelMask);
1359 FAudioMasteringVoice_GetChannelMask(This->faudio_voice, (uint32_t *)pChannelMask);
1361 #endif
1363 static const struct IXAudio2MasteringVoiceVtbl XAudio2MasteringVoice_Vtbl = {
1364 XA2M_GetVoiceDetails,
1365 XA2M_SetOutputVoices,
1366 XA2M_SetEffectChain,
1367 XA2M_EnableEffect,
1368 XA2M_DisableEffect,
1369 XA2M_GetEffectState,
1370 XA2M_SetEffectParameters,
1371 XA2M_GetEffectParameters,
1372 XA2M_SetFilterParameters,
1373 XA2M_GetFilterParameters,
1374 #if XAUDIO2_VER >= 4
1375 XA2M_SetOutputFilterParameters,
1376 XA2M_GetOutputFilterParameters,
1377 #endif
1378 XA2M_SetVolume,
1379 XA2M_GetVolume,
1380 XA2M_SetChannelVolumes,
1381 XA2M_GetChannelVolumes,
1382 XA2M_SetOutputMatrix,
1383 XA2M_GetOutputMatrix,
1384 XA2M_DestroyVoice,
1385 #if XAUDIO2_VER >= 8
1386 XA2M_GetChannelMask
1387 #endif
1390 /* More Common Voice Functions */
1392 static XA2VoiceImpl *impl_from_IXAudio2Voice(IXAudio2Voice *iface)
1394 if(iface->lpVtbl == (void*)&XAudio2SourceVoice_Vtbl)
1395 return impl_from_IXAudio2SourceVoice((IXAudio2SourceVoice*)iface);
1396 if(iface->lpVtbl == (void*)&XAudio2MasteringVoice_Vtbl)
1397 return impl_from_IXAudio2MasteringVoice((IXAudio2MasteringVoice*)iface);
1398 if(iface->lpVtbl == (void*)&XAudio2SubmixVoice_Vtbl)
1399 return impl_from_IXAudio2SubmixVoice((IXAudio2SubmixVoice*)iface);
1400 ERR("invalid IXAudio2Voice pointer: %p\n", iface);
1401 return NULL;
1404 /* XAudio2 Engine Implementation */
1406 static inline IXAudio2Impl *impl_from_IXAudio2(IXAudio2 *iface)
1408 return CONTAINING_RECORD(iface, IXAudio2Impl, IXAudio2_iface);
1411 static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
1412 void **ppvObject)
1414 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1416 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1418 if(IsEqualGUID(riid, &IID_IUnknown) ||
1419 IsEqualGUID(riid, &IID_IXAudio2))
1420 *ppvObject = &This->IXAudio2_iface;
1421 else
1422 *ppvObject = NULL;
1424 if(*ppvObject){
1425 IUnknown_AddRef((IUnknown*)*ppvObject);
1426 return S_OK;
1429 FIXME("(%p)->(%s,%p), not found\n", This,debugstr_guid(riid), ppvObject);
1431 return E_NOINTERFACE;
1434 static ULONG WINAPI IXAudio2Impl_AddRef(IXAudio2 *iface)
1436 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1437 ULONG ref = FAudio_AddRef(This->faudio);
1438 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1439 return ref;
1442 static ULONG WINAPI IXAudio2Impl_Release(IXAudio2 *iface)
1444 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1445 ULONG ref = FAudio_Release(This->faudio);
1447 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1449 if (!ref) {
1450 XA2VoiceImpl *v, *v2;
1452 LIST_FOR_EACH_ENTRY_SAFE(v, v2, &This->voices, XA2VoiceImpl, entry){
1453 v->lock.DebugInfo->Spare[0] = 0;
1454 DeleteCriticalSection(&v->lock);
1455 free(v);
1458 free(This->cbs);
1460 This->lock.DebugInfo->Spare[0] = 0;
1461 DeleteCriticalSection(&This->lock);
1463 free(This);
1465 return ref;
1468 #if XAUDIO2_VER <= 7
1469 static HRESULT WINAPI IXAudio2Impl_GetDeviceCount(IXAudio2 *iface, UINT32 *count)
1471 IXAudio2Impl *audio = impl_from_IXAudio2(iface);
1473 TRACE("%p, %p\n", audio, count);
1475 return FAudio_GetDeviceCount(audio->faudio, count);
1478 static HRESULT WINAPI IXAudio2Impl_GetDeviceDetails(IXAudio2 *iface, UINT32 index,
1479 XAUDIO2_DEVICE_DETAILS *details)
1481 IXAudio2Impl *audio = impl_from_IXAudio2(iface);
1483 TRACE("%p, %u, %p\n", audio, index, details);
1485 return FAudio_GetDeviceDetails(audio->faudio, index, (FAudioDeviceDetails *)details);
1488 static HRESULT WINAPI IXAudio2Impl_Initialize(IXAudio2 *iface, UINT32 flags, XAUDIO2_PROCESSOR processor)
1490 IXAudio2Impl *audio = impl_from_IXAudio2(iface);
1492 TRACE("%p, %#x, %#x\n", audio, flags, processor);
1494 return xaudio2_initialize(audio, flags, processor);
1496 #endif
1498 static HRESULT WINAPI IXAudio2Impl_RegisterForCallbacks(IXAudio2 *iface,
1499 IXAudio2EngineCallback *pCallback)
1501 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1502 int i;
1504 TRACE("(%p)->(%p)\n", This, pCallback);
1506 EnterCriticalSection(&This->lock);
1508 for(i = 0; i < This->ncbs; ++i){
1509 if(!This->cbs[i] || This->cbs[i] == pCallback){
1510 This->cbs[i] = pCallback;
1511 LeaveCriticalSection(&This->lock);
1512 return S_OK;
1516 This->ncbs++;
1517 This->cbs = realloc(This->cbs, This->ncbs * sizeof(*This->cbs));
1519 This->cbs[i] = pCallback;
1521 LeaveCriticalSection(&This->lock);
1523 return S_OK;
1526 static void WINAPI IXAudio2Impl_UnregisterForCallbacks(IXAudio2 *iface,
1527 IXAudio2EngineCallback *pCallback)
1529 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1530 int i;
1532 TRACE("(%p)->(%p)\n", This, pCallback);
1534 EnterCriticalSection(&This->lock);
1536 if(This->ncbs == 0){
1537 LeaveCriticalSection(&This->lock);
1538 return;
1541 for(i = 0; i < This->ncbs; ++i){
1542 if(This->cbs[i] == pCallback)
1543 break;
1546 for(; i < This->ncbs - 1 && This->cbs[i + 1]; ++i)
1547 This->cbs[i] = This->cbs[i + 1];
1549 if(i < This->ncbs)
1550 This->cbs[i] = NULL;
1552 LeaveCriticalSection(&This->lock);
1555 static inline XA2VoiceImpl *create_voice(IXAudio2Impl *This)
1557 XA2VoiceImpl *voice;
1559 voice = calloc(1, sizeof(*voice));
1560 if(!voice)
1561 return NULL;
1563 list_add_head(&This->voices, &voice->entry);
1565 voice->IXAudio2SourceVoice_iface.lpVtbl = &XAudio2SourceVoice_Vtbl;
1566 voice->IXAudio2SubmixVoice_iface.lpVtbl = &XAudio2SubmixVoice_Vtbl;
1567 voice->FAudioVoiceCallback_vtbl = FAudioVoiceCallback_Vtbl;
1569 InitializeCriticalSection(&voice->lock);
1570 voice->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2VoiceImpl.lock");
1572 return voice;
1575 static HRESULT WINAPI IXAudio2Impl_CreateSourceVoice(IXAudio2 *iface,
1576 IXAudio2SourceVoice **ppSourceVoice, const WAVEFORMATEX *pSourceFormat,
1577 UINT32 flags, float maxFrequencyRatio,
1578 IXAudio2VoiceCallback *pCallback, const XAUDIO2_VOICE_SENDS *pSendList,
1579 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1581 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1582 XA2VoiceImpl *src;
1583 HRESULT hr;
1584 FAudioVoiceSends *faudio_sends;
1586 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This, ppSourceVoice,
1587 pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
1588 pEffectChain);
1590 EnterCriticalSection(&This->lock);
1592 LIST_FOR_EACH_ENTRY(src, &This->voices, XA2VoiceImpl, entry){
1593 EnterCriticalSection(&src->lock);
1594 if(!src->in_use)
1595 break;
1596 LeaveCriticalSection(&src->lock);
1599 if(&src->entry == &This->voices){
1600 src = create_voice(This);
1601 EnterCriticalSection(&src->lock);
1604 LeaveCriticalSection(&This->lock);
1606 src->effect_chain = wrap_effect_chain(pEffectChain);
1607 faudio_sends = wrap_voice_sends(pSendList);
1609 hr = FAudio_CreateSourceVoice(This->faudio, &src->faudio_voice,
1610 (FAudioWaveFormatEx*)pSourceFormat, flags, maxFrequencyRatio,
1611 &src->FAudioVoiceCallback_vtbl, faudio_sends,
1612 src->effect_chain);
1613 free_voice_sends(faudio_sends);
1614 if(FAILED(hr)){
1615 LeaveCriticalSection(&This->lock);
1616 return hr;
1618 src->in_use = TRUE;
1619 src->cb = pCallback;
1621 LeaveCriticalSection(&src->lock);
1623 *ppSourceVoice = &src->IXAudio2SourceVoice_iface;
1625 TRACE("Created source voice: %p\n", src);
1627 return S_OK;
1630 static HRESULT WINAPI IXAudio2Impl_CreateSubmixVoice(IXAudio2 *iface,
1631 IXAudio2SubmixVoice **ppSubmixVoice, UINT32 inputChannels,
1632 UINT32 inputSampleRate, UINT32 flags, UINT32 processingStage,
1633 const XAUDIO2_VOICE_SENDS *pSendList,
1634 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
1636 HRESULT hr;
1637 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1638 XA2VoiceImpl *sub;
1639 FAudioVoiceSends *faudio_sends;
1641 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This, ppSubmixVoice,
1642 inputChannels, inputSampleRate, flags, processingStage, pSendList,
1643 pEffectChain);
1645 EnterCriticalSection(&This->lock);
1647 LIST_FOR_EACH_ENTRY(sub, &This->voices, XA2VoiceImpl, entry){
1648 EnterCriticalSection(&sub->lock);
1649 if(!sub->in_use)
1650 break;
1651 LeaveCriticalSection(&sub->lock);
1654 if(&sub->entry == &This->voices){
1655 sub = create_voice(This);
1656 EnterCriticalSection(&sub->lock);
1659 LeaveCriticalSection(&This->lock);
1661 sub->effect_chain = wrap_effect_chain(pEffectChain);
1662 faudio_sends = wrap_voice_sends(pSendList);
1664 hr = FAudio_CreateSubmixVoice(This->faudio, &sub->faudio_voice, inputChannels,
1665 inputSampleRate, flags, processingStage, faudio_sends,
1666 sub->effect_chain);
1667 free_voice_sends(faudio_sends);
1668 if(FAILED(hr)){
1669 LeaveCriticalSection(&sub->lock);
1670 return hr;
1672 sub->in_use = TRUE;
1674 LeaveCriticalSection(&sub->lock);
1676 *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
1678 TRACE("Created submix voice: %p\n", sub);
1680 return S_OK;
1683 static HRESULT WINAPI IXAudio2Impl_CreateMasteringVoice(IXAudio2 *iface,
1684 IXAudio2MasteringVoice **ppMasteringVoice, UINT32 inputChannels,
1685 UINT32 inputSampleRate, UINT32 flags,
1686 #if XAUDIO2_VER >= 8
1687 const WCHAR *deviceId,
1688 #else
1689 UINT32 index,
1690 #endif
1691 const XAUDIO2_EFFECT_CHAIN *pEffectChain
1692 #if XAUDIO2_VER >= 8
1693 , AUDIO_STREAM_CATEGORY streamCategory
1694 #endif
1697 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1699 TRACE("(%p)->(%p, %u, %u, 0x%x, %p)\n", This,
1700 ppMasteringVoice, inputChannels, inputSampleRate, flags, pEffectChain);
1702 EnterCriticalSection(&This->lock);
1704 *ppMasteringVoice = &This->mst.IXAudio2MasteringVoice_iface;
1706 EnterCriticalSection(&This->mst.lock);
1708 if(This->mst.in_use){
1709 LeaveCriticalSection(&This->mst.lock);
1710 LeaveCriticalSection(&This->lock);
1711 return COMPAT_E_INVALID_CALL;
1714 LeaveCriticalSection(&This->lock);
1716 This->mst.effect_chain = wrap_effect_chain(pEffectChain);
1718 #if XAUDIO2_VER >= 8
1719 TRACE("device id %s, category %#x\n", debugstr_w(deviceId), streamCategory);
1721 FAudio_CreateMasteringVoice8(This->faudio, &This->mst.faudio_voice, inputChannels,
1722 inputSampleRate, flags, NULL /* TODO: (uint16_t*)deviceId */,
1723 This->mst.effect_chain, (FAudioStreamCategory)streamCategory);
1724 #else
1725 TRACE("device index %u\n", index);
1727 FAudio_CreateMasteringVoice(This->faudio, &This->mst.faudio_voice, inputChannels,
1728 inputSampleRate, flags, index, This->mst.effect_chain);
1729 #endif
1731 This->mst.in_use = TRUE;
1733 LeaveCriticalSection(&This->mst.lock);
1735 return S_OK;
1738 static HRESULT WINAPI IXAudio2Impl_StartEngine(IXAudio2 *iface)
1740 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1742 TRACE("(%p)->()\n", This);
1744 return FAudio_StartEngine(This->faudio);
1747 static void WINAPI IXAudio2Impl_StopEngine(IXAudio2 *iface)
1749 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1751 TRACE("(%p)->()\n", This);
1753 FAudio_StopEngine(This->faudio);
1756 static HRESULT WINAPI IXAudio2Impl_CommitChanges(IXAudio2 *iface,
1757 UINT32 operationSet)
1759 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1761 TRACE("(%p)->(0x%x)\n", This, operationSet);
1763 return FAudio_CommitOperationSet(This->faudio, operationSet);
1766 static void WINAPI IXAudio2Impl_GetPerformanceData(IXAudio2 *iface, XAUDIO2_PERFORMANCE_DATA *data)
1768 IXAudio2Impl *audio = impl_from_IXAudio2(iface);
1769 FAudioPerformanceData faudio_data;
1771 TRACE("(%p)->(%p)\n", audio, data);
1773 FAudio_GetPerformanceData(audio->faudio, &faudio_data);
1775 data->AudioCyclesSinceLastQuery = faudio_data.AudioCyclesSinceLastQuery;
1776 data->TotalCyclesSinceLastQuery = faudio_data.TotalCyclesSinceLastQuery;
1777 data->MinimumCyclesPerQuantum = faudio_data.MinimumCyclesPerQuantum;
1778 data->MaximumCyclesPerQuantum = faudio_data.MaximumCyclesPerQuantum;
1779 data->MemoryUsageInBytes = faudio_data.MemoryUsageInBytes;
1780 data->CurrentLatencyInSamples = faudio_data.CurrentLatencyInSamples;
1781 #if XAUDIO2_VER == 0
1782 data->GlitchesSinceLastQuery = faudio_data.GlitchesSinceEngineStarted - audio->last_query_glitches;
1783 audio->last_query_glitches = faudio_data.GlitchesSinceEngineStarted;
1784 #else
1785 data->GlitchesSinceEngineStarted = faudio_data.GlitchesSinceEngineStarted;
1786 #endif
1787 data->ActiveSourceVoiceCount = faudio_data.ActiveSourceVoiceCount;
1788 data->TotalSourceVoiceCount = faudio_data.TotalSourceVoiceCount;
1789 data->ActiveSubmixVoiceCount = faudio_data.ActiveSubmixVoiceCount;
1790 #if XAUDIO2_VER <= 2
1791 data->TotalSubmixVoiceCount = faudio_data.ActiveSubmixVoiceCount;
1792 #else
1793 data->ActiveResamplerCount = faudio_data.ActiveResamplerCount;
1794 data->ActiveMatrixMixCount = faudio_data.ActiveMatrixMixCount;
1795 #endif
1796 data->ActiveXmaSourceVoices = faudio_data.ActiveXmaSourceVoices;
1797 data->ActiveXmaStreams = faudio_data.ActiveXmaStreams;
1800 static void WINAPI IXAudio2Impl_SetDebugConfiguration(IXAudio2 *iface,
1801 const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
1802 void *pReserved)
1804 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1806 TRACE("(%p)->(%p, %p)\n", This, pDebugConfiguration, pReserved);
1808 FAudio_SetDebugConfiguration(This->faudio, (FAudioDebugConfiguration *)pDebugConfiguration, pReserved);
1811 static const IXAudio2Vtbl XAudio2_Vtbl =
1813 IXAudio2Impl_QueryInterface,
1814 IXAudio2Impl_AddRef,
1815 IXAudio2Impl_Release,
1816 #if XAUDIO2_VER <= 7
1817 IXAudio2Impl_GetDeviceCount,
1818 IXAudio2Impl_GetDeviceDetails,
1819 IXAudio2Impl_Initialize,
1820 #endif
1821 IXAudio2Impl_RegisterForCallbacks,
1822 IXAudio2Impl_UnregisterForCallbacks,
1823 IXAudio2Impl_CreateSourceVoice,
1824 IXAudio2Impl_CreateSubmixVoice,
1825 IXAudio2Impl_CreateMasteringVoice,
1826 IXAudio2Impl_StartEngine,
1827 IXAudio2Impl_StopEngine,
1828 IXAudio2Impl_CommitChanges,
1829 IXAudio2Impl_GetPerformanceData,
1830 IXAudio2Impl_SetDebugConfiguration
1833 /* XAudio2 ClassFactory */
1835 struct xaudio2_cf {
1836 IClassFactory IClassFactory_iface;
1837 LONG ref;
1840 static struct xaudio2_cf *impl_from_IClassFactory(IClassFactory *iface)
1842 return CONTAINING_RECORD(iface, struct xaudio2_cf, IClassFactory_iface);
1845 static HRESULT WINAPI XAudio2CF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
1847 if(IsEqualGUID(riid, &IID_IUnknown)
1848 || IsEqualGUID(riid, &IID_IClassFactory))
1850 IClassFactory_AddRef(iface);
1851 *ppobj = iface;
1852 return S_OK;
1855 *ppobj = NULL;
1856 WARN("(%p)->(%s, %p): interface not found\n", iface, debugstr_guid(riid), ppobj);
1857 return E_NOINTERFACE;
1860 static ULONG WINAPI XAudio2CF_AddRef(IClassFactory *iface)
1862 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1863 ULONG ref = InterlockedIncrement(&This->ref);
1864 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1865 return ref;
1868 static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
1870 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1871 ULONG ref = InterlockedDecrement(&This->ref);
1872 TRACE("(%p)->(): Refcount now %lu\n", This, ref);
1873 if (!ref)
1874 free(This);
1875 return ref;
1878 static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1879 REFIID riid, void **ppobj)
1881 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1882 HRESULT hr;
1883 IXAudio2Impl *object;
1885 TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
1887 *ppobj = NULL;
1889 if(pOuter)
1890 return CLASS_E_NOAGGREGATION;
1892 object = calloc(1, sizeof(*object));
1893 if(!object)
1894 return E_OUTOFMEMORY;
1896 object->IXAudio2_iface.lpVtbl = &XAudio2_Vtbl;
1897 object->mst.IXAudio2MasteringVoice_iface.lpVtbl = &XAudio2MasteringVoice_Vtbl;
1899 object->FAudioEngineCallback_vtbl = FAudioEngineCallback_Vtbl;
1901 list_init(&object->voices);
1903 InitializeCriticalSection(&object->lock);
1904 object->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IXAudio2Impl.lock");
1906 InitializeCriticalSection(&object->mst.lock);
1907 object->mst.lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": XA2MasteringVoice.lock");
1909 FAudioCOMConstructWithCustomAllocatorEXT(
1910 &object->faudio,
1911 XAUDIO2_VER,
1912 XAudio_Internal_Malloc,
1913 XAudio_Internal_Free,
1914 XAudio_Internal_Realloc
1917 FAudio_RegisterForCallbacks(object->faudio, &object->FAudioEngineCallback_vtbl);
1919 hr = IXAudio2_QueryInterface(&object->IXAudio2_iface, riid, ppobj);
1920 IXAudio2_Release(&object->IXAudio2_iface);
1921 if(FAILED(hr)){
1922 return hr;
1925 TRACE("Created XAudio version %u: %p\n", 20 + XAUDIO2_VER, object);
1927 return hr;
1930 static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock)
1932 struct xaudio2_cf *This = impl_from_IClassFactory(iface);
1933 FIXME("(%p)->(%d): stub!\n", This, dolock);
1934 return S_OK;
1937 static const IClassFactoryVtbl XAudio2CF_Vtbl =
1939 XAudio2CF_QueryInterface,
1940 XAudio2CF_AddRef,
1941 XAudio2CF_Release,
1942 XAudio2CF_CreateInstance,
1943 XAudio2CF_LockServer
1946 /* Engine Generators */
1948 static inline HRESULT make_xaudio2_factory(REFIID riid, void **ppv)
1950 HRESULT hr;
1951 struct xaudio2_cf *ret = malloc(sizeof(struct xaudio2_cf));
1952 ret->IClassFactory_iface.lpVtbl = &XAudio2CF_Vtbl;
1953 ret->ref = 0;
1954 hr = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
1955 if(FAILED(hr))
1956 free(ret);
1957 return hr;
1960 HRESULT xaudio2_initialize(IXAudio2Impl *This, UINT32 flags, XAUDIO2_PROCESSOR proc)
1962 if(proc != XAUDIO2_ANY_PROCESSOR)
1963 WARN("Processor affinity not implemented in FAudio\n");
1964 return FAudio_Initialize(This->faudio, flags, FAUDIO_DEFAULT_PROCESSOR);
1967 #if XAUDIO2_VER <= 7
1968 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
1970 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
1972 if (IsEqualGUID(rclsid, &CLSID_XAudio2))
1973 return make_xaudio2_factory(riid, ppv);
1975 if (IsEqualGUID(rclsid, &CLSID_AudioVolumeMeter))
1976 return make_xapo_factory(&CLSID_AudioVolumeMeter, riid, ppv);
1978 if (IsEqualGUID(rclsid, &CLSID_AudioReverb))
1979 return make_xapo_factory(&CLSID_AudioReverb, riid, ppv);
1981 return CLASS_E_CLASSNOTAVAILABLE;
1983 #else
1984 HRESULT WINAPI XAudio2Create(IXAudio2 **ppxa2, UINT32 flags, XAUDIO2_PROCESSOR proc)
1986 HRESULT hr;
1987 IXAudio2 *xa2;
1988 IClassFactory *cf;
1990 TRACE("%p 0x%x 0x%x\n", ppxa2, flags, proc);
1992 hr = make_xaudio2_factory(&IID_IClassFactory, (void**)&cf);
1993 if(FAILED(hr))
1994 return hr;
1996 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IXAudio2, (void**)&xa2);
1997 IClassFactory_Release(cf);
1998 if(FAILED(hr))
1999 return hr;
2001 hr = xaudio2_initialize(impl_from_IXAudio2(xa2), flags, proc);
2002 if(FAILED(hr)){
2003 IXAudio2_Release(xa2);
2004 return hr;
2007 *ppxa2 = xa2;
2009 return S_OK;
2011 #endif /* XAUDIO2_VER >= 8 */