2 * Copyright (c) 2015 Mark Harmstone
3 * Copyright (c) 2015 Andrew Eikum for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
34 #include "wine/list.h"
41 #include "mmdeviceapi.h"
42 #include "audioclient.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(xaudio2
);
50 static ALCdevice
*(ALC_APIENTRY
*palcLoopbackOpenDeviceSOFT
)(const ALCchar
*);
51 static void (ALC_APIENTRY
*palcRenderSamplesSOFT
)(ALCdevice
*, ALCvoid
*, ALCsizei
);
53 static HINSTANCE instance
;
55 static void dump_fmt(const WAVEFORMATEX
*fmt
)
57 TRACE("wFormatTag: 0x%x (", fmt
->wFormatTag
);
58 switch(fmt
->wFormatTag
){
59 #define DOCASE(x) case x: TRACE(#x); break;
60 DOCASE(WAVE_FORMAT_PCM
)
61 DOCASE(WAVE_FORMAT_IEEE_FLOAT
)
62 DOCASE(WAVE_FORMAT_EXTENSIBLE
)
70 TRACE("nChannels: %u\n", fmt
->nChannels
);
71 TRACE("nSamplesPerSec: %u\n", fmt
->nSamplesPerSec
);
72 TRACE("nAvgBytesPerSec: %u\n", fmt
->nAvgBytesPerSec
);
73 TRACE("nBlockAlign: %u\n", fmt
->nBlockAlign
);
74 TRACE("wBitsPerSample: %u\n", fmt
->wBitsPerSample
);
75 TRACE("cbSize: %u\n", fmt
->cbSize
);
77 if(fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
){
78 WAVEFORMATEXTENSIBLE
*fmtex
= (void*)fmt
;
79 TRACE("dwChannelMask: %08x\n", fmtex
->dwChannelMask
);
80 TRACE("Samples: %04x\n", fmtex
->Samples
.wReserved
);
81 TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex
->SubFormat
));
85 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD reason
, void *pReserved
)
87 TRACE("(%p, %d, %p)\n", hinstDLL
, reason
, pReserved
);
91 case DLL_WINE_PREATTACH
:
92 return FALSE
; /* prefer native version */
93 case DLL_PROCESS_ATTACH
:
95 DisableThreadLibraryCalls( hinstDLL
);
97 if(!alcIsExtensionPresent(NULL
, "ALC_SOFT_loopback") ||
98 !(palcLoopbackOpenDeviceSOFT
= alcGetProcAddress(NULL
, "alcLoopbackOpenDeviceSOFT")) ||
99 !(palcRenderSamplesSOFT
= alcGetProcAddress(NULL
, "alcRenderSamplesSOFT"))){
100 ERR("XAudio2 requires the ALC_SOFT_loopback extension (OpenAL-Soft >= 1.14)\n");
109 HRESULT WINAPI
DllCanUnloadNow(void)
114 HRESULT WINAPI
DllRegisterServer(void)
117 return __wine_register_resources(instance
);
120 HRESULT WINAPI
DllUnregisterServer(void)
123 return __wine_unregister_resources(instance
);
126 typedef struct _XA2Buffer
{
127 XAUDIO2_BUFFER xa2buffer
;
129 UINT32 latest_al_buf
;
132 typedef struct _IXAudio2Impl IXAudio2Impl
;
134 typedef struct _XA2SourceImpl
{
135 IXAudio27SourceVoice IXAudio27SourceVoice_iface
;
136 IXAudio2SourceVoice IXAudio2SourceVoice_iface
;
142 CRITICAL_SECTION lock
;
146 UINT32 submit_blocksize
;
148 IXAudio2VoiceCallback
*cb
;
151 XAUDIO2_SEND_DESCRIPTOR
*sends
;
155 UINT64 played_frames
;
157 XA2Buffer buffers
[XAUDIO2_MAX_QUEUED_BUFFERS
];
158 UINT32 first_buf
, cur_buf
, nbufs
, in_al_bytes
;
161 /* most cases will only need about 4 AL buffers, but some corner cases
162 * could require up to MAX_QUEUED_BUFFERS */
163 ALuint al_bufs
[XAUDIO2_MAX_QUEUED_BUFFERS
];
164 DWORD first_al_buf
, al_bufs_used
;
169 XA2SourceImpl
*impl_from_IXAudio2SourceVoice(IXAudio2SourceVoice
*iface
)
171 return CONTAINING_RECORD(iface
, XA2SourceImpl
, IXAudio2SourceVoice_iface
);
174 XA2SourceImpl
*impl_from_IXAudio27SourceVoice(IXAudio27SourceVoice
*iface
)
176 return CONTAINING_RECORD(iface
, XA2SourceImpl
, IXAudio27SourceVoice_iface
);
179 typedef struct _XA2SubmixImpl
{
180 IXAudio2SubmixVoice IXAudio2SubmixVoice_iface
;
184 CRITICAL_SECTION lock
;
189 XA2SubmixImpl
*impl_from_IXAudio2SubmixVoice(IXAudio2SubmixVoice
*iface
)
191 return CONTAINING_RECORD(iface
, XA2SubmixImpl
, IXAudio2SubmixVoice_iface
);
194 struct _IXAudio2Impl
{
195 IXAudio27 IXAudio27_iface
;
196 IXAudio2 IXAudio2_iface
;
197 IXAudio2MasteringVoice IXAudio2MasteringVoice_iface
;
201 CRITICAL_SECTION lock
;
203 HANDLE engine
, mmevt
;
208 struct list source_voices
;
209 struct list submix_voices
;
211 IMMDeviceEnumerator
*devenum
;
216 IAudioClient
*aclient
;
217 IAudioRenderClient
*render
;
219 UINT32 period_frames
;
221 WAVEFORMATEXTENSIBLE fmt
;
223 ALCdevice
*al_device
;
227 IXAudio2EngineCallback
**cbs
;
232 static inline IXAudio2Impl
*impl_from_IXAudio2(IXAudio2
*iface
)
234 return CONTAINING_RECORD(iface
, IXAudio2Impl
, IXAudio2_iface
);
237 static inline IXAudio2Impl
*impl_from_IXAudio27(IXAudio27
*iface
)
239 return CONTAINING_RECORD(iface
, IXAudio2Impl
, IXAudio27_iface
);
242 IXAudio2Impl
*impl_from_IXAudio2MasteringVoice(IXAudio2MasteringVoice
*iface
)
244 return CONTAINING_RECORD(iface
, IXAudio2Impl
, IXAudio2MasteringVoice_iface
);
247 static DWORD
get_channel_mask(unsigned int channels
)
253 return KSAUDIO_SPEAKER_MONO
;
255 return KSAUDIO_SPEAKER_STEREO
;
257 return KSAUDIO_SPEAKER_STEREO
| SPEAKER_LOW_FREQUENCY
;
259 return KSAUDIO_SPEAKER_QUAD
; /* not _SURROUND */
261 return KSAUDIO_SPEAKER_QUAD
| SPEAKER_LOW_FREQUENCY
;
263 return KSAUDIO_SPEAKER_5POINT1
; /* not 5POINT1_SURROUND */
265 return KSAUDIO_SPEAKER_5POINT1
| SPEAKER_BACK_CENTER
;
267 return KSAUDIO_SPEAKER_7POINT1_SURROUND
; /* Vista deprecates 7POINT1 */
269 FIXME("Unknown speaker configuration: %u\n", channels
);
273 static void WINAPI
XA2SRC_GetVoiceDetails(IXAudio2SourceVoice
*iface
,
274 XAUDIO2_VOICE_DETAILS
*pVoiceDetails
)
276 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
277 TRACE("%p, %p\n", This
, pVoiceDetails
);
280 static HRESULT WINAPI
XA2SRC_SetOutputVoices(IXAudio2SourceVoice
*iface
,
281 const XAUDIO2_VOICE_SENDS
*pSendList
)
283 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
285 XAUDIO2_VOICE_SENDS def_send
;
286 XAUDIO2_SEND_DESCRIPTOR def_desc
;
288 TRACE("%p, %p\n", This
, pSendList
);
292 def_desc
.pOutputVoice
= (IXAudio2Voice
*)&This
->xa2
->IXAudio2MasteringVoice_iface
;
294 def_send
.SendCount
= 1;
295 def_send
.pSends
= &def_desc
;
297 pSendList
= &def_send
;
300 if(TRACE_ON(xaudio2
)){
301 for(i
= 0; i
< pSendList
->SendCount
; ++i
){
302 XAUDIO2_SEND_DESCRIPTOR
*desc
= &pSendList
->pSends
[i
];
303 TRACE("Outputting to: 0x%x, %p\n", desc
->Flags
, desc
->pOutputVoice
);
307 if(This
->nsends
< pSendList
->SendCount
){
308 HeapFree(GetProcessHeap(), 0, This
->sends
);
309 This
->sends
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->sends
) * pSendList
->SendCount
);
310 This
->nsends
= pSendList
->SendCount
;
312 memset(This
->sends
, 0, sizeof(*This
->sends
) * This
->nsends
);
314 memcpy(This
->sends
, pSendList
->pSends
, sizeof(*This
->sends
) * pSendList
->SendCount
);
319 static HRESULT WINAPI
XA2SRC_SetEffectChain(IXAudio2SourceVoice
*iface
,
320 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
322 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
323 TRACE("%p, %p\n", This
, pEffectChain
);
327 static HRESULT WINAPI
XA2SRC_EnableEffect(IXAudio2SourceVoice
*iface
,
328 UINT32 EffectIndex
, UINT32 OperationSet
)
330 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
331 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
335 static HRESULT WINAPI
XA2SRC_DisableEffect(IXAudio2SourceVoice
*iface
,
336 UINT32 EffectIndex
, UINT32 OperationSet
)
338 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
339 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
343 static void WINAPI
XA2SRC_GetEffectState(IXAudio2SourceVoice
*iface
,
344 UINT32 EffectIndex
, BOOL
*pEnabled
)
346 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
347 TRACE("%p, %u, %p\n", This
, EffectIndex
, pEnabled
);
350 static HRESULT WINAPI
XA2SRC_SetEffectParameters(IXAudio2SourceVoice
*iface
,
351 UINT32 EffectIndex
, const void *pParameters
, UINT32 ParametersByteSize
,
354 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
355 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This
, EffectIndex
, pParameters
,
356 ParametersByteSize
, OperationSet
);
360 static HRESULT WINAPI
XA2SRC_GetEffectParameters(IXAudio2SourceVoice
*iface
,
361 UINT32 EffectIndex
, void *pParameters
, UINT32 ParametersByteSize
)
363 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
364 TRACE("%p, %u, %p, 0x%x\n", This
, EffectIndex
, pParameters
,
369 static HRESULT WINAPI
XA2SRC_SetFilterParameters(IXAudio2SourceVoice
*iface
,
370 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
372 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
373 TRACE("%p, %p, 0x%x\n", This
, pParameters
, OperationSet
);
377 static void WINAPI
XA2SRC_GetFilterParameters(IXAudio2SourceVoice
*iface
,
378 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
380 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
381 TRACE("%p, %p\n", This
, pParameters
);
384 static HRESULT WINAPI
XA2SRC_SetOutputFilterParameters(IXAudio2SourceVoice
*iface
,
385 IXAudio2Voice
*pDestinationVoice
,
386 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
388 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
389 TRACE("%p, %p, %p, 0x%x\n", This
, pDestinationVoice
, pParameters
, OperationSet
);
393 static void WINAPI
XA2SRC_GetOutputFilterParameters(IXAudio2SourceVoice
*iface
,
394 IXAudio2Voice
*pDestinationVoice
,
395 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
397 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
398 TRACE("%p, %p, %p\n", This
, pDestinationVoice
, pParameters
);
401 static HRESULT WINAPI
XA2SRC_SetVolume(IXAudio2SourceVoice
*iface
, float Volume
,
404 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
405 TRACE("%p, %f, 0x%x\n", This
, Volume
, OperationSet
);
409 static void WINAPI
XA2SRC_GetVolume(IXAudio2SourceVoice
*iface
, float *pVolume
)
411 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
412 TRACE("%p, %p\n", This
, pVolume
);
415 static HRESULT WINAPI
XA2SRC_SetChannelVolumes(IXAudio2SourceVoice
*iface
,
416 UINT32 Channels
, const float *pVolumes
, UINT32 OperationSet
)
418 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
419 TRACE("%p, %u, %p, 0x%x\n", This
, Channels
, pVolumes
, OperationSet
);
423 static void WINAPI
XA2SRC_GetChannelVolumes(IXAudio2SourceVoice
*iface
,
424 UINT32 Channels
, float *pVolumes
)
426 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
427 TRACE("%p, %u, %p\n", This
, Channels
, pVolumes
);
430 static HRESULT WINAPI
XA2SRC_SetOutputMatrix(IXAudio2SourceVoice
*iface
,
431 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
432 UINT32 DestinationChannels
, const float *pLevelMatrix
,
435 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
436 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This
, pDestinationVoice
,
437 SourceChannels
, DestinationChannels
, pLevelMatrix
, OperationSet
);
441 static void WINAPI
XA2SRC_GetOutputMatrix(IXAudio2SourceVoice
*iface
,
442 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
443 UINT32 DestinationChannels
, float *pLevelMatrix
)
445 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
446 TRACE("%p, %p, %u, %u, %p\n", This
, pDestinationVoice
,
447 SourceChannels
, DestinationChannels
, pLevelMatrix
);
450 static void WINAPI
XA2SRC_DestroyVoice(IXAudio2SourceVoice
*iface
)
452 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
457 EnterCriticalSection(&This
->lock
);
460 LeaveCriticalSection(&This
->lock
);
464 This
->in_use
= FALSE
;
466 This
->running
= FALSE
;
468 IXAudio2SourceVoice_Stop(iface
, 0, 0);
470 alSourceStop(This
->al_src
);
472 /* unqueue all buffers */
473 alSourcei(This
->al_src
, AL_BUFFER
, AL_NONE
);
475 alGetSourcei(This
->al_src
, AL_BUFFERS_PROCESSED
, &processed
);
478 ALuint al_buffers
[XAUDIO2_MAX_QUEUED_BUFFERS
];
480 alSourceUnqueueBuffers(This
->al_src
, processed
, al_buffers
);
483 HeapFree(GetProcessHeap(), 0, This
->fmt
);
485 alDeleteBuffers(XAUDIO2_MAX_QUEUED_BUFFERS
, This
->al_bufs
);
486 alDeleteSources(1, &This
->al_src
);
488 This
->in_al_bytes
= 0;
489 This
->al_bufs_used
= 0;
490 This
->played_frames
= 0;
495 LeaveCriticalSection(&This
->lock
);
498 static HRESULT WINAPI
XA2SRC_Start(IXAudio2SourceVoice
*iface
, UINT32 Flags
,
501 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
503 TRACE("%p, 0x%x, 0x%x\n", This
, Flags
, OperationSet
);
505 EnterCriticalSection(&This
->lock
);
507 This
->running
= TRUE
;
509 LeaveCriticalSection(&This
->lock
);
514 static HRESULT WINAPI
XA2SRC_Stop(IXAudio2SourceVoice
*iface
, UINT32 Flags
,
517 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
519 TRACE("%p, 0x%x, 0x%x\n", This
, Flags
, OperationSet
);
521 EnterCriticalSection(&This
->lock
);
523 This
->running
= FALSE
;
525 LeaveCriticalSection(&This
->lock
);
530 static ALenum
get_al_format(const WAVEFORMATEX
*fmt
)
532 WAVEFORMATEXTENSIBLE
*fmtex
= (WAVEFORMATEXTENSIBLE
*)fmt
;
533 if(fmt
->wFormatTag
== WAVE_FORMAT_PCM
||
534 (fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
&&
535 IsEqualGUID(&fmtex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))){
536 switch(fmt
->wBitsPerSample
){
538 switch(fmt
->nChannels
){
540 return AL_FORMAT_MONO8
;
542 return AL_FORMAT_STEREO8
;
544 return AL_FORMAT_QUAD8
;
546 return AL_FORMAT_51CHN8
;
548 return AL_FORMAT_61CHN8
;
550 return AL_FORMAT_71CHN8
;
553 switch(fmt
->nChannels
){
555 return AL_FORMAT_MONO16
;
557 return AL_FORMAT_STEREO16
;
559 return AL_FORMAT_QUAD16
;
561 return AL_FORMAT_51CHN16
;
563 return AL_FORMAT_61CHN16
;
565 return AL_FORMAT_71CHN16
;
568 }else if(fmt
->wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
||
569 (fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
&&
570 IsEqualGUID(&fmtex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))){
571 if(fmt
->wBitsPerSample
== 32){
572 switch(fmt
->nChannels
){
574 return AL_FORMAT_MONO_FLOAT32
;
576 return AL_FORMAT_STEREO_FLOAT32
;
583 static HRESULT WINAPI
XA2SRC_SubmitSourceBuffer(IXAudio2SourceVoice
*iface
,
584 const XAUDIO2_BUFFER
*pBuffer
, const XAUDIO2_BUFFER_WMA
*pBufferWMA
)
586 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
590 TRACE("%p, %p, %p\n", This
, pBuffer
, pBufferWMA
);
592 if(TRACE_ON(xaudio2
)){
593 TRACE("Flags: 0x%x\n", pBuffer
->Flags
);
594 TRACE("AudioBytes: %u\n", pBuffer
->AudioBytes
);
595 TRACE("pAudioData: %p\n", pBuffer
->pAudioData
);
596 TRACE("PlayBegin: %u\n", pBuffer
->PlayBegin
);
597 TRACE("PlayLength: %u\n", pBuffer
->PlayLength
);
598 TRACE("LoopBegin: %u\n", pBuffer
->LoopBegin
);
599 TRACE("LoopLength: %u\n", pBuffer
->LoopLength
);
600 TRACE("LoopCount: %u\n", pBuffer
->LoopCount
);
601 TRACE("pContext: %p\n", pBuffer
->pContext
);
604 EnterCriticalSection(&This
->lock
);
606 if(This
->nbufs
>= XAUDIO2_MAX_QUEUED_BUFFERS
){
607 TRACE("Too many buffers queued!\n");
608 LeaveCriticalSection(&This
->lock
);
609 return XAUDIO2_E_INVALID_CALL
;
612 buf_idx
= (This
->first_buf
+ This
->nbufs
) % XAUDIO2_MAX_QUEUED_BUFFERS
;
613 buf
= &This
->buffers
[buf_idx
];
614 memset(buf
, 0, sizeof(*buf
));
616 /* API contract: pAudioData must remain valid until this buffer is played,
617 * but pBuffer itself may be reused immediately */
618 memcpy(&buf
->xa2buffer
, pBuffer
, sizeof(*pBuffer
));
621 buf
->latest_al_buf
= -1;
625 TRACE("%p: queued buffer %u (%u bytes), now %u buffers held\n",
626 This
, buf_idx
, buf
->xa2buffer
.AudioBytes
, This
->nbufs
);
628 LeaveCriticalSection(&This
->lock
);
633 static HRESULT WINAPI
XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice
*iface
)
635 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
640 static HRESULT WINAPI
XA2SRC_Discontinuity(IXAudio2SourceVoice
*iface
)
642 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
647 static HRESULT WINAPI
XA2SRC_ExitLoop(IXAudio2SourceVoice
*iface
, UINT32 OperationSet
)
649 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
650 TRACE("%p, 0x%x\n", This
, OperationSet
);
654 static void WINAPI
XA2SRC_GetState(IXAudio2SourceVoice
*iface
,
655 XAUDIO2_VOICE_STATE
*pVoiceState
, UINT32 Flags
)
657 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
658 TRACE("%p, %p, 0x%x\n", This
, pVoiceState
, Flags
);
661 static HRESULT WINAPI
XA2SRC_SetFrequencyRatio(IXAudio2SourceVoice
*iface
,
662 float Ratio
, UINT32 OperationSet
)
664 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
665 TRACE("%p, %f, 0x%x\n", This
, Ratio
, OperationSet
);
669 static void WINAPI
XA2SRC_GetFrequencyRatio(IXAudio2SourceVoice
*iface
, float *pRatio
)
671 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
672 TRACE("%p, %p\n", This
, pRatio
);
675 static HRESULT WINAPI
XA2SRC_SetSourceSampleRate(
676 IXAudio2SourceVoice
*iface
,
677 UINT32 NewSourceSampleRate
)
679 XA2SourceImpl
*This
= impl_from_IXAudio2SourceVoice(iface
);
680 TRACE("%p, %u\n", This
, NewSourceSampleRate
);
684 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl
= {
685 XA2SRC_GetVoiceDetails
,
686 XA2SRC_SetOutputVoices
,
687 XA2SRC_SetEffectChain
,
689 XA2SRC_DisableEffect
,
690 XA2SRC_GetEffectState
,
691 XA2SRC_SetEffectParameters
,
692 XA2SRC_GetEffectParameters
,
693 XA2SRC_SetFilterParameters
,
694 XA2SRC_GetFilterParameters
,
695 XA2SRC_SetOutputFilterParameters
,
696 XA2SRC_GetOutputFilterParameters
,
699 XA2SRC_SetChannelVolumes
,
700 XA2SRC_GetChannelVolumes
,
701 XA2SRC_SetOutputMatrix
,
702 XA2SRC_GetOutputMatrix
,
706 XA2SRC_SubmitSourceBuffer
,
707 XA2SRC_FlushSourceBuffers
,
708 XA2SRC_Discontinuity
,
711 XA2SRC_SetFrequencyRatio
,
712 XA2SRC_GetFrequencyRatio
,
713 XA2SRC_SetSourceSampleRate
716 static void WINAPI
XA27SRC_GetVoiceDetails(IXAudio27SourceVoice
*iface
,
717 XAUDIO2_VOICE_DETAILS
*pVoiceDetails
)
719 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
720 return XA2SRC_GetVoiceDetails(&This
->IXAudio2SourceVoice_iface
, pVoiceDetails
);
723 static HRESULT WINAPI
XA27SRC_SetOutputVoices(IXAudio27SourceVoice
*iface
,
724 const XAUDIO2_VOICE_SENDS
*pSendList
)
726 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
727 return XA2SRC_SetOutputVoices(&This
->IXAudio2SourceVoice_iface
, pSendList
);
730 static HRESULT WINAPI
XA27SRC_SetEffectChain(IXAudio27SourceVoice
*iface
,
731 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
733 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
734 return XA2SRC_SetEffectChain(&This
->IXAudio2SourceVoice_iface
, pEffectChain
);
737 static HRESULT WINAPI
XA27SRC_EnableEffect(IXAudio27SourceVoice
*iface
,
738 UINT32 EffectIndex
, UINT32 OperationSet
)
740 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
741 return XA2SRC_EnableEffect(&This
->IXAudio2SourceVoice_iface
, EffectIndex
, OperationSet
);
744 static HRESULT WINAPI
XA27SRC_DisableEffect(IXAudio27SourceVoice
*iface
,
745 UINT32 EffectIndex
, UINT32 OperationSet
)
747 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
748 return XA2SRC_DisableEffect(&This
->IXAudio2SourceVoice_iface
, EffectIndex
, OperationSet
);
751 static void WINAPI
XA27SRC_GetEffectState(IXAudio27SourceVoice
*iface
,
752 UINT32 EffectIndex
, BOOL
*pEnabled
)
754 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
755 XA2SRC_GetEffectState(&This
->IXAudio2SourceVoice_iface
, EffectIndex
, pEnabled
);
758 static HRESULT WINAPI
XA27SRC_SetEffectParameters(IXAudio27SourceVoice
*iface
,
759 UINT32 EffectIndex
, const void *pParameters
, UINT32 ParametersByteSize
,
762 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
763 return XA2SRC_SetEffectParameters(&This
->IXAudio2SourceVoice_iface
,
764 EffectIndex
, pParameters
, ParametersByteSize
, OperationSet
);
767 static HRESULT WINAPI
XA27SRC_GetEffectParameters(IXAudio27SourceVoice
*iface
,
768 UINT32 EffectIndex
, void *pParameters
, UINT32 ParametersByteSize
)
770 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
771 return XA2SRC_GetEffectParameters(&This
->IXAudio2SourceVoice_iface
,
772 EffectIndex
, pParameters
, ParametersByteSize
);
775 static HRESULT WINAPI
XA27SRC_SetFilterParameters(IXAudio27SourceVoice
*iface
,
776 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
778 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
779 return XA2SRC_SetFilterParameters(&This
->IXAudio2SourceVoice_iface
,
780 pParameters
, OperationSet
);
783 static void WINAPI
XA27SRC_GetFilterParameters(IXAudio27SourceVoice
*iface
,
784 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
786 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
787 XA2SRC_GetFilterParameters(&This
->IXAudio2SourceVoice_iface
, pParameters
);
790 static HRESULT WINAPI
XA27SRC_SetOutputFilterParameters(IXAudio27SourceVoice
*iface
,
791 IXAudio2Voice
*pDestinationVoice
,
792 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
794 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
795 return XA2SRC_SetOutputFilterParameters(&This
->IXAudio2SourceVoice_iface
,
796 pDestinationVoice
, pParameters
, OperationSet
);
799 static void WINAPI
XA27SRC_GetOutputFilterParameters(IXAudio27SourceVoice
*iface
,
800 IXAudio2Voice
*pDestinationVoice
,
801 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
803 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
804 XA2SRC_GetOutputFilterParameters(&This
->IXAudio2SourceVoice_iface
,
805 pDestinationVoice
, pParameters
);
808 static HRESULT WINAPI
XA27SRC_SetVolume(IXAudio27SourceVoice
*iface
, float Volume
,
811 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
812 return XA2SRC_SetVolume(&This
->IXAudio2SourceVoice_iface
, Volume
,
816 static void WINAPI
XA27SRC_GetVolume(IXAudio27SourceVoice
*iface
, float *pVolume
)
818 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
819 XA2SRC_GetVolume(&This
->IXAudio2SourceVoice_iface
, pVolume
);
822 static HRESULT WINAPI
XA27SRC_SetChannelVolumes(IXAudio27SourceVoice
*iface
,
823 UINT32 Channels
, const float *pVolumes
, UINT32 OperationSet
)
825 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
826 return XA2SRC_SetChannelVolumes(&This
->IXAudio2SourceVoice_iface
, Channels
,
827 pVolumes
, OperationSet
);
830 static void WINAPI
XA27SRC_GetChannelVolumes(IXAudio27SourceVoice
*iface
,
831 UINT32 Channels
, float *pVolumes
)
833 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
834 XA2SRC_GetChannelVolumes(&This
->IXAudio2SourceVoice_iface
, Channels
,
838 static HRESULT WINAPI
XA27SRC_SetOutputMatrix(IXAudio27SourceVoice
*iface
,
839 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
840 UINT32 DestinationChannels
, const float *pLevelMatrix
,
843 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
844 return XA2SRC_SetOutputMatrix(&This
->IXAudio2SourceVoice_iface
,
845 pDestinationVoice
, SourceChannels
, DestinationChannels
,
846 pLevelMatrix
, OperationSet
);
849 static void WINAPI
XA27SRC_GetOutputMatrix(IXAudio27SourceVoice
*iface
,
850 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
851 UINT32 DestinationChannels
, float *pLevelMatrix
)
853 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
854 XA2SRC_GetOutputMatrix(&This
->IXAudio2SourceVoice_iface
, pDestinationVoice
,
855 SourceChannels
, DestinationChannels
, pLevelMatrix
);
858 static void WINAPI
XA27SRC_DestroyVoice(IXAudio27SourceVoice
*iface
)
860 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
861 XA2SRC_DestroyVoice(&This
->IXAudio2SourceVoice_iface
);
864 static HRESULT WINAPI
XA27SRC_Start(IXAudio27SourceVoice
*iface
, UINT32 Flags
,
867 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
868 return XA2SRC_Start(&This
->IXAudio2SourceVoice_iface
, Flags
, OperationSet
);
871 static HRESULT WINAPI
XA27SRC_Stop(IXAudio27SourceVoice
*iface
, UINT32 Flags
,
874 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
875 return XA2SRC_Stop(&This
->IXAudio2SourceVoice_iface
, Flags
, OperationSet
);
878 static HRESULT WINAPI
XA27SRC_SubmitSourceBuffer(IXAudio27SourceVoice
*iface
,
879 const XAUDIO2_BUFFER
*pBuffer
, const XAUDIO2_BUFFER_WMA
*pBufferWMA
)
881 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
882 return XA2SRC_SubmitSourceBuffer(&This
->IXAudio2SourceVoice_iface
, pBuffer
,
886 static HRESULT WINAPI
XA27SRC_FlushSourceBuffers(IXAudio27SourceVoice
*iface
)
888 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
889 return XA2SRC_FlushSourceBuffers(&This
->IXAudio2SourceVoice_iface
);
892 static HRESULT WINAPI
XA27SRC_Discontinuity(IXAudio27SourceVoice
*iface
)
894 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
895 return XA2SRC_Discontinuity(&This
->IXAudio2SourceVoice_iface
);
898 static HRESULT WINAPI
XA27SRC_ExitLoop(IXAudio27SourceVoice
*iface
, UINT32 OperationSet
)
900 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
901 return XA2SRC_ExitLoop(&This
->IXAudio2SourceVoice_iface
, OperationSet
);
904 static void WINAPI
XA27SRC_GetState(IXAudio27SourceVoice
*iface
,
905 XAUDIO2_VOICE_STATE
*pVoiceState
)
907 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
908 return XA2SRC_GetState(&This
->IXAudio2SourceVoice_iface
, pVoiceState
, 0);
911 static HRESULT WINAPI
XA27SRC_SetFrequencyRatio(IXAudio27SourceVoice
*iface
,
912 float Ratio
, UINT32 OperationSet
)
914 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
915 return XA2SRC_SetFrequencyRatio(&This
->IXAudio2SourceVoice_iface
, Ratio
, OperationSet
);
918 static void WINAPI
XA27SRC_GetFrequencyRatio(IXAudio27SourceVoice
*iface
, float *pRatio
)
920 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
921 return XA2SRC_GetFrequencyRatio(&This
->IXAudio2SourceVoice_iface
, pRatio
);
924 static HRESULT WINAPI
XA27SRC_SetSourceSampleRate(
925 IXAudio27SourceVoice
*iface
,
926 UINT32 NewSourceSampleRate
)
928 XA2SourceImpl
*This
= impl_from_IXAudio27SourceVoice(iface
);
929 return XA2SRC_SetSourceSampleRate(&This
->IXAudio2SourceVoice_iface
, NewSourceSampleRate
);
932 static const IXAudio27SourceVoiceVtbl XAudio27SourceVoice_Vtbl
= {
933 XA27SRC_GetVoiceDetails
,
934 XA27SRC_SetOutputVoices
,
935 XA27SRC_SetEffectChain
,
936 XA27SRC_EnableEffect
,
937 XA27SRC_DisableEffect
,
938 XA27SRC_GetEffectState
,
939 XA27SRC_SetEffectParameters
,
940 XA27SRC_GetEffectParameters
,
941 XA27SRC_SetFilterParameters
,
942 XA27SRC_GetFilterParameters
,
943 XA27SRC_SetOutputFilterParameters
,
944 XA27SRC_GetOutputFilterParameters
,
947 XA27SRC_SetChannelVolumes
,
948 XA27SRC_GetChannelVolumes
,
949 XA27SRC_SetOutputMatrix
,
950 XA27SRC_GetOutputMatrix
,
951 XA27SRC_DestroyVoice
,
954 XA27SRC_SubmitSourceBuffer
,
955 XA27SRC_FlushSourceBuffers
,
956 XA27SRC_Discontinuity
,
959 XA27SRC_SetFrequencyRatio
,
960 XA27SRC_GetFrequencyRatio
,
961 XA27SRC_SetSourceSampleRate
964 static void WINAPI
XA2M_GetVoiceDetails(IXAudio2MasteringVoice
*iface
,
965 XAUDIO2_VOICE_DETAILS
*pVoiceDetails
)
967 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
968 TRACE("%p, %p\n", This
, pVoiceDetails
);
971 static HRESULT WINAPI
XA2M_SetOutputVoices(IXAudio2MasteringVoice
*iface
,
972 const XAUDIO2_VOICE_SENDS
*pSendList
)
974 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
975 TRACE("%p, %p\n", This
, pSendList
);
979 static HRESULT WINAPI
XA2M_SetEffectChain(IXAudio2MasteringVoice
*iface
,
980 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
982 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
983 TRACE("%p, %p\n", This
, pEffectChain
);
987 static HRESULT WINAPI
XA2M_EnableEffect(IXAudio2MasteringVoice
*iface
, UINT32 EffectIndex
,
990 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
991 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
995 static HRESULT WINAPI
XA2M_DisableEffect(IXAudio2MasteringVoice
*iface
, UINT32 EffectIndex
,
998 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
999 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
1003 static void WINAPI
XA2M_GetEffectState(IXAudio2MasteringVoice
*iface
, UINT32 EffectIndex
,
1006 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1007 TRACE("%p, %u, %p\n", This
, EffectIndex
, pEnabled
);
1010 static HRESULT WINAPI
XA2M_SetEffectParameters(IXAudio2MasteringVoice
*iface
,
1011 UINT32 EffectIndex
, const void *pParameters
, UINT32 ParametersByteSize
,
1012 UINT32 OperationSet
)
1014 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1015 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This
, EffectIndex
, pParameters
,
1016 ParametersByteSize
, OperationSet
);
1020 static HRESULT WINAPI
XA2M_GetEffectParameters(IXAudio2MasteringVoice
*iface
,
1021 UINT32 EffectIndex
, void *pParameters
, UINT32 ParametersByteSize
)
1023 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1024 TRACE("%p, %u, %p, 0x%x\n", This
, EffectIndex
, pParameters
,
1025 ParametersByteSize
);
1029 static HRESULT WINAPI
XA2M_SetFilterParameters(IXAudio2MasteringVoice
*iface
,
1030 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
1032 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1033 TRACE("%p, %p, 0x%x\n", This
, pParameters
, OperationSet
);
1037 static void WINAPI
XA2M_GetFilterParameters(IXAudio2MasteringVoice
*iface
,
1038 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
1040 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1041 TRACE("%p, %p\n", This
, pParameters
);
1044 static HRESULT WINAPI
XA2M_SetOutputFilterParameters(IXAudio2MasteringVoice
*iface
,
1045 IXAudio2Voice
*pDestinationVoice
,
1046 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
1048 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1049 TRACE("%p, %p, %p, 0x%x\n", This
, pDestinationVoice
, pParameters
, OperationSet
);
1053 static void WINAPI
XA2M_GetOutputFilterParameters(IXAudio2MasteringVoice
*iface
,
1054 IXAudio2Voice
*pDestinationVoice
,
1055 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
1057 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1058 TRACE("%p, %p, %p\n", This
, pDestinationVoice
, pParameters
);
1061 static HRESULT WINAPI
XA2M_SetVolume(IXAudio2MasteringVoice
*iface
, float Volume
,
1062 UINT32 OperationSet
)
1064 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1065 TRACE("%p, %f, 0x%x\n", This
, Volume
, OperationSet
);
1069 static void WINAPI
XA2M_GetVolume(IXAudio2MasteringVoice
*iface
, float *pVolume
)
1071 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1072 TRACE("%p, %p\n", This
, pVolume
);
1075 static HRESULT WINAPI
XA2M_SetChannelVolumes(IXAudio2MasteringVoice
*iface
, UINT32 Channels
,
1076 const float *pVolumes
, UINT32 OperationSet
)
1078 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1079 TRACE("%p, %u, %p, 0x%x\n", This
, Channels
, pVolumes
, OperationSet
);
1083 static void WINAPI
XA2M_GetChannelVolumes(IXAudio2MasteringVoice
*iface
, UINT32 Channels
,
1086 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1087 TRACE("%p, %u, %p\n", This
, Channels
, pVolumes
);
1090 static HRESULT WINAPI
XA2M_SetOutputMatrix(IXAudio2MasteringVoice
*iface
,
1091 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
1092 UINT32 DestinationChannels
, const float *pLevelMatrix
,
1093 UINT32 OperationSet
)
1095 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1096 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This
, pDestinationVoice
,
1097 SourceChannels
, DestinationChannels
, pLevelMatrix
, OperationSet
);
1101 static void WINAPI
XA2M_GetOutputMatrix(IXAudio2MasteringVoice
*iface
,
1102 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
1103 UINT32 DestinationChannels
, float *pLevelMatrix
)
1105 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1106 TRACE("%p, %p, %u, %u, %p\n", This
, pDestinationVoice
,
1107 SourceChannels
, DestinationChannels
, pLevelMatrix
);
1110 static void WINAPI
XA2M_DestroyVoice(IXAudio2MasteringVoice
*iface
)
1112 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1114 TRACE("%p\n", This
);
1116 EnterCriticalSection(&This
->lock
);
1119 LeaveCriticalSection(&This
->lock
);
1123 IAudioRenderClient_Release(This
->render
);
1124 This
->render
= NULL
;
1126 IAudioClient_Release(This
->aclient
);
1127 This
->aclient
= NULL
;
1129 alcCloseDevice(This
->al_device
);
1130 This
->al_device
= NULL
;
1132 alcDestroyContext(This
->al_ctx
);
1133 This
->al_ctx
= NULL
;
1135 LeaveCriticalSection(&This
->lock
);
1138 /* not present in XAudio2 2.7 */
1139 static void WINAPI
XA2M_GetChannelMask(IXAudio2MasteringVoice
*iface
,
1140 DWORD
*pChannelMask
)
1142 IXAudio2Impl
*This
= impl_from_IXAudio2MasteringVoice(iface
);
1143 TRACE("%p %p\n", This
, pChannelMask
);
1146 static const struct IXAudio2MasteringVoiceVtbl XAudio2MasteringVoice_Vtbl
= {
1147 XA2M_GetVoiceDetails
,
1148 XA2M_SetOutputVoices
,
1149 XA2M_SetEffectChain
,
1152 XA2M_GetEffectState
,
1153 XA2M_SetEffectParameters
,
1154 XA2M_GetEffectParameters
,
1155 XA2M_SetFilterParameters
,
1156 XA2M_GetFilterParameters
,
1157 XA2M_SetOutputFilterParameters
,
1158 XA2M_GetOutputFilterParameters
,
1161 XA2M_SetChannelVolumes
,
1162 XA2M_GetChannelVolumes
,
1163 XA2M_SetOutputMatrix
,
1164 XA2M_GetOutputMatrix
,
1169 static void WINAPI
XA2SUB_GetVoiceDetails(IXAudio2SubmixVoice
*iface
,
1170 XAUDIO2_VOICE_DETAILS
*pVoiceDetails
)
1172 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1173 TRACE("%p, %p\n", This
, pVoiceDetails
);
1176 static HRESULT WINAPI
XA2SUB_SetOutputVoices(IXAudio2SubmixVoice
*iface
,
1177 const XAUDIO2_VOICE_SENDS
*pSendList
)
1179 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1180 TRACE("%p, %p\n", This
, pSendList
);
1184 static HRESULT WINAPI
XA2SUB_SetEffectChain(IXAudio2SubmixVoice
*iface
,
1185 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
1187 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1188 TRACE("%p, %p\n", This
, pEffectChain
);
1192 static HRESULT WINAPI
XA2SUB_EnableEffect(IXAudio2SubmixVoice
*iface
, UINT32 EffectIndex
,
1193 UINT32 OperationSet
)
1195 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1196 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
1200 static HRESULT WINAPI
XA2SUB_DisableEffect(IXAudio2SubmixVoice
*iface
, UINT32 EffectIndex
,
1201 UINT32 OperationSet
)
1203 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1204 TRACE("%p, %u, 0x%x\n", This
, EffectIndex
, OperationSet
);
1208 static void WINAPI
XA2SUB_GetEffectState(IXAudio2SubmixVoice
*iface
, UINT32 EffectIndex
,
1211 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1212 TRACE("%p, %u, %p\n", This
, EffectIndex
, pEnabled
);
1215 static HRESULT WINAPI
XA2SUB_SetEffectParameters(IXAudio2SubmixVoice
*iface
,
1216 UINT32 EffectIndex
, const void *pParameters
, UINT32 ParametersByteSize
,
1217 UINT32 OperationSet
)
1219 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1220 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This
, EffectIndex
, pParameters
,
1221 ParametersByteSize
, OperationSet
);
1225 static HRESULT WINAPI
XA2SUB_GetEffectParameters(IXAudio2SubmixVoice
*iface
,
1226 UINT32 EffectIndex
, void *pParameters
, UINT32 ParametersByteSize
)
1228 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1229 TRACE("%p, %u, %p, 0x%x\n", This
, EffectIndex
, pParameters
,
1230 ParametersByteSize
);
1234 static HRESULT WINAPI
XA2SUB_SetFilterParameters(IXAudio2SubmixVoice
*iface
,
1235 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
1237 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1238 TRACE("%p, %p, 0x%x\n", This
, pParameters
, OperationSet
);
1242 static void WINAPI
XA2SUB_GetFilterParameters(IXAudio2SubmixVoice
*iface
,
1243 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
1245 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1246 TRACE("%p, %p\n", This
, pParameters
);
1249 static HRESULT WINAPI
XA2SUB_SetOutputFilterParameters(IXAudio2SubmixVoice
*iface
,
1250 IXAudio2Voice
*pDestinationVoice
,
1251 const XAUDIO2_FILTER_PARAMETERS
*pParameters
, UINT32 OperationSet
)
1253 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1254 TRACE("%p, %p, %p, 0x%x\n", This
, pDestinationVoice
, pParameters
, OperationSet
);
1258 static void WINAPI
XA2SUB_GetOutputFilterParameters(IXAudio2SubmixVoice
*iface
,
1259 IXAudio2Voice
*pDestinationVoice
,
1260 XAUDIO2_FILTER_PARAMETERS
*pParameters
)
1262 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1263 TRACE("%p, %p, %p\n", This
, pDestinationVoice
, pParameters
);
1266 static HRESULT WINAPI
XA2SUB_SetVolume(IXAudio2SubmixVoice
*iface
, float Volume
,
1267 UINT32 OperationSet
)
1269 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1270 TRACE("%p, %f, 0x%x\n", This
, Volume
, OperationSet
);
1274 static void WINAPI
XA2SUB_GetVolume(IXAudio2SubmixVoice
*iface
, float *pVolume
)
1276 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1277 TRACE("%p, %p\n", This
, pVolume
);
1280 static HRESULT WINAPI
XA2SUB_SetChannelVolumes(IXAudio2SubmixVoice
*iface
, UINT32 Channels
,
1281 const float *pVolumes
, UINT32 OperationSet
)
1283 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1284 TRACE("%p, %u, %p, 0x%x\n", This
, Channels
, pVolumes
, OperationSet
);
1288 static void WINAPI
XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice
*iface
, UINT32 Channels
,
1291 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1292 TRACE("%p, %u, %p\n", This
, Channels
, pVolumes
);
1295 static HRESULT WINAPI
XA2SUB_SetOutputMatrix(IXAudio2SubmixVoice
*iface
,
1296 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
1297 UINT32 DestinationChannels
, const float *pLevelMatrix
,
1298 UINT32 OperationSet
)
1300 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1301 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This
, pDestinationVoice
,
1302 SourceChannels
, DestinationChannels
, pLevelMatrix
, OperationSet
);
1306 static void WINAPI
XA2SUB_GetOutputMatrix(IXAudio2SubmixVoice
*iface
,
1307 IXAudio2Voice
*pDestinationVoice
, UINT32 SourceChannels
,
1308 UINT32 DestinationChannels
, float *pLevelMatrix
)
1310 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1311 TRACE("%p, %p, %u, %u, %p\n", This
, pDestinationVoice
,
1312 SourceChannels
, DestinationChannels
, pLevelMatrix
);
1315 static void WINAPI
XA2SUB_DestroyVoice(IXAudio2SubmixVoice
*iface
)
1317 XA2SubmixImpl
*This
= impl_from_IXAudio2SubmixVoice(iface
);
1319 TRACE("%p\n", This
);
1321 EnterCriticalSection(&This
->lock
);
1323 This
->in_use
= FALSE
;
1325 LeaveCriticalSection(&This
->lock
);
1328 static const struct IXAudio2SubmixVoiceVtbl XAudio2SubmixVoice_Vtbl
= {
1329 XA2SUB_GetVoiceDetails
,
1330 XA2SUB_SetOutputVoices
,
1331 XA2SUB_SetEffectChain
,
1332 XA2SUB_EnableEffect
,
1333 XA2SUB_DisableEffect
,
1334 XA2SUB_GetEffectState
,
1335 XA2SUB_SetEffectParameters
,
1336 XA2SUB_GetEffectParameters
,
1337 XA2SUB_SetFilterParameters
,
1338 XA2SUB_GetFilterParameters
,
1339 XA2SUB_SetOutputFilterParameters
,
1340 XA2SUB_GetOutputFilterParameters
,
1343 XA2SUB_SetChannelVolumes
,
1344 XA2SUB_GetChannelVolumes
,
1345 XA2SUB_SetOutputMatrix
,
1346 XA2SUB_GetOutputMatrix
,
1350 static HRESULT WINAPI
IXAudio2Impl_QueryInterface(IXAudio2
*iface
, REFIID riid
,
1353 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1355 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1357 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
1358 IsEqualGUID(riid
, &IID_IXAudio2
))
1359 *ppvObject
= &This
->IXAudio2_iface
;
1360 else if(IsEqualGUID(riid
, &IID_IXAudio27
))
1361 *ppvObject
= &This
->IXAudio27_iface
;
1366 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1370 FIXME("(%p)->(%s,%p), not found\n", This
,debugstr_guid(riid
), ppvObject
);
1372 return E_NOINTERFACE
;
1375 static ULONG WINAPI
IXAudio2Impl_AddRef(IXAudio2
*iface
)
1377 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1378 ULONG ref
= InterlockedIncrement(&This
->ref
);
1379 TRACE("(%p)->(): Refcount now %u\n", This
, ref
);
1383 static ULONG WINAPI
IXAudio2Impl_Release(IXAudio2
*iface
)
1385 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1386 ULONG ref
= InterlockedDecrement(&This
->ref
);
1388 TRACE("(%p)->(): Refcount now %u\n", This
, ref
);
1392 XA2SourceImpl
*src
, *src2
;
1393 XA2SubmixImpl
*sub
, *sub2
;
1396 This
->stop_engine
= TRUE
;
1397 SetEvent(This
->mmevt
);
1398 WaitForSingleObject(This
->engine
, INFINITE
);
1399 CloseHandle(This
->engine
);
1402 LIST_FOR_EACH_ENTRY_SAFE(src
, src2
, &This
->source_voices
, XA2SourceImpl
, entry
){
1403 HeapFree(GetProcessHeap(), 0, src
->sends
);
1404 IXAudio2SourceVoice_DestroyVoice(&src
->IXAudio2SourceVoice_iface
);
1405 DeleteCriticalSection(&src
->lock
);
1406 HeapFree(GetProcessHeap(), 0, src
);
1409 LIST_FOR_EACH_ENTRY_SAFE(sub
, sub2
, &This
->submix_voices
, XA2SubmixImpl
, entry
){
1410 IXAudio2SubmixVoice_DestroyVoice(&sub
->IXAudio2SubmixVoice_iface
);
1411 DeleteCriticalSection(&sub
->lock
);
1412 HeapFree(GetProcessHeap(), 0, sub
);
1415 IXAudio2MasteringVoice_DestroyVoice(&This
->IXAudio2MasteringVoice_iface
);
1418 IMMDeviceEnumerator_Release(This
->devenum
);
1419 for(i
= 0; i
< This
->ndevs
; ++i
)
1420 CoTaskMemFree(This
->devids
[i
]);
1421 HeapFree(GetProcessHeap(), 0, This
->devids
);
1422 HeapFree(GetProcessHeap(), 0, This
->cbs
);
1424 CloseHandle(This
->mmevt
);
1426 DeleteCriticalSection(&This
->lock
);
1428 HeapFree(GetProcessHeap(), 0, This
);
1433 static HRESULT WINAPI
IXAudio2Impl_RegisterForCallbacks(IXAudio2
*iface
,
1434 IXAudio2EngineCallback
*pCallback
)
1436 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1439 TRACE("(%p)->(%p)\n", This
, pCallback
);
1441 EnterCriticalSection(&This
->lock
);
1443 for(i
= 0; i
< This
->ncbs
; ++i
){
1444 if(!This
->cbs
[i
] || This
->cbs
[i
] == pCallback
){
1445 This
->cbs
[i
] = pCallback
;
1446 LeaveCriticalSection(&This
->lock
);
1452 This
->cbs
= HeapReAlloc(GetProcessHeap(), 0, This
->cbs
, This
->ncbs
* sizeof(*This
->cbs
));
1454 This
->cbs
[i
] = pCallback
;
1456 LeaveCriticalSection(&This
->lock
);
1461 static void WINAPI
IXAudio2Impl_UnregisterForCallbacks(IXAudio2
*iface
,
1462 IXAudio2EngineCallback
*pCallback
)
1464 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1467 TRACE("(%p)->(%p)\n", This
, pCallback
);
1469 EnterCriticalSection(&This
->lock
);
1471 for(i
= 0; i
< This
->ncbs
; ++i
){
1472 if(This
->cbs
[i
] == pCallback
)
1476 for(; i
< This
->ncbs
- 1 && This
->cbs
[i
+ 1]; ++i
)
1477 This
->cbs
[i
] = This
->cbs
[i
+ 1];
1480 This
->cbs
[i
] = NULL
;
1482 LeaveCriticalSection(&This
->lock
);
1485 static WAVEFORMATEX
*copy_waveformat(const WAVEFORMATEX
*wfex
)
1489 if(wfex
->wFormatTag
== WAVE_FORMAT_PCM
){
1490 pwfx
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX
));
1491 CopyMemory(pwfx
, wfex
, sizeof(PCMWAVEFORMAT
));
1494 pwfx
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX
) + wfex
->cbSize
);
1495 CopyMemory(pwfx
, wfex
, sizeof(WAVEFORMATEX
) + wfex
->cbSize
);
1501 static HRESULT WINAPI
IXAudio2Impl_CreateSourceVoice(IXAudio2
*iface
,
1502 IXAudio2SourceVoice
**ppSourceVoice
, const WAVEFORMATEX
*pSourceFormat
,
1503 UINT32 flags
, float maxFrequencyRatio
,
1504 IXAudio2VoiceCallback
*pCallback
, const XAUDIO2_VOICE_SENDS
*pSendList
,
1505 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
1507 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1511 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This
, ppSourceVoice
,
1512 pSourceFormat
, flags
, maxFrequencyRatio
, pCallback
, pSendList
,
1515 dump_fmt(pSourceFormat
);
1517 EnterCriticalSection(&This
->lock
);
1519 LIST_FOR_EACH_ENTRY(src
, &This
->source_voices
, XA2SourceImpl
, entry
){
1524 if(&src
->entry
== &This
->source_voices
){
1525 src
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*src
));
1527 LeaveCriticalSection(&This
->lock
);
1528 return E_OUTOFMEMORY
;
1531 list_add_head(&This
->source_voices
, &src
->entry
);
1533 src
->IXAudio27SourceVoice_iface
.lpVtbl
= &XAudio27SourceVoice_Vtbl
;
1534 src
->IXAudio2SourceVoice_iface
.lpVtbl
= &XAudio2SourceVoice_Vtbl
;
1536 InitializeCriticalSection(&src
->lock
);
1537 src
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": XA2SourceImpl.lock");
1543 src
->running
= FALSE
;
1545 LeaveCriticalSection(&This
->lock
);
1547 src
->cb
= pCallback
;
1549 src
->al_fmt
= get_al_format(pSourceFormat
);
1551 src
->in_use
= FALSE
;
1552 WARN("OpenAL can't convert this format!\n");
1553 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
1556 src
->submit_blocksize
= pSourceFormat
->nBlockAlign
;
1558 src
->fmt
= copy_waveformat(pSourceFormat
);
1560 hr
= XA2SRC_SetOutputVoices(&src
->IXAudio2SourceVoice_iface
, pSendList
);
1562 src
->in_use
= FALSE
;
1566 alGenSources(1, &src
->al_src
);
1567 alGenBuffers(XAUDIO2_MAX_QUEUED_BUFFERS
, src
->al_bufs
);
1569 alSourcePlay(src
->al_src
);
1571 if(This
->version
== 27)
1572 *ppSourceVoice
= (IXAudio2SourceVoice
*)&src
->IXAudio27SourceVoice_iface
;
1574 *ppSourceVoice
= &src
->IXAudio2SourceVoice_iface
;
1576 TRACE("Created source voice: %p\n", src
);
1581 static HRESULT WINAPI
IXAudio2Impl_CreateSubmixVoice(IXAudio2
*iface
,
1582 IXAudio2SubmixVoice
**ppSubmixVoice
, UINT32 inputChannels
,
1583 UINT32 inputSampleRate
, UINT32 flags
, UINT32 processingStage
,
1584 const XAUDIO2_VOICE_SENDS
*pSendList
,
1585 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
1587 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1590 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This
, ppSubmixVoice
,
1591 inputChannels
, inputSampleRate
, flags
, processingStage
, pSendList
,
1594 EnterCriticalSection(&This
->lock
);
1596 LIST_FOR_EACH_ENTRY(sub
, &This
->submix_voices
, XA2SubmixImpl
, entry
){
1601 if(&sub
->entry
== &This
->submix_voices
){
1602 sub
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*sub
));
1604 LeaveCriticalSection(&This
->lock
);
1605 return E_OUTOFMEMORY
;
1608 list_add_head(&This
->submix_voices
, &sub
->entry
);
1610 sub
->IXAudio2SubmixVoice_iface
.lpVtbl
= &XAudio2SubmixVoice_Vtbl
;
1612 InitializeCriticalSection(&sub
->lock
);
1613 sub
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": XA2SubmixImpl.lock");
1618 LeaveCriticalSection(&This
->lock
);
1620 *ppSubmixVoice
= &sub
->IXAudio2SubmixVoice_iface
;
1622 TRACE("Created submix voice: %p\n", sub
);
1627 static ALenum
al_get_loopback_format(const WAVEFORMATEXTENSIBLE
*fmt
)
1629 if(fmt
->Format
.wFormatTag
== WAVE_FORMAT_PCM
||
1630 (fmt
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
&&
1631 IsEqualGUID(&fmt
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))){
1632 switch(fmt
->Format
.wBitsPerSample
){
1634 return ALC_UNSIGNED_BYTE_SOFT
;
1636 return ALC_SHORT_SOFT
;
1638 return ALC_INT_SOFT
;
1640 }else if(fmt
->Format
.wFormatTag
== WAVE_FORMAT_IEEE_FLOAT
||
1641 (fmt
->Format
.wFormatTag
== WAVE_FORMAT_EXTENSIBLE
&&
1642 IsEqualGUID(&fmt
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
))){
1643 if(fmt
->Format
.wBitsPerSample
== 32)
1644 return ALC_FLOAT_SOFT
;
1649 static HRESULT WINAPI
IXAudio2Impl_CreateMasteringVoice(IXAudio2
*iface
,
1650 IXAudio2MasteringVoice
**ppMasteringVoice
, UINT32 inputChannels
,
1651 UINT32 inputSampleRate
, UINT32 flags
, const WCHAR
*deviceId
,
1652 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
,
1653 AUDIO_STREAM_CATEGORY streamCategory
)
1655 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1660 REFERENCE_TIME period
;
1662 TRACE("(%p)->(%p, %u, %u, 0x%x, %s, %p, 0x%x)\n", This
,
1663 ppMasteringVoice
, inputChannels
, inputSampleRate
, flags
,
1664 wine_dbgstr_w(deviceId
), pEffectChain
, streamCategory
);
1667 WARN("Unknown flags set: 0x%x\n", flags
);
1670 WARN("Effect chain is unimplemented\n");
1672 EnterCriticalSection(&This
->lock
);
1674 /* there can only be one Mastering Voice, so just build it into XA2 */
1676 LeaveCriticalSection(&This
->lock
);
1677 return XAUDIO2_E_INVALID_CALL
;
1681 if(This
->ndevs
== 0){
1682 LeaveCriticalSection(&This
->lock
);
1683 return ERROR_NOT_FOUND
;
1685 deviceId
= This
->devids
[0];
1688 hr
= IMMDeviceEnumerator_GetDevice(This
->devenum
, deviceId
, &dev
);
1690 WARN("GetDevice failed: %08x\n", hr
);
1691 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1695 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
,
1696 CLSCTX_INPROC_SERVER
, NULL
, (void**)&This
->aclient
);
1698 WARN("Activate(IAudioClient) failed: %08x\n", hr
);
1699 IMMDevice_Release(dev
);
1700 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1704 IMMDevice_Release(dev
);
1706 hr
= IAudioClient_GetMixFormat(This
->aclient
, &fmt
);
1708 WARN("GetMixFormat failed: %08x\n", hr
);
1709 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1713 if(sizeof(WAVEFORMATEX
) + fmt
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)){
1714 FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
1715 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1719 if(inputChannels
== XAUDIO2_DEFAULT_CHANNELS
)
1720 inputChannels
= fmt
->nChannels
;
1721 if(inputSampleRate
== XAUDIO2_DEFAULT_SAMPLERATE
)
1722 inputSampleRate
= fmt
->nSamplesPerSec
;
1724 memcpy(&This
->fmt
, fmt
, sizeof(WAVEFORMATEX
) + fmt
->cbSize
);
1725 This
->fmt
.Format
.nChannels
= inputChannels
;
1726 This
->fmt
.Format
.nSamplesPerSec
= inputSampleRate
;
1727 This
->fmt
.Format
.nBlockAlign
= This
->fmt
.Format
.nChannels
* This
->fmt
.Format
.wBitsPerSample
/ 8;
1728 This
->fmt
.Format
.nAvgBytesPerSec
= This
->fmt
.Format
.nSamplesPerSec
* This
->fmt
.Format
.nBlockAlign
;
1729 This
->fmt
.dwChannelMask
= get_channel_mask(This
->fmt
.Format
.nChannels
);
1734 hr
= IAudioClient_IsFormatSupported(This
->aclient
,
1735 AUDCLNT_SHAREMODE_SHARED
, &This
->fmt
.Format
, &fmt
);
1737 if(sizeof(WAVEFORMATEX
) + fmt
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)){
1738 FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
1739 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1742 memcpy(&This
->fmt
, fmt
, sizeof(WAVEFORMATEX
) + fmt
->cbSize
);
1747 hr
= IAudioClient_Initialize(This
->aclient
, AUDCLNT_SHAREMODE_SHARED
,
1748 AUDCLNT_STREAMFLAGS_EVENTCALLBACK
, inputSampleRate
/* 1s buffer */,
1749 0, &This
->fmt
.Format
, NULL
);
1751 WARN("Initialize failed: %08x\n", hr
);
1752 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1756 hr
= IAudioClient_GetDevicePeriod(This
->aclient
, &period
, NULL
);
1758 WARN("GetDevicePeriod failed: %08x\n", hr
);
1759 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1763 This
->period_frames
= MulDiv(period
, inputSampleRate
, 10000000);
1765 hr
= IAudioClient_SetEventHandle(This
->aclient
, This
->mmevt
);
1767 WARN("Initialize failed: %08x\n", hr
);
1768 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1772 hr
= IAudioClient_GetService(This
->aclient
, &IID_IAudioRenderClient
,
1773 (void**)&This
->render
);
1775 WARN("GetService(IAudioRenderClient) failed: %08x\n", hr
);
1776 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1780 /* setup openal context */
1781 attrs
[0] = ALC_FORMAT_CHANNELS_SOFT
;
1782 switch(inputChannels
){
1784 attrs
[1] = ALC_MONO_SOFT
;
1787 attrs
[1] = ALC_STEREO_SOFT
;
1790 attrs
[1] = ALC_QUAD_SOFT
;
1793 attrs
[1] = ALC_5POINT1_SOFT
;
1796 attrs
[1] = ALC_6POINT1_SOFT
;
1799 attrs
[1] = ALC_7POINT1_SOFT
;
1802 WARN("OpenAL doesn't support %u channels\n", inputChannels
);
1803 LeaveCriticalSection(&This
->lock
);
1804 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
1806 attrs
[2] = ALC_FREQUENCY
;
1807 attrs
[3] = inputSampleRate
;
1808 attrs
[4] = ALC_FORMAT_TYPE_SOFT
;
1809 attrs
[5] = al_get_loopback_format(&This
->fmt
);
1813 WARN("OpenAL can't output samples in this format\n");
1814 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1818 This
->al_device
= palcLoopbackOpenDeviceSOFT(NULL
);
1819 if(!This
->al_device
){
1820 WARN("alcLoopbackOpenDeviceSOFT failed\n");
1821 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1825 This
->al_ctx
= alcCreateContext(This
->al_device
, attrs
);
1827 WARN("alcCreateContext failed\n");
1828 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1832 if(alcMakeContextCurrent(This
->al_ctx
) == ALC_FALSE
){
1833 WARN("alcMakeContextCurrent failed\n");
1834 hr
= XAUDIO2_E_DEVICE_INVALIDATED
;
1838 IAudioClient_Start(This
->aclient
);
1840 *ppMasteringVoice
= &This
->IXAudio2MasteringVoice_iface
;
1845 IAudioRenderClient_Release(This
->render
);
1846 This
->render
= NULL
;
1849 IAudioClient_Release(This
->aclient
);
1850 This
->aclient
= NULL
;
1853 alcDestroyContext(This
->al_ctx
);
1854 This
->al_ctx
= NULL
;
1856 if(This
->al_device
){
1857 alcCloseDevice(This
->al_device
);
1858 This
->al_device
= NULL
;
1862 LeaveCriticalSection(&This
->lock
);
1867 static DWORD WINAPI
engine_threadproc(void *arg
);
1869 static HRESULT WINAPI
IXAudio2Impl_StartEngine(IXAudio2
*iface
)
1871 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1873 TRACE("(%p)->()\n", This
);
1875 This
->running
= TRUE
;
1878 This
->engine
= CreateThread(NULL
, 0, engine_threadproc
, This
, 0, NULL
);
1883 static void WINAPI
IXAudio2Impl_StopEngine(IXAudio2
*iface
)
1885 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1887 TRACE("(%p)->()\n", This
);
1889 This
->running
= FALSE
;
1892 static HRESULT WINAPI
IXAudio2Impl_CommitChanges(IXAudio2
*iface
,
1893 UINT32 operationSet
)
1895 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1897 FIXME("(%p)->(0x%x): stub!\n", This
, operationSet
);
1902 static void WINAPI
IXAudio2Impl_GetPerformanceData(IXAudio2
*iface
,
1903 XAUDIO2_PERFORMANCE_DATA
*pPerfData
)
1905 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1907 FIXME("(%p)->(%p): stub!\n", This
, pPerfData
);
1909 memset(pPerfData
, 0, sizeof(*pPerfData
));
1912 static void WINAPI
IXAudio2Impl_SetDebugConfiguration(IXAudio2
*iface
,
1913 const XAUDIO2_DEBUG_CONFIGURATION
*pDebugConfiguration
,
1916 IXAudio2Impl
*This
= impl_from_IXAudio2(iface
);
1918 FIXME("(%p)->(%p, %p): stub!\n", This
, pDebugConfiguration
, pReserved
);
1922 static const IXAudio2Vtbl XAudio2_Vtbl
=
1924 IXAudio2Impl_QueryInterface
,
1925 IXAudio2Impl_AddRef
,
1926 IXAudio2Impl_Release
,
1927 IXAudio2Impl_RegisterForCallbacks
,
1928 IXAudio2Impl_UnregisterForCallbacks
,
1929 IXAudio2Impl_CreateSourceVoice
,
1930 IXAudio2Impl_CreateSubmixVoice
,
1931 IXAudio2Impl_CreateMasteringVoice
,
1932 IXAudio2Impl_StartEngine
,
1933 IXAudio2Impl_StopEngine
,
1934 IXAudio2Impl_CommitChanges
,
1935 IXAudio2Impl_GetPerformanceData
,
1936 IXAudio2Impl_SetDebugConfiguration
1939 static HRESULT WINAPI
XA27_QueryInterface(IXAudio27
*iface
, REFIID riid
,
1942 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
1943 return IXAudio2Impl_QueryInterface(&This
->IXAudio2_iface
, riid
, ppvObject
);
1946 static ULONG WINAPI
XA27_AddRef(IXAudio27
*iface
)
1948 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
1949 return IXAudio2Impl_AddRef(&This
->IXAudio2_iface
);
1952 static ULONG WINAPI
XA27_Release(IXAudio27
*iface
)
1954 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
1955 return IXAudio2Impl_Release(&This
->IXAudio2_iface
);
1958 static HRESULT WINAPI
XA27_GetDeviceCount(IXAudio27
*iface
, UINT32
*pCount
)
1960 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
1962 TRACE("%p, %p\n", This
, pCount
);
1964 *pCount
= This
->ndevs
;
1969 static HRESULT WINAPI
XA27_GetDeviceDetails(IXAudio27
*iface
, UINT32 index
,
1970 XAUDIO2_DEVICE_DETAILS
*pDeviceDetails
)
1972 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
1975 IAudioClient
*client
;
1980 TRACE("%p, %u, %p\n", This
, index
, pDeviceDetails
);
1982 if(index
>= This
->ndevs
)
1983 return E_INVALIDARG
;
1985 hr
= IMMDeviceEnumerator_GetDevice(This
->devenum
, This
->devids
[index
], &dev
);
1987 WARN("GetDevice failed: %08x\n", hr
);
1991 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
,
1992 NULL
, (void**)&client
);
1994 WARN("Activate failed: %08x\n", hr
);
1995 IMMDevice_Release(dev
);
1999 hr
= IMMDevice_OpenPropertyStore(dev
, STGM_READ
, &ps
);
2001 WARN("OpenPropertyStore failed: %08x\n", hr
);
2002 IAudioClient_Release(client
);
2003 IMMDevice_Release(dev
);
2007 PropVariantInit(&var
);
2009 hr
= IPropertyStore_GetValue(ps
, (PROPERTYKEY
*)&DEVPKEY_Device_FriendlyName
, &var
);
2011 WARN("GetValue failed: %08x\n", hr
);
2015 lstrcpynW(pDeviceDetails
->DisplayName
, var
.u
.pwszVal
, sizeof(pDeviceDetails
->DisplayName
)/sizeof(WCHAR
));
2017 PropVariantClear(&var
);
2019 hr
= IAudioClient_GetMixFormat(client
, &wfx
);
2021 WARN("GetMixFormat failed: %08x\n", hr
);
2025 lstrcpyW(pDeviceDetails
->DeviceID
, This
->devids
[index
]);
2028 pDeviceDetails
->Role
= GlobalDefaultDevice
;
2030 pDeviceDetails
->Role
= NotDefaultDevice
;
2032 if(sizeof(WAVEFORMATEX
) + wfx
->cbSize
> sizeof(pDeviceDetails
->OutputFormat
)){
2033 FIXME("AudioClient format is too large to fit into WAVEFORMATEXTENSIBLE!\n");
2038 memcpy(&pDeviceDetails
->OutputFormat
, wfx
, sizeof(WAVEFORMATEX
) + wfx
->cbSize
);
2043 IPropertyStore_Release(ps
);
2044 IAudioClient_Release(client
);
2045 IMMDevice_Release(dev
);
2050 static HRESULT WINAPI
XA27_Initialize(IXAudio27
*iface
, UINT32 flags
,
2051 XAUDIO2_PROCESSOR processor
)
2053 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2054 TRACE("(%p)->(0x%x, 0x%x)\n", This
, flags
, processor
);
2058 static HRESULT WINAPI
XA27_RegisterForCallbacks(IXAudio27
*iface
,
2059 IXAudio2EngineCallback
*pCallback
)
2061 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2062 return IXAudio2Impl_RegisterForCallbacks(&This
->IXAudio2_iface
, pCallback
);
2065 static void WINAPI
XA27_UnregisterForCallbacks(IXAudio27
*iface
,
2066 IXAudio2EngineCallback
*pCallback
)
2068 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2069 IXAudio2Impl_UnregisterForCallbacks(&This
->IXAudio2_iface
, pCallback
);
2072 static HRESULT WINAPI
XA27_CreateSourceVoice(IXAudio27
*iface
,
2073 IXAudio2SourceVoice
**ppSourceVoice
, const WAVEFORMATEX
*pSourceFormat
,
2074 UINT32 flags
, float maxFrequencyRatio
,
2075 IXAudio2VoiceCallback
*pCallback
, const XAUDIO2_VOICE_SENDS
*pSendList
,
2076 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
2078 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2079 return IXAudio2Impl_CreateSourceVoice(&This
->IXAudio2_iface
, ppSourceVoice
,
2080 pSourceFormat
, flags
, maxFrequencyRatio
, pCallback
, pSendList
,
2084 static HRESULT WINAPI
XA27_CreateSubmixVoice(IXAudio27
*iface
,
2085 IXAudio2SubmixVoice
**ppSubmixVoice
, UINT32 inputChannels
,
2086 UINT32 inputSampleRate
, UINT32 flags
, UINT32 processingStage
,
2087 const XAUDIO2_VOICE_SENDS
*pSendList
,
2088 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
2090 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2091 return IXAudio2Impl_CreateSubmixVoice(&This
->IXAudio2_iface
, ppSubmixVoice
,
2092 inputChannels
, inputSampleRate
, flags
, processingStage
, pSendList
,
2096 static HRESULT WINAPI
XA27_CreateMasteringVoice(IXAudio27
*iface
,
2097 IXAudio2MasteringVoice
**ppMasteringVoice
, UINT32 inputChannels
,
2098 UINT32 inputSampleRate
, UINT32 flags
, UINT32 deviceIndex
,
2099 const XAUDIO2_EFFECT_CHAIN
*pEffectChain
)
2101 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2103 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p)\n", This
, ppMasteringVoice
,
2104 inputChannels
, inputSampleRate
, flags
, deviceIndex
,
2107 if(deviceIndex
>= This
->ndevs
)
2108 return E_INVALIDARG
;
2110 return IXAudio2Impl_CreateMasteringVoice(&This
->IXAudio2_iface
, ppMasteringVoice
,
2111 inputChannels
, inputSampleRate
, flags
, This
->devids
[deviceIndex
],
2112 pEffectChain
, AudioCategory_GameEffects
);
2115 static HRESULT WINAPI
XA27_StartEngine(IXAudio27
*iface
)
2117 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2118 return IXAudio2Impl_StartEngine(&This
->IXAudio2_iface
);
2121 static void WINAPI
XA27_StopEngine(IXAudio27
*iface
)
2123 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2124 return IXAudio2Impl_StopEngine(&This
->IXAudio2_iface
);
2127 static HRESULT WINAPI
XA27_CommitChanges(IXAudio27
*iface
, UINT32 operationSet
)
2129 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2130 return IXAudio2Impl_CommitChanges(&This
->IXAudio2_iface
, operationSet
);
2133 static void WINAPI
XA27_GetPerformanceData(IXAudio27
*iface
,
2134 XAUDIO2_PERFORMANCE_DATA
*pPerfData
)
2136 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2137 return IXAudio2Impl_GetPerformanceData(&This
->IXAudio2_iface
, pPerfData
);
2140 static void WINAPI
XA27_SetDebugConfiguration(IXAudio27
*iface
,
2141 const XAUDIO2_DEBUG_CONFIGURATION
*pDebugConfiguration
,
2144 IXAudio2Impl
*This
= impl_from_IXAudio27(iface
);
2145 return IXAudio2Impl_SetDebugConfiguration(&This
->IXAudio2_iface
,
2146 pDebugConfiguration
, pReserved
);
2149 static const IXAudio27Vtbl XAudio27_Vtbl
= {
2150 XA27_QueryInterface
,
2153 XA27_GetDeviceCount
,
2154 XA27_GetDeviceDetails
,
2156 XA27_RegisterForCallbacks
,
2157 XA27_UnregisterForCallbacks
,
2158 XA27_CreateSourceVoice
,
2159 XA27_CreateSubmixVoice
,
2160 XA27_CreateMasteringVoice
,
2164 XA27_GetPerformanceData
,
2165 XA27_SetDebugConfiguration
2168 static HRESULT WINAPI
XAudio2CF_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **ppobj
)
2170 if(IsEqualGUID(riid
, &IID_IUnknown
)
2171 || IsEqualGUID(riid
, &IID_IClassFactory
))
2173 IClassFactory_AddRef(iface
);
2179 WARN("(%p)->(%s, %p): interface not found\n", iface
, debugstr_guid(riid
), ppobj
);
2180 return E_NOINTERFACE
;
2183 static ULONG WINAPI
XAudio2CF_AddRef(IClassFactory
*iface
)
2188 static ULONG WINAPI
XAudio2CF_Release(IClassFactory
*iface
)
2193 static HRESULT
initialize_mmdevices(IXAudio2Impl
*This
)
2195 IMMDeviceCollection
*devcoll
;
2200 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
,
2201 CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&This
->devenum
);
2206 hr
= IMMDeviceEnumerator_EnumAudioEndpoints(This
->devenum
, eRender
,
2207 DEVICE_STATE_ACTIVE
, &devcoll
);
2212 hr
= IMMDeviceCollection_GetCount(devcoll
, &devcount
);
2214 IMMDeviceCollection_Release(devcoll
);
2220 IMMDevice
*dev
, *def_dev
;
2222 /* make sure that device 0 is the default device */
2223 IMMDeviceEnumerator_GetDefaultAudioEndpoint(This
->devenum
, eRender
, eConsole
, &def_dev
);
2225 This
->devids
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
*) * devcount
);
2227 for(i
= 0; i
< devcount
; ++i
){
2228 hr
= IMMDeviceCollection_Item(devcoll
, i
, &dev
);
2239 hr
= IMMDevice_GetId(dev
, &This
->devids
[idx
]);
2241 WARN("GetId failed: %08x\n", hr
);
2242 HeapFree(GetProcessHeap(), 0, This
->devids
);
2243 This
->devids
= NULL
;
2244 IMMDevice_Release(dev
);
2248 IMMDevice_Release(dev
);
2250 WARN("Item failed: %08x\n", hr
);
2251 HeapFree(GetProcessHeap(), 0, This
->devids
);
2252 This
->devids
= NULL
;
2253 IMMDeviceCollection_Release(devcoll
);
2259 IMMDeviceCollection_Release(devcoll
);
2261 This
->ndevs
= devcount
;
2266 static HRESULT WINAPI
XAudio2CF_CreateInstance(IClassFactory
*iface
, IUnknown
*pOuter
,
2267 REFIID riid
, void **ppobj
)
2270 IXAudio2Impl
*object
;
2272 TRACE("(static)->(%p,%s,%p)\n", pOuter
, debugstr_guid(riid
), ppobj
);
2277 return CLASS_E_NOAGGREGATION
;
2279 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
));
2281 return E_OUTOFMEMORY
;
2283 object
->IXAudio27_iface
.lpVtbl
= &XAudio27_Vtbl
;
2284 object
->IXAudio2_iface
.lpVtbl
= &XAudio2_Vtbl
;
2285 object
->IXAudio2MasteringVoice_iface
.lpVtbl
= &XAudio2MasteringVoice_Vtbl
;
2287 if(IsEqualGUID(riid
, &IID_IXAudio27
))
2288 object
->version
= 27;
2290 object
->version
= 28;
2292 list_init(&object
->source_voices
);
2293 list_init(&object
->submix_voices
);
2295 object
->mmevt
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2296 InitializeCriticalSection(&object
->lock
);
2297 object
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": IXAudio2Impl.lock");
2299 hr
= IXAudio2_QueryInterface(&object
->IXAudio2_iface
, riid
, ppobj
);
2301 HeapFree(GetProcessHeap(), 0, object
);
2305 hr
= initialize_mmdevices(object
);
2307 IUnknown_Release((IUnknown
*)*ppobj
);
2312 object
->cbs
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->ncbs
* sizeof(*object
->cbs
));
2314 IXAudio2_StartEngine(&object
->IXAudio2_iface
);
2319 static HRESULT WINAPI
XAudio2CF_LockServer(IClassFactory
*iface
, BOOL dolock
)
2321 FIXME("(static)->(%d): stub!\n", dolock
);
2325 static const IClassFactoryVtbl XAudio2CF_Vtbl
=
2327 XAudio2CF_QueryInterface
,
2330 XAudio2CF_CreateInstance
,
2331 XAudio2CF_LockServer
2334 static IClassFactory xaudio2_cf
= { &XAudio2CF_Vtbl
};
2336 HRESULT WINAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void **ppv
)
2338 IClassFactory
*factory
= NULL
;
2340 TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
2342 if(IsEqualGUID(rclsid
, &CLSID_XAudio2
)) {
2343 factory
= &xaudio2_cf
;
2345 if(!factory
) return CLASS_E_CLASSNOTAVAILABLE
;
2347 return IClassFactory_QueryInterface(factory
, riid
, ppv
);
2350 /* returns TRUE if there is more data avilable in the buffer, FALSE if the
2351 * buffer's data has all been queued */
2352 static BOOL
xa2buffer_queue_period(XA2SourceImpl
*src
, XA2Buffer
*buf
, ALuint al_buf
)
2354 UINT32 submit_bytes
;
2355 const BYTE
*submit_buf
= NULL
;
2357 if(buf
->offs_bytes
>= buf
->xa2buffer
.AudioBytes
){
2358 WARN("Shouldn't happen: Trying to push frames from a spent buffer?\n");
2362 submit_bytes
= min(src
->xa2
->period_frames
* src
->submit_blocksize
, buf
->xa2buffer
.AudioBytes
- buf
->offs_bytes
);
2363 submit_buf
= buf
->xa2buffer
.pAudioData
+ buf
->offs_bytes
;
2364 buf
->offs_bytes
+= submit_bytes
;
2366 alBufferData(al_buf
, src
->al_fmt
, submit_buf
, submit_bytes
,
2367 src
->fmt
->nSamplesPerSec
);
2369 alSourceQueueBuffers(src
->al_src
, 1, &al_buf
);
2371 src
->in_al_bytes
+= submit_bytes
;
2372 src
->al_bufs_used
++;
2374 buf
->latest_al_buf
= al_buf
;
2376 TRACE("queueing %u bytes, now %u in AL\n", submit_bytes
, src
->in_al_bytes
);
2378 return buf
->offs_bytes
< buf
->xa2buffer
.AudioBytes
;
2381 static void update_source_state(XA2SourceImpl
*src
)
2387 alGetSourcei(src
->al_src
, AL_BUFFERS_PROCESSED
, &processed
);
2390 ALuint al_buffers
[XAUDIO2_MAX_QUEUED_BUFFERS
];
2392 alSourceUnqueueBuffers(src
->al_src
, processed
, al_buffers
);
2393 src
->first_al_buf
+= processed
;
2394 src
->first_al_buf
%= XAUDIO2_MAX_QUEUED_BUFFERS
;
2395 src
->al_bufs_used
-= processed
;
2397 for(i
= 0; i
< processed
; ++i
){
2400 alGetBufferi(al_buffers
[i
], AL_SIZE
, &bufsize
);
2402 src
->in_al_bytes
-= bufsize
;
2403 src
->played_frames
+= bufsize
/ src
->submit_blocksize
;
2405 if(al_buffers
[i
] == src
->buffers
[src
->first_buf
].latest_al_buf
){
2406 DWORD old_buf
= src
->first_buf
;
2409 src
->first_buf
%= XAUDIO2_MAX_QUEUED_BUFFERS
;
2412 TRACE("%p: done with buffer %u\n", src
, old_buf
);
2415 IXAudio2VoiceCallback_OnBufferEnd(src
->cb
,
2416 src
->buffers
[old_buf
].xa2buffer
.pContext
);
2419 IXAudio2VoiceCallback_OnBufferStart(src
->cb
,
2420 src
->buffers
[src
->first_buf
].xa2buffer
.pContext
);
2426 alGetSourcei(src
->al_src
, AL_BYTE_OFFSET
, &bufpos
);
2428 /* maintain 4 periods in AL */
2429 while(src
->cur_buf
!= (src
->first_buf
+ src
->nbufs
) % XAUDIO2_MAX_QUEUED_BUFFERS
&&
2430 src
->in_al_bytes
- bufpos
< 4 * src
->xa2
->period_frames
* src
->submit_blocksize
){
2431 TRACE("%p: going to queue a period from buffer %u\n", src
, src
->cur_buf
);
2433 /* starting from an empty buffer */
2434 if(src
->cb
&& src
->cur_buf
== src
->first_buf
&& src
->buffers
[src
->cur_buf
].offs_bytes
== 0)
2435 IXAudio2VoiceCallback_OnBufferStart(src
->cb
,
2436 src
->buffers
[src
->first_buf
].xa2buffer
.pContext
);
2438 if(!xa2buffer_queue_period(src
, &src
->buffers
[src
->cur_buf
],
2439 src
->al_bufs
[(src
->first_al_buf
+ src
->al_bufs_used
) % XAUDIO2_MAX_QUEUED_BUFFERS
])){
2440 /* buffer is spent, move on */
2442 src
->cur_buf
%= XAUDIO2_MAX_QUEUED_BUFFERS
;
2447 static void do_engine_tick(IXAudio2Impl
*This
)
2452 UINT32 nframes
, i
, pad
;
2454 /* maintain up to 3 periods in mmdevapi */
2455 hr
= IAudioClient_GetCurrentPadding(This
->aclient
, &pad
);
2457 WARN("GetCurrentPadding failed: 0x%x\n", hr
);
2461 nframes
= This
->period_frames
* 3 - pad
;
2462 TRACE("going to render %u frames\n", nframes
);
2467 for(i
= 0; i
< This
->ncbs
&& This
->cbs
[i
]; ++i
)
2468 IXAudio2EngineCallback_OnProcessingPassStart(This
->cbs
[i
]);
2470 LIST_FOR_EACH_ENTRY(src
, &This
->source_voices
, XA2SourceImpl
, entry
){
2473 EnterCriticalSection(&src
->lock
);
2475 if(!src
->in_use
|| !src
->running
){
2476 LeaveCriticalSection(&src
->lock
);
2481 /* TODO: detect incoming underrun and inform callback */
2482 IXAudio2VoiceCallback_OnVoiceProcessingPassStart(src
->cb
, 0);
2484 update_source_state(src
);
2486 alGetSourcei(src
->al_src
, AL_SOURCE_STATE
, &st
);
2487 if(st
!= AL_PLAYING
)
2488 alSourcePlay(src
->al_src
);
2491 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(src
->cb
);
2493 LeaveCriticalSection(&src
->lock
);
2496 hr
= IAudioRenderClient_GetBuffer(This
->render
, nframes
, &buf
);
2498 WARN("GetBuffer failed: %08x\n", hr
);
2500 palcRenderSamplesSOFT(This
->al_device
, buf
, nframes
);
2502 hr
= IAudioRenderClient_ReleaseBuffer(This
->render
, nframes
, 0);
2504 WARN("ReleaseBuffer failed: %08x\n", hr
);
2506 for(i
= 0; i
< This
->ncbs
&& This
->cbs
[i
]; ++i
)
2507 IXAudio2EngineCallback_OnProcessingPassEnd(This
->cbs
[i
]);
2510 static DWORD WINAPI
engine_threadproc(void *arg
)
2512 IXAudio2Impl
*This
= arg
;
2514 WaitForSingleObject(This
->mmevt
, INFINITE
);
2516 if(This
->stop_engine
)
2522 EnterCriticalSection(&This
->lock
);
2524 do_engine_tick(This
);
2526 LeaveCriticalSection(&This
->lock
);