xaudio2: Implement IXAudio2SourceVoice::SubmitSourceBuffer.
[wine.git] / dlls / xaudio2_7 / xaudio_dll.c
blob26670b7d611fc638b8e792758534093222792cf8
1 /*
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
20 #include <stdarg.h>
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
24 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
30 #include "ole2.h"
31 #include "rpcproxy.h"
33 #include "wine/debug.h"
34 #include "wine/list.h"
35 #include <propsys.h>
36 #include "initguid.h"
38 #include "mmsystem.h"
39 #include "xaudio2.h"
40 #include "devpkey.h"
41 #include "mmdeviceapi.h"
42 #include "audioclient.h"
44 #include <AL/al.h>
45 #include <AL/alc.h>
46 #include <AL/alext.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)
63 #undef DOCASE
64 default:
65 TRACE("Unknown");
66 break;
68 TRACE(")\n");
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);
89 switch (reason)
91 case DLL_WINE_PREATTACH:
92 return FALSE; /* prefer native version */
93 case DLL_PROCESS_ATTACH:
94 instance = hinstDLL;
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");
101 return FALSE;
104 break;
106 return TRUE;
109 HRESULT WINAPI DllCanUnloadNow(void)
111 return S_FALSE;
114 HRESULT WINAPI DllRegisterServer(void)
116 TRACE("\n");
117 return __wine_register_resources(instance);
120 HRESULT WINAPI DllUnregisterServer(void)
122 TRACE("\n");
123 return __wine_unregister_resources(instance);
126 typedef struct _XA2Buffer {
127 XAUDIO2_BUFFER xa2buffer;
128 DWORD offs_bytes;
129 UINT32 latest_al_buf;
130 } XA2Buffer;
132 typedef struct _IXAudio2Impl IXAudio2Impl;
134 typedef struct _XA2SourceImpl {
135 IXAudio27SourceVoice IXAudio27SourceVoice_iface;
136 IXAudio2SourceVoice IXAudio2SourceVoice_iface;
138 IXAudio2Impl *xa2;
140 BOOL in_use;
142 CRITICAL_SECTION lock;
144 WAVEFORMATEX *fmt;
145 ALenum al_fmt;
146 UINT32 submit_blocksize;
148 IXAudio2VoiceCallback *cb;
150 DWORD nsends;
151 XAUDIO2_SEND_DESCRIPTOR *sends;
153 BOOL running;
155 UINT64 played_frames;
157 XA2Buffer buffers[XAUDIO2_MAX_QUEUED_BUFFERS];
158 UINT32 first_buf, cur_buf, nbufs, in_al_bytes;
160 ALuint al_src;
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;
166 struct list entry;
167 } XA2SourceImpl;
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;
182 BOOL in_use;
184 CRITICAL_SECTION lock;
186 struct list entry;
187 } XA2SubmixImpl;
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;
199 LONG ref;
201 CRITICAL_SECTION lock;
203 HANDLE engine, mmevt;
204 BOOL stop_engine;
206 DWORD version;
208 struct list source_voices;
209 struct list submix_voices;
211 IMMDeviceEnumerator *devenum;
213 WCHAR **devids;
214 UINT32 ndevs;
216 IAudioClient *aclient;
217 IAudioRenderClient *render;
219 UINT32 period_frames;
221 WAVEFORMATEXTENSIBLE fmt;
223 ALCdevice *al_device;
224 ALCcontext *al_ctx;
226 UINT32 ncbs;
227 IXAudio2EngineCallback **cbs;
229 BOOL running;
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)
249 switch(channels){
250 case 0:
251 return 0;
252 case 1:
253 return KSAUDIO_SPEAKER_MONO;
254 case 2:
255 return KSAUDIO_SPEAKER_STEREO;
256 case 3:
257 return KSAUDIO_SPEAKER_STEREO | SPEAKER_LOW_FREQUENCY;
258 case 4:
259 return KSAUDIO_SPEAKER_QUAD; /* not _SURROUND */
260 case 5:
261 return KSAUDIO_SPEAKER_QUAD | SPEAKER_LOW_FREQUENCY;
262 case 6:
263 return KSAUDIO_SPEAKER_5POINT1; /* not 5POINT1_SURROUND */
264 case 7:
265 return KSAUDIO_SPEAKER_5POINT1 | SPEAKER_BACK_CENTER;
266 case 8:
267 return KSAUDIO_SPEAKER_7POINT1_SURROUND; /* Vista deprecates 7POINT1 */
269 FIXME("Unknown speaker configuration: %u\n", channels);
270 return 0;
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);
284 int i;
285 XAUDIO2_VOICE_SENDS def_send;
286 XAUDIO2_SEND_DESCRIPTOR def_desc;
288 TRACE("%p, %p\n", This, pSendList);
290 if(!pSendList){
291 def_desc.Flags = 0;
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;
311 }else
312 memset(This->sends, 0, sizeof(*This->sends) * This->nsends);
314 memcpy(This->sends, pSendList->pSends, sizeof(*This->sends) * pSendList->SendCount);
316 return S_OK;
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);
324 return S_OK;
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);
332 return S_OK;
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);
340 return S_OK;
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,
352 UINT32 OperationSet)
354 XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
355 TRACE("%p, %u, %p, 0x%x, 0x%x\n", This, EffectIndex, pParameters,
356 ParametersByteSize, OperationSet);
357 return S_OK;
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,
365 ParametersByteSize);
366 return S_OK;
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);
374 return S_OK;
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);
390 return S_OK;
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,
402 UINT32 OperationSet)
404 XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
405 TRACE("%p, %f, 0x%x\n", This, Volume, OperationSet);
406 return S_OK;
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);
420 return S_OK;
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,
433 UINT32 OperationSet)
435 XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
436 TRACE("%p, %p, %u, %u, %p, 0x%x\n", This, pDestinationVoice,
437 SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
438 return S_OK;
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);
453 ALint processed;
455 TRACE("%p\n", This);
457 EnterCriticalSection(&This->lock);
459 if(!This->in_use){
460 LeaveCriticalSection(&This->lock);
461 return;
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);
477 if(processed > 0){
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;
491 This->nbufs = 0;
492 This->first_buf = 0;
493 This->cur_buf = 0;
495 LeaveCriticalSection(&This->lock);
498 static HRESULT WINAPI XA2SRC_Start(IXAudio2SourceVoice *iface, UINT32 Flags,
499 UINT32 OperationSet)
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);
511 return S_OK;
514 static HRESULT WINAPI XA2SRC_Stop(IXAudio2SourceVoice *iface, UINT32 Flags,
515 UINT32 OperationSet)
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);
527 return S_OK;
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){
537 case 8:
538 switch(fmt->nChannels){
539 case 1:
540 return AL_FORMAT_MONO8;
541 case 2:
542 return AL_FORMAT_STEREO8;
543 case 4:
544 return AL_FORMAT_QUAD8;
545 case 6:
546 return AL_FORMAT_51CHN8;
547 case 7:
548 return AL_FORMAT_61CHN8;
549 case 8:
550 return AL_FORMAT_71CHN8;
552 case 16:
553 switch(fmt->nChannels){
554 case 1:
555 return AL_FORMAT_MONO16;
556 case 2:
557 return AL_FORMAT_STEREO16;
558 case 4:
559 return AL_FORMAT_QUAD16;
560 case 6:
561 return AL_FORMAT_51CHN16;
562 case 7:
563 return AL_FORMAT_61CHN16;
564 case 8:
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){
573 case 1:
574 return AL_FORMAT_MONO_FLOAT32;
575 case 2:
576 return AL_FORMAT_STEREO_FLOAT32;
580 return 0;
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);
587 XA2Buffer *buf;
588 UINT32 buf_idx;
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));
620 buf->offs_bytes = 0;
621 buf->latest_al_buf = -1;
623 ++This->nbufs;
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);
630 return S_OK;
633 static HRESULT WINAPI XA2SRC_FlushSourceBuffers(IXAudio2SourceVoice *iface)
635 XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
636 TRACE("%p\n", This);
637 return S_OK;
640 static HRESULT WINAPI XA2SRC_Discontinuity(IXAudio2SourceVoice *iface)
642 XA2SourceImpl *This = impl_from_IXAudio2SourceVoice(iface);
643 TRACE("%p\n", This);
644 return S_OK;
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);
651 return S_OK;
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);
666 return S_OK;
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);
681 return S_OK;
684 static const IXAudio2SourceVoiceVtbl XAudio2SourceVoice_Vtbl = {
685 XA2SRC_GetVoiceDetails,
686 XA2SRC_SetOutputVoices,
687 XA2SRC_SetEffectChain,
688 XA2SRC_EnableEffect,
689 XA2SRC_DisableEffect,
690 XA2SRC_GetEffectState,
691 XA2SRC_SetEffectParameters,
692 XA2SRC_GetEffectParameters,
693 XA2SRC_SetFilterParameters,
694 XA2SRC_GetFilterParameters,
695 XA2SRC_SetOutputFilterParameters,
696 XA2SRC_GetOutputFilterParameters,
697 XA2SRC_SetVolume,
698 XA2SRC_GetVolume,
699 XA2SRC_SetChannelVolumes,
700 XA2SRC_GetChannelVolumes,
701 XA2SRC_SetOutputMatrix,
702 XA2SRC_GetOutputMatrix,
703 XA2SRC_DestroyVoice,
704 XA2SRC_Start,
705 XA2SRC_Stop,
706 XA2SRC_SubmitSourceBuffer,
707 XA2SRC_FlushSourceBuffers,
708 XA2SRC_Discontinuity,
709 XA2SRC_ExitLoop,
710 XA2SRC_GetState,
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,
760 UINT32 OperationSet)
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,
809 UINT32 OperationSet)
811 XA2SourceImpl *This = impl_from_IXAudio27SourceVoice(iface);
812 return XA2SRC_SetVolume(&This->IXAudio2SourceVoice_iface, Volume,
813 OperationSet);
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,
835 pVolumes);
838 static HRESULT WINAPI XA27SRC_SetOutputMatrix(IXAudio27SourceVoice *iface,
839 IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels,
840 UINT32 DestinationChannels, const float *pLevelMatrix,
841 UINT32 OperationSet)
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,
865 UINT32 OperationSet)
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,
872 UINT32 OperationSet)
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,
883 pBufferWMA);
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,
945 XA27SRC_SetVolume,
946 XA27SRC_GetVolume,
947 XA27SRC_SetChannelVolumes,
948 XA27SRC_GetChannelVolumes,
949 XA27SRC_SetOutputMatrix,
950 XA27SRC_GetOutputMatrix,
951 XA27SRC_DestroyVoice,
952 XA27SRC_Start,
953 XA27SRC_Stop,
954 XA27SRC_SubmitSourceBuffer,
955 XA27SRC_FlushSourceBuffers,
956 XA27SRC_Discontinuity,
957 XA27SRC_ExitLoop,
958 XA27SRC_GetState,
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);
976 return S_OK;
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);
984 return S_OK;
987 static HRESULT WINAPI XA2M_EnableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
988 UINT32 OperationSet)
990 IXAudio2Impl *This = impl_from_IXAudio2MasteringVoice(iface);
991 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
992 return S_OK;
995 static HRESULT WINAPI XA2M_DisableEffect(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
996 UINT32 OperationSet)
998 IXAudio2Impl *This = impl_from_IXAudio2MasteringVoice(iface);
999 TRACE("%p, %u, 0x%x\n", This, EffectIndex, OperationSet);
1000 return S_OK;
1003 static void WINAPI XA2M_GetEffectState(IXAudio2MasteringVoice *iface, UINT32 EffectIndex,
1004 BOOL *pEnabled)
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);
1017 return S_OK;
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);
1026 return S_OK;
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);
1034 return S_OK;
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);
1050 return S_OK;
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);
1066 return S_OK;
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);
1080 return S_OK;
1083 static void WINAPI XA2M_GetChannelVolumes(IXAudio2MasteringVoice *iface, UINT32 Channels,
1084 float *pVolumes)
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);
1098 return S_OK;
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);
1118 if(!This->aclient){
1119 LeaveCriticalSection(&This->lock);
1120 return;
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,
1150 XA2M_EnableEffect,
1151 XA2M_DisableEffect,
1152 XA2M_GetEffectState,
1153 XA2M_SetEffectParameters,
1154 XA2M_GetEffectParameters,
1155 XA2M_SetFilterParameters,
1156 XA2M_GetFilterParameters,
1157 XA2M_SetOutputFilterParameters,
1158 XA2M_GetOutputFilterParameters,
1159 XA2M_SetVolume,
1160 XA2M_GetVolume,
1161 XA2M_SetChannelVolumes,
1162 XA2M_GetChannelVolumes,
1163 XA2M_SetOutputMatrix,
1164 XA2M_GetOutputMatrix,
1165 XA2M_DestroyVoice,
1166 XA2M_GetChannelMask
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);
1181 return S_OK;
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);
1189 return S_OK;
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);
1197 return S_OK;
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);
1205 return S_OK;
1208 static void WINAPI XA2SUB_GetEffectState(IXAudio2SubmixVoice *iface, UINT32 EffectIndex,
1209 BOOL *pEnabled)
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);
1222 return S_OK;
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);
1231 return S_OK;
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);
1239 return S_OK;
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);
1255 return S_OK;
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);
1271 return S_OK;
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);
1285 return S_OK;
1288 static void WINAPI XA2SUB_GetChannelVolumes(IXAudio2SubmixVoice *iface, UINT32 Channels,
1289 float *pVolumes)
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);
1303 return S_OK;
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,
1341 XA2SUB_SetVolume,
1342 XA2SUB_GetVolume,
1343 XA2SUB_SetChannelVolumes,
1344 XA2SUB_GetChannelVolumes,
1345 XA2SUB_SetOutputMatrix,
1346 XA2SUB_GetOutputMatrix,
1347 XA2SUB_DestroyVoice
1350 static HRESULT WINAPI IXAudio2Impl_QueryInterface(IXAudio2 *iface, REFIID riid,
1351 void **ppvObject)
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;
1362 else
1363 *ppvObject = NULL;
1365 if(*ppvObject){
1366 IUnknown_AddRef((IUnknown*)*ppvObject);
1367 return S_OK;
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);
1380 return 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);
1390 if (!ref) {
1391 int i;
1392 XA2SourceImpl *src, *src2;
1393 XA2SubmixImpl *sub, *sub2;
1395 if(This->engine){
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);
1417 if(This->devenum)
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);
1430 return ref;
1433 static HRESULT WINAPI IXAudio2Impl_RegisterForCallbacks(IXAudio2 *iface,
1434 IXAudio2EngineCallback *pCallback)
1436 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1437 int i;
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);
1447 return S_OK;
1451 This->ncbs *= 2;
1452 This->cbs = HeapReAlloc(GetProcessHeap(), 0, This->cbs, This->ncbs * sizeof(*This->cbs));
1454 This->cbs[i] = pCallback;
1456 LeaveCriticalSection(&This->lock);
1458 return S_OK;
1461 static void WINAPI IXAudio2Impl_UnregisterForCallbacks(IXAudio2 *iface,
1462 IXAudio2EngineCallback *pCallback)
1464 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1465 int i;
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)
1473 break;
1476 for(; i < This->ncbs - 1 && This->cbs[i + 1]; ++i)
1477 This->cbs[i] = This->cbs[i + 1];
1479 if(i < This->ncbs)
1480 This->cbs[i] = NULL;
1482 LeaveCriticalSection(&This->lock);
1485 static WAVEFORMATEX *copy_waveformat(const WAVEFORMATEX *wfex)
1487 WAVEFORMATEX *pwfx;
1489 if(wfex->wFormatTag == WAVE_FORMAT_PCM){
1490 pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX));
1491 CopyMemory(pwfx, wfex, sizeof(PCMWAVEFORMAT));
1492 pwfx->cbSize = 0;
1493 }else{
1494 pwfx = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEX) + wfex->cbSize);
1495 CopyMemory(pwfx, wfex, sizeof(WAVEFORMATEX) + wfex->cbSize);
1498 return pwfx;
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);
1508 XA2SourceImpl *src;
1509 HRESULT hr;
1511 TRACE("(%p)->(%p, %p, 0x%x, %f, %p, %p, %p)\n", This, ppSourceVoice,
1512 pSourceFormat, flags, maxFrequencyRatio, pCallback, pSendList,
1513 pEffectChain);
1515 dump_fmt(pSourceFormat);
1517 EnterCriticalSection(&This->lock);
1519 LIST_FOR_EACH_ENTRY(src, &This->source_voices, XA2SourceImpl, entry){
1520 if(!src->in_use)
1521 break;
1524 if(&src->entry == &This->source_voices){
1525 src = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*src));
1526 if(!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");
1539 src->xa2 = This;
1542 src->in_use = TRUE;
1543 src->running = FALSE;
1545 LeaveCriticalSection(&This->lock);
1547 src->cb = pCallback;
1549 src->al_fmt = get_al_format(pSourceFormat);
1550 if(!src->al_fmt){
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);
1561 if(FAILED(hr)){
1562 src->in_use = FALSE;
1563 return hr;
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;
1573 else
1574 *ppSourceVoice = &src->IXAudio2SourceVoice_iface;
1576 TRACE("Created source voice: %p\n", src);
1578 return S_OK;
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);
1588 XA2SubmixImpl *sub;
1590 TRACE("(%p)->(%p, %u, %u, 0x%x, %u, %p, %p)\n", This, ppSubmixVoice,
1591 inputChannels, inputSampleRate, flags, processingStage, pSendList,
1592 pEffectChain);
1594 EnterCriticalSection(&This->lock);
1596 LIST_FOR_EACH_ENTRY(sub, &This->submix_voices, XA2SubmixImpl, entry){
1597 if(!sub->in_use)
1598 break;
1601 if(&sub->entry == &This->submix_voices){
1602 sub = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sub));
1603 if(!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");
1616 sub->in_use = TRUE;
1618 LeaveCriticalSection(&This->lock);
1620 *ppSubmixVoice = &sub->IXAudio2SubmixVoice_iface;
1622 TRACE("Created submix voice: %p\n", sub);
1624 return S_OK;
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){
1633 case 8:
1634 return ALC_UNSIGNED_BYTE_SOFT;
1635 case 16:
1636 return ALC_SHORT_SOFT;
1637 case 32:
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;
1646 return 0;
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);
1656 IMMDevice *dev;
1657 HRESULT hr;
1658 WAVEFORMATEX *fmt;
1659 ALCint attrs[7];
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);
1666 if(flags != 0)
1667 WARN("Unknown flags set: 0x%x\n", flags);
1669 if(pEffectChain)
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 */
1675 if(This->aclient){
1676 LeaveCriticalSection(&This->lock);
1677 return XAUDIO2_E_INVALID_CALL;
1680 if(!deviceId){
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);
1689 if(FAILED(hr)){
1690 WARN("GetDevice failed: %08x\n", hr);
1691 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1692 goto exit;
1695 hr = IMMDevice_Activate(dev, &IID_IAudioClient,
1696 CLSCTX_INPROC_SERVER, NULL, (void**)&This->aclient);
1697 if(FAILED(hr)){
1698 WARN("Activate(IAudioClient) failed: %08x\n", hr);
1699 IMMDevice_Release(dev);
1700 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1701 goto exit;
1704 IMMDevice_Release(dev);
1706 hr = IAudioClient_GetMixFormat(This->aclient, &fmt);
1707 if(FAILED(hr)){
1708 WARN("GetMixFormat failed: %08x\n", hr);
1709 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1710 goto exit;
1713 if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
1714 FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
1715 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1716 goto exit;
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);
1731 CoTaskMemFree(fmt);
1732 fmt = NULL;
1734 hr = IAudioClient_IsFormatSupported(This->aclient,
1735 AUDCLNT_SHAREMODE_SHARED, &This->fmt.Format, &fmt);
1736 if(hr == S_FALSE){
1737 if(sizeof(WAVEFORMATEX) + fmt->cbSize > sizeof(WAVEFORMATEXTENSIBLE)){
1738 FIXME("Mix format doesn't fit into WAVEFORMATEXTENSIBLE!\n");
1739 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1740 goto exit;
1742 memcpy(&This->fmt, fmt, sizeof(WAVEFORMATEX) + fmt->cbSize);
1745 CoTaskMemFree(fmt);
1747 hr = IAudioClient_Initialize(This->aclient, AUDCLNT_SHAREMODE_SHARED,
1748 AUDCLNT_STREAMFLAGS_EVENTCALLBACK, inputSampleRate /* 1s buffer */,
1749 0, &This->fmt.Format, NULL);
1750 if(FAILED(hr)){
1751 WARN("Initialize failed: %08x\n", hr);
1752 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1753 goto exit;
1756 hr = IAudioClient_GetDevicePeriod(This->aclient, &period, NULL);
1757 if(FAILED(hr)){
1758 WARN("GetDevicePeriod failed: %08x\n", hr);
1759 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1760 goto exit;
1763 This->period_frames = MulDiv(period, inputSampleRate, 10000000);
1765 hr = IAudioClient_SetEventHandle(This->aclient, This->mmevt);
1766 if(FAILED(hr)){
1767 WARN("Initialize failed: %08x\n", hr);
1768 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1769 goto exit;
1772 hr = IAudioClient_GetService(This->aclient, &IID_IAudioRenderClient,
1773 (void**)&This->render);
1774 if(FAILED(hr)){
1775 WARN("GetService(IAudioRenderClient) failed: %08x\n", hr);
1776 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1777 goto exit;
1780 /* setup openal context */
1781 attrs[0] = ALC_FORMAT_CHANNELS_SOFT;
1782 switch(inputChannels){
1783 case 1:
1784 attrs[1] = ALC_MONO_SOFT;
1785 break;
1786 case 2:
1787 attrs[1] = ALC_STEREO_SOFT;
1788 break;
1789 case 4:
1790 attrs[1] = ALC_QUAD_SOFT;
1791 break;
1792 case 6:
1793 attrs[1] = ALC_5POINT1_SOFT;
1794 break;
1795 case 7:
1796 attrs[1] = ALC_6POINT1_SOFT;
1797 break;
1798 case 8:
1799 attrs[1] = ALC_7POINT1_SOFT;
1800 break;
1801 default:
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);
1810 attrs[6] = 0;
1812 if(!attrs[5]){
1813 WARN("OpenAL can't output samples in this format\n");
1814 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1815 goto exit;
1818 This->al_device = palcLoopbackOpenDeviceSOFT(NULL);
1819 if(!This->al_device){
1820 WARN("alcLoopbackOpenDeviceSOFT failed\n");
1821 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1822 goto exit;
1825 This->al_ctx = alcCreateContext(This->al_device, attrs);
1826 if(!This->al_ctx){
1827 WARN("alcCreateContext failed\n");
1828 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1829 goto exit;
1832 if(alcMakeContextCurrent(This->al_ctx) == ALC_FALSE){
1833 WARN("alcMakeContextCurrent failed\n");
1834 hr = XAUDIO2_E_DEVICE_INVALIDATED;
1835 goto exit;
1838 IAudioClient_Start(This->aclient);
1840 *ppMasteringVoice = &This->IXAudio2MasteringVoice_iface;
1842 exit:
1843 if(FAILED(hr)){
1844 if(This->render){
1845 IAudioRenderClient_Release(This->render);
1846 This->render = NULL;
1848 if(This->aclient){
1849 IAudioClient_Release(This->aclient);
1850 This->aclient = NULL;
1852 if(This->al_ctx){
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);
1864 return hr;
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;
1877 if(!This->engine)
1878 This->engine = CreateThread(NULL, 0, engine_threadproc, This, 0, NULL);
1880 return S_OK;
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);
1899 return E_NOTIMPL;
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,
1914 void *pReserved)
1916 IXAudio2Impl *This = impl_from_IXAudio2(iface);
1918 FIXME("(%p)->(%p, %p): stub!\n", This, pDebugConfiguration, pReserved);
1921 /* XAudio2 2.8 */
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,
1940 void **ppvObject)
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;
1966 return S_OK;
1969 static HRESULT WINAPI XA27_GetDeviceDetails(IXAudio27 *iface, UINT32 index,
1970 XAUDIO2_DEVICE_DETAILS *pDeviceDetails)
1972 IXAudio2Impl *This = impl_from_IXAudio27(iface);
1973 HRESULT hr;
1974 IMMDevice *dev;
1975 IAudioClient *client;
1976 IPropertyStore *ps;
1977 WAVEFORMATEX *wfx;
1978 PROPVARIANT var;
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);
1986 if(FAILED(hr)){
1987 WARN("GetDevice failed: %08x\n", hr);
1988 return hr;
1991 hr = IMMDevice_Activate(dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
1992 NULL, (void**)&client);
1993 if(FAILED(hr)){
1994 WARN("Activate failed: %08x\n", hr);
1995 IMMDevice_Release(dev);
1996 return hr;
1999 hr = IMMDevice_OpenPropertyStore(dev, STGM_READ, &ps);
2000 if(FAILED(hr)){
2001 WARN("OpenPropertyStore failed: %08x\n", hr);
2002 IAudioClient_Release(client);
2003 IMMDevice_Release(dev);
2004 return hr;
2007 PropVariantInit(&var);
2009 hr = IPropertyStore_GetValue(ps, (PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &var);
2010 if(FAILED(hr)){
2011 WARN("GetValue failed: %08x\n", hr);
2012 goto done;
2015 lstrcpynW(pDeviceDetails->DisplayName, var.u.pwszVal, sizeof(pDeviceDetails->DisplayName)/sizeof(WCHAR));
2017 PropVariantClear(&var);
2019 hr = IAudioClient_GetMixFormat(client, &wfx);
2020 if(FAILED(hr)){
2021 WARN("GetMixFormat failed: %08x\n", hr);
2022 goto done;
2025 lstrcpyW(pDeviceDetails->DeviceID, This->devids[index]);
2027 if(index == 0)
2028 pDeviceDetails->Role = GlobalDefaultDevice;
2029 else
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");
2034 CoTaskMemFree(wfx);
2035 hr = E_FAIL;
2036 goto done;
2038 memcpy(&pDeviceDetails->OutputFormat, wfx, sizeof(WAVEFORMATEX) + wfx->cbSize);
2040 CoTaskMemFree(wfx);
2042 done:
2043 IPropertyStore_Release(ps);
2044 IAudioClient_Release(client);
2045 IMMDevice_Release(dev);
2047 return hr;
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);
2055 return S_OK;
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,
2081 pEffectChain);
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,
2093 pEffectChain);
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,
2105 pEffectChain);
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,
2142 void *pReserved)
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,
2151 XA27_AddRef,
2152 XA27_Release,
2153 XA27_GetDeviceCount,
2154 XA27_GetDeviceDetails,
2155 XA27_Initialize,
2156 XA27_RegisterForCallbacks,
2157 XA27_UnregisterForCallbacks,
2158 XA27_CreateSourceVoice,
2159 XA27_CreateSubmixVoice,
2160 XA27_CreateMasteringVoice,
2161 XA27_StartEngine,
2162 XA27_StopEngine,
2163 XA27_CommitChanges,
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);
2174 *ppobj = iface;
2175 return S_OK;
2178 *ppobj = NULL;
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)
2185 return 2;
2188 static ULONG WINAPI XAudio2CF_Release(IClassFactory *iface)
2190 return 1;
2193 static HRESULT initialize_mmdevices(IXAudio2Impl *This)
2195 IMMDeviceCollection *devcoll;
2196 UINT devcount;
2197 HRESULT hr;
2199 if(!This->devenum){
2200 hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
2201 CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&This->devenum);
2202 if(FAILED(hr))
2203 return hr;
2206 hr = IMMDeviceEnumerator_EnumAudioEndpoints(This->devenum, eRender,
2207 DEVICE_STATE_ACTIVE, &devcoll);
2208 if(FAILED(hr)){
2209 return hr;
2212 hr = IMMDeviceCollection_GetCount(devcoll, &devcount);
2213 if(FAILED(hr)){
2214 IMMDeviceCollection_Release(devcoll);
2215 return hr;
2218 if(devcount > 0){
2219 UINT i, count = 1;
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);
2229 if(SUCCEEDED(hr)){
2230 UINT idx;
2232 if(dev == def_dev)
2233 idx = 0;
2234 else{
2235 idx = count;
2236 ++count;
2239 hr = IMMDevice_GetId(dev, &This->devids[idx]);
2240 if(FAILED(hr)){
2241 WARN("GetId failed: %08x\n", hr);
2242 HeapFree(GetProcessHeap(), 0, This->devids);
2243 This->devids = NULL;
2244 IMMDevice_Release(dev);
2245 return hr;
2248 IMMDevice_Release(dev);
2249 }else{
2250 WARN("Item failed: %08x\n", hr);
2251 HeapFree(GetProcessHeap(), 0, This->devids);
2252 This->devids = NULL;
2253 IMMDeviceCollection_Release(devcoll);
2254 return hr;
2259 IMMDeviceCollection_Release(devcoll);
2261 This->ndevs = devcount;
2263 return S_OK;
2266 static HRESULT WINAPI XAudio2CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2267 REFIID riid, void **ppobj)
2269 HRESULT hr;
2270 IXAudio2Impl *object;
2272 TRACE("(static)->(%p,%s,%p)\n", pOuter, debugstr_guid(riid), ppobj);
2274 *ppobj = NULL;
2276 if(pOuter)
2277 return CLASS_E_NOAGGREGATION;
2279 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2280 if(!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;
2289 else
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);
2300 if(FAILED(hr)){
2301 HeapFree(GetProcessHeap(), 0, object);
2302 return hr;
2305 hr = initialize_mmdevices(object);
2306 if(FAILED(hr)){
2307 IUnknown_Release((IUnknown*)*ppobj);
2308 return hr;
2311 object->ncbs = 4;
2312 object->cbs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->ncbs * sizeof(*object->cbs));
2314 IXAudio2_StartEngine(&object->IXAudio2_iface);
2316 return hr;
2319 static HRESULT WINAPI XAudio2CF_LockServer(IClassFactory *iface, BOOL dolock)
2321 FIXME("(static)->(%d): stub!\n", dolock);
2322 return S_OK;
2325 static const IClassFactoryVtbl XAudio2CF_Vtbl =
2327 XAudio2CF_QueryInterface,
2328 XAudio2CF_AddRef,
2329 XAudio2CF_Release,
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");
2359 return FALSE;
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)
2383 int i;
2384 ALint processed;
2385 ALint bufpos;
2387 alGetSourcei(src->al_src, AL_BUFFERS_PROCESSED, &processed);
2389 if(processed > 0){
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){
2398 ALint bufsize;
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;
2408 src->first_buf++;
2409 src->first_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
2410 src->nbufs--;
2412 TRACE("%p: done with buffer %u\n", src, old_buf);
2414 if(src->cb){
2415 IXAudio2VoiceCallback_OnBufferEnd(src->cb,
2416 src->buffers[old_buf].xa2buffer.pContext);
2418 if(src->nbufs > 0)
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 */
2441 src->cur_buf++;
2442 src->cur_buf %= XAUDIO2_MAX_QUEUED_BUFFERS;
2447 static void do_engine_tick(IXAudio2Impl *This)
2449 BYTE *buf;
2450 XA2SourceImpl *src;
2451 HRESULT hr;
2452 UINT32 nframes, i, pad;
2454 /* maintain up to 3 periods in mmdevapi */
2455 hr = IAudioClient_GetCurrentPadding(This->aclient, &pad);
2456 if(FAILED(hr)){
2457 WARN("GetCurrentPadding failed: 0x%x\n", hr);
2458 return;
2461 nframes = This->period_frames * 3 - pad;
2462 TRACE("going to render %u frames\n", nframes);
2464 if(!nframes)
2465 return;
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){
2471 ALint st = 0;
2473 EnterCriticalSection(&src->lock);
2475 if(!src->in_use || !src->running){
2476 LeaveCriticalSection(&src->lock);
2477 continue;
2480 if(src->cb)
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);
2490 if(src->cb)
2491 IXAudio2VoiceCallback_OnVoiceProcessingPassEnd(src->cb);
2493 LeaveCriticalSection(&src->lock);
2496 hr = IAudioRenderClient_GetBuffer(This->render, nframes, &buf);
2497 if(FAILED(hr))
2498 WARN("GetBuffer failed: %08x\n", hr);
2500 palcRenderSamplesSOFT(This->al_device, buf, nframes);
2502 hr = IAudioRenderClient_ReleaseBuffer(This->render, nframes, 0);
2503 if(FAILED(hr))
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;
2513 while(1){
2514 WaitForSingleObject(This->mmevt, INFINITE);
2516 if(This->stop_engine)
2517 break;
2519 if(!This->running)
2520 continue;
2522 EnterCriticalSection(&This->lock);
2524 do_engine_tick(This);
2526 LeaveCriticalSection(&This->lock);
2528 return 0;