1 #include "xaudio2.h"
2 #include "XAPO.h"
3
4 #include <FAPOBase.h>
5
6 ///////////////////////////////////////////////////////////////////////////////
7 //
8 // IXAudio2VoiceCallback
9 //
10
11 struct FAudioVoiceCppCallback
12 {
13 FAudioVoiceCallback callbacks;
14 IXAudio2VoiceCallback *com;
15 };
16
OnBufferEnd(FAudioVoiceCallback * callback,void * pBufferContext)17 static void FAUDIOCALL OnBufferEnd(FAudioVoiceCallback *callback, void *pBufferContext)
18 {
19 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnBufferEnd(pBufferContext);
20 }
21
OnBufferStart(FAudioVoiceCallback * callback,void * pBufferContext)22 static void FAUDIOCALL OnBufferStart(FAudioVoiceCallback *callback, void *pBufferContext)
23 {
24 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnBufferStart(pBufferContext);
25 }
26
OnLoopEnd(FAudioVoiceCallback * callback,void * pBufferContext)27 static void FAUDIOCALL OnLoopEnd(FAudioVoiceCallback *callback, void *pBufferContext)
28 {
29 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnLoopEnd(pBufferContext);
30 }
31
OnStreamEnd(FAudioVoiceCallback * callback)32 static void FAUDIOCALL OnStreamEnd(FAudioVoiceCallback *callback)
33 {
34 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnStreamEnd();
35 }
36
OnVoiceError(FAudioVoiceCallback * callback,void * pBufferContext,uint32_t Error)37 static void FAUDIOCALL OnVoiceError(
38 FAudioVoiceCallback *callback,
39 void *pBufferContext,
40 uint32_t Error
41 ) {
42 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceError(pBufferContext, Error);
43 }
44
OnVoiceProcessingPassEnd(FAudioVoiceCallback * callback)45 static void FAUDIOCALL OnVoiceProcessingPassEnd(FAudioVoiceCallback *callback)
46 {
47 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassEnd();
48 }
49
OnVoiceProcessingPassStart(FAudioVoiceCallback * callback,uint32_t BytesRequired)50 static void FAUDIOCALL OnVoiceProcessingPassStart(
51 FAudioVoiceCallback *callback,
52 uint32_t BytesRequired
53 ) {
54 #if XAUDIO2_VERSION >= 1
55 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassStart(
56 BytesRequired);
57 #else
58 reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassStart();
59 #endif // XAUDIO2_VERSION >= 1
60 }
61
wrap_voice_callback(IXAudio2VoiceCallback * com_interface)62 FAudioVoiceCppCallback *wrap_voice_callback(IXAudio2VoiceCallback *com_interface)
63 {
64 if (com_interface == NULL)
65 {
66 return NULL;
67 }
68
69 FAudioVoiceCppCallback *cb = new FAudioVoiceCppCallback();
70 cb->callbacks.OnBufferEnd = OnBufferEnd;
71 cb->callbacks.OnBufferStart = OnBufferStart;
72 cb->callbacks.OnLoopEnd = OnLoopEnd;
73 cb->callbacks.OnStreamEnd = OnStreamEnd;
74 cb->callbacks.OnVoiceError = OnVoiceError;
75 cb->callbacks.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd;
76 cb->callbacks.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart;
77 cb->com = com_interface;
78
79 return cb;
80 }
81
82 ///////////////////////////////////////////////////////////////////////////////
83 //
84 // IXAudio2EngineCallback
85 //
86
87 struct FAudioCppEngineCallback
88 {
89 FAudioEngineCallback callbacks;
90 IXAudio2EngineCallback *com;
91
92 FAudioCppEngineCallback *next;
93 };
94
OnCriticalError(FAudioEngineCallback * callback,uint32_t Error)95 static void FAUDIOCALL OnCriticalError(FAudioEngineCallback *callback, uint32_t Error)
96 {
97 reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnCriticalError(Error);
98 }
99
OnProcessingPassEnd(FAudioEngineCallback * callback)100 static void FAUDIOCALL OnProcessingPassEnd(FAudioEngineCallback *callback)
101 {
102 reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnProcessingPassEnd();
103 }
104
OnProcessingPassStart(FAudioEngineCallback * callback)105 static void FAUDIOCALL OnProcessingPassStart(FAudioEngineCallback *callback)
106 {
107 reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnProcessingPassStart();
108 }
109
wrap_engine_callback(IXAudio2EngineCallback * com_interface)110 static FAudioCppEngineCallback *wrap_engine_callback(IXAudio2EngineCallback *com_interface)
111 {
112 if (com_interface == NULL)
113 {
114 return NULL;
115 }
116
117 FAudioCppEngineCallback *cb = new FAudioCppEngineCallback();
118 cb->callbacks.OnCriticalError = OnCriticalError;
119 cb->callbacks.OnProcessingPassEnd = OnProcessingPassEnd;
120 cb->callbacks.OnProcessingPassStart = OnProcessingPassStart;
121 cb->com = com_interface;
122 cb->next = NULL;
123
124 return cb;
125 }
126
find_and_remove_engine_callback(FAudioCppEngineCallback * list,IXAudio2EngineCallback * com)127 static FAudioCppEngineCallback *find_and_remove_engine_callback(
128 FAudioCppEngineCallback *list,
129 IXAudio2EngineCallback *com
130 ) {
131 FAudioCppEngineCallback *last = list;
132
133 for (FAudioCppEngineCallback *it = list->next; it != NULL; it = it->next)
134 {
135 if (it->com == com)
136 {
137 last->next = it->next;
138 return it;
139 }
140
141 last = it;
142 }
143
144 return NULL;
145 }
146
147 ///////////////////////////////////////////////////////////////////////////////
148 //
149 // XAUDIO2_VOICE_SENDS / XAUDIO2_SEND_DESCRIPTOR => FAudio
150 //
151
unwrap_voice_sends(const XAUDIO2_VOICE_SENDS * x_sends)152 static FAudioVoiceSends *unwrap_voice_sends(const XAUDIO2_VOICE_SENDS *x_sends)
153 {
154 if (x_sends == NULL)
155 {
156 return NULL;
157 }
158
159 FAudioVoiceSends *f_sends = new FAudioVoiceSends;
160 f_sends->SendCount = x_sends->SendCount;
161 f_sends->pSends = new FAudioSendDescriptor[f_sends->SendCount];
162
163 for (uint32_t i = 0; i < f_sends->SendCount; ++i)
164 {
165 #if XAUDIO2_VERSION >= 4
166 f_sends->pSends[i].Flags = x_sends->pSends[i].Flags;
167 f_sends->pSends[i].pOutputVoice = x_sends->pSends[i].pOutputVoice->faudio_voice;
168 #else
169 f_sends->pSends[i].Flags = 0;
170 f_sends->pSends[i].pOutputVoice = x_sends->pSends[i]->faudio_voice;
171 #endif // XAUDIO2_VERSION >= 4
172 }
173
174 return f_sends;
175 }
176
free_voice_sends(FAudioVoiceSends * f_sends)177 static void free_voice_sends(FAudioVoiceSends *f_sends)
178 {
179 if (f_sends != NULL)
180 {
181 delete[] f_sends->pSends;
182 delete f_sends;
183 }
184 }
185
186 ///////////////////////////////////////////////////////////////////////////////
187 //
188 // XAUDIO2_EFFECT_CHAIN / XAUDIO2_EFFECT_DESCRIPTOR => FAudio
189 //
190
191 struct FAPOCppBase
192 {
193 FAPO fapo;
194 IXAPO *xapo;
195 IXAPOParameters *xapo_params;
196 LONG refcount;
197 };
198
AddRef(void * fapo)199 static int32_t FAPOCALL AddRef(void *fapo)
200 {
201 FAPOCppBase *base = reinterpret_cast<FAPOCppBase *>(fapo);
202 return ++base->refcount;
203 }
204
Release(void * fapo)205 static int32_t FAPOCALL Release(void *fapo)
206 {
207 FAPOCppBase *base = reinterpret_cast<FAPOCppBase *>(fapo);
208 IXAPO *xapo = base->xapo;
209 LONG ref = --base->refcount;
210 if (ref == 0)
211 {
212 xapo->Release();
213 if (base->xapo_params != NULL)
214 {
215 base->xapo_params->Release();
216 }
217 delete base;
218 }
219 return ref;
220 }
221
GetRegistrationProperties(void * fapo,FAPORegistrationProperties ** ppRegistrationProperties)222 static uint32_t FAPOCALL GetRegistrationProperties(
223 void *fapo,
224 FAPORegistrationProperties **ppRegistrationProperties)
225 {
226 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
227 return xapo->GetRegistrationProperties(ppRegistrationProperties);
228 }
229
IsInputFormatSupported(void * fapo,const FAudioWaveFormatEx * pOutputFormat,const FAudioWaveFormatEx * pRequestedInputFormat,FAudioWaveFormatEx ** ppSupportedInputFormat)230 static uint32_t FAPOCALL IsInputFormatSupported(
231 void *fapo,
232 const FAudioWaveFormatEx *pOutputFormat,
233 const FAudioWaveFormatEx *pRequestedInputFormat,
234 FAudioWaveFormatEx **ppSupportedInputFormat
235 ) {
236 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
237 return xapo->IsInputFormatSupported(
238 pOutputFormat,
239 pRequestedInputFormat,
240 ppSupportedInputFormat);
241 }
242
IsOutputFormatSupported(void * fapo,const FAudioWaveFormatEx * pInputFormat,const FAudioWaveFormatEx * pRequestedOutputFormat,FAudioWaveFormatEx ** ppSupportedOutputFormat)243 static uint32_t FAPOCALL IsOutputFormatSupported(
244 void *fapo,
245 const FAudioWaveFormatEx *pInputFormat,
246 const FAudioWaveFormatEx *pRequestedOutputFormat,
247 FAudioWaveFormatEx **ppSupportedOutputFormat
248 ) {
249 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
250 return xapo->IsOutputFormatSupported(
251 pInputFormat,
252 pRequestedOutputFormat,
253 ppSupportedOutputFormat);
254 }
255
Initialize(void * fapo,const void * pData,uint32_t DataByteSize)256 static uint32_t FAPOCALL Initialize(void *fapo, const void *pData, uint32_t DataByteSize)
257 {
258 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
259 return xapo->Initialize(pData, DataByteSize);
260 }
261
Reset(void * fapo)262 static void FAPOCALL Reset(void *fapo)
263 {
264 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
265 xapo->Reset();
266 }
267
LockForProcess(void * fapo,uint32_t InputLockedParameterCount,const FAPOLockForProcessBufferParameters * pInputLockedParameters,uint32_t OutputLockedParameterCount,const FAPOLockForProcessBufferParameters * pOutputLockedParameters)268 static uint32_t FAPOCALL LockForProcess(
269 void *fapo,
270 uint32_t InputLockedParameterCount,
271 const FAPOLockForProcessBufferParameters *pInputLockedParameters,
272 uint32_t OutputLockedParameterCount,
273 const FAPOLockForProcessBufferParameters *pOutputLockedParameters
274 ) {
275 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
276 return xapo->LockForProcess(
277 InputLockedParameterCount,
278 pInputLockedParameters,
279 OutputLockedParameterCount,
280 pOutputLockedParameters);
281 }
282
UnlockForProcess(void * fapo)283 static void FAPOCALL UnlockForProcess(void *fapo)
284 {
285 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
286 xapo->UnlockForProcess();
287 }
288
Process(void * fapo,uint32_t InputProcessParameterCount,const FAPOProcessBufferParameters * pInputProcessParameters,uint32_t OutputProcessParameterCount,FAPOProcessBufferParameters * pOutputProcessParameters,int32_t IsEnabled)289 static void FAPOCALL Process(
290 void *fapo,
291 uint32_t InputProcessParameterCount,
292 const FAPOProcessBufferParameters *pInputProcessParameters,
293 uint32_t OutputProcessParameterCount,
294 FAPOProcessBufferParameters *pOutputProcessParameters,
295 int32_t IsEnabled
296 ) {
297 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
298 xapo->Process(
299 InputProcessParameterCount,
300 pInputProcessParameters,
301 OutputProcessParameterCount,
302 pOutputProcessParameters,
303 IsEnabled);
304 }
305
CalcInputFrames(void * fapo,uint32_t OutputFrameCount)306 static uint32_t FAPOCALL CalcInputFrames(void *fapo, uint32_t OutputFrameCount)
307 {
308 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
309 return xapo->CalcInputFrames(OutputFrameCount);
310 }
311
CalcOutputFrames(void * fapo,uint32_t InputFrameCount)312 static uint32_t FAPOCALL CalcOutputFrames(void *fapo, uint32_t InputFrameCount)
313 {
314 IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo;
315 return xapo->CalcOutputFrames(InputFrameCount);
316 }
317
SetParameters(void * fapoParameters,const void * pParameters,uint32_t ParameterByteSize)318 static void FAPOCALL SetParameters(
319 void *fapoParameters,
320 const void *pParameters,
321 uint32_t ParameterByteSize
322 ) {
323 IXAPOParameters *xapo_params = reinterpret_cast<FAPOCppBase *>(fapoParameters)->xapo_params;
324 return xapo_params->SetParameters(pParameters, ParameterByteSize);
325 }
326
GetParameters(void * fapoParameters,void * pParameters,uint32_t ParameterByteSize)327 static void FAPOCALL GetParameters(void *fapoParameters, void *pParameters, uint32_t ParameterByteSize)
328 {
329 IXAPOParameters *xapo_params = reinterpret_cast<FAPOCppBase *>(fapoParameters)->xapo_params;
330 return xapo_params->GetParameters(pParameters, ParameterByteSize);
331 }
332
wrap_xapo_effect(IUnknown * xapo)333 static FAPO *wrap_xapo_effect(IUnknown *xapo)
334 {
335 if (xapo == NULL)
336 {
337 return NULL;
338 }
339
340 // FIXME: assumes that all effects are derived from CXAPOParametersBase
341 FAPOCppBase *f_effect = new FAPOCppBase;
342 f_effect->refcount = 1;
343 xapo->QueryInterface(IID_IXAPO, (void **)&f_effect->xapo);
344 xapo->QueryInterface(IID_IXAPOParameters, (void **)&f_effect->xapo_params);
345
346 f_effect->fapo.AddRef = AddRef;
347 f_effect->fapo.Release = Release;
348 f_effect->fapo.GetRegistrationProperties = GetRegistrationProperties;
349 f_effect->fapo.IsInputFormatSupported = IsInputFormatSupported;
350 f_effect->fapo.IsOutputFormatSupported = IsOutputFormatSupported;
351 f_effect->fapo.Initialize = Initialize;
352 f_effect->fapo.Reset = Reset;
353 f_effect->fapo.LockForProcess = LockForProcess;
354 f_effect->fapo.UnlockForProcess = UnlockForProcess;
355 f_effect->fapo.Process = Process;
356 f_effect->fapo.CalcInputFrames = CalcInputFrames;
357 f_effect->fapo.CalcOutputFrames = CalcOutputFrames;
358 f_effect->fapo.GetParameters = GetParameters;
359 f_effect->fapo.SetParameters = SetParameters;
360
361 return &f_effect->fapo;
362 }
363
wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN * x_chain)364 static FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *x_chain)
365 {
366 if (x_chain == NULL)
367 {
368 return NULL;
369 }
370
371 FAudioEffectChain *f_chain = new FAudioEffectChain;
372 f_chain->EffectCount = x_chain->EffectCount;
373 f_chain->pEffectDescriptors = new FAudioEffectDescriptor[f_chain->EffectCount];
374
375 for (uint32_t i = 0; i < f_chain->EffectCount; ++i)
376 {
377 f_chain->pEffectDescriptors[i].InitialState = x_chain->pEffectDescriptors[i].InitialState;
378 f_chain->pEffectDescriptors[i].OutputChannels =
379 x_chain->pEffectDescriptors[i].OutputChannels;
380 f_chain->pEffectDescriptors[i].pEffect =
381 wrap_xapo_effect(x_chain->pEffectDescriptors[i].pEffect);
382 }
383
384 return f_chain;
385 }
386
free_effect_chain(FAudioEffectChain * f_chain)387 static void free_effect_chain(FAudioEffectChain *f_chain)
388 {
389 if (f_chain != NULL)
390 {
391 delete[] f_chain->pEffectDescriptors;
392 delete f_chain;
393 }
394 }
395
396 ///////////////////////////////////////////////////////////////////////////////
397 //
398 // IXAudio2SourceVoice implementation
399 //
400
401 class XAudio2SourceVoiceImpl : public IXAudio2SourceVoice
402 {
403 public:
XAudio2SourceVoiceImpl(FAudio * faudio,const WAVEFORMATEX * pSourceFormat,UINT32 Flags,float MaxFrequencyRatio,IXAudio2VoiceCallback * pCallback,const XAUDIO2_VOICE_SENDS * pSendList,const XAUDIO2_EFFECT_CHAIN * pEffectChain)404 XAudio2SourceVoiceImpl(
405 FAudio *faudio,
406 const WAVEFORMATEX *pSourceFormat,
407 UINT32 Flags,
408 float MaxFrequencyRatio,
409 IXAudio2VoiceCallback *pCallback,
410 const XAUDIO2_VOICE_SENDS *pSendList,
411 const XAUDIO2_EFFECT_CHAIN *pEffectChain)
412 {
413 voice_callback = wrap_voice_callback(pCallback);
414 voice_sends = unwrap_voice_sends(pSendList);
415 effect_chain = wrap_effect_chain(pEffectChain);
416 FAudio_CreateSourceVoice(
417 faudio,
418 &faudio_voice,
419 pSourceFormat,
420 Flags,
421 MaxFrequencyRatio,
422 reinterpret_cast<FAudioVoiceCallback *>(voice_callback),
423 voice_sends,
424 effect_chain);
425 }
426
427 // IXAudio2Voice
GetVoiceDetails(XAUDIO2_VOICE_DETAILS * pVoiceDetails)428 COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails)
429 {
430 #if XAUDIO2_VERSION > 7
431 FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails);
432 #else
433 FAudioVoiceDetails fDetails;
434 FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails);
435 pVoiceDetails->CreationFlags = fDetails.CreationFlags;
436 pVoiceDetails->InputChannels = fDetails.InputChannels;
437 pVoiceDetails->InputSampleRate = fDetails.InputSampleRate;
438 #endif // XAUDIO2_VERSION <= 7
439 }
440
SetOutputVoices(const XAUDIO2_VOICE_SENDS * pSendList)441 COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList)
442 {
443 free_voice_sends(voice_sends);
444 voice_sends = unwrap_voice_sends(pSendList);
445 return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends);
446 }
447
SetEffectChain(const XAUDIO2_EFFECT_CHAIN * pEffectChain)448 COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
449 {
450 free_effect_chain(effect_chain);
451 effect_chain = wrap_effect_chain(pEffectChain);
452 return FAudioVoice_SetEffectChain(faudio_voice, effect_chain);
453 }
454
EnableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)455 COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
456 {
457 return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet);
458 }
459
DisableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)460 COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
461 {
462 return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet);
463 }
464
GetEffectState(UINT32 EffectIndex,BOOL * pEnabled)465 COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled)
466 {
467 FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled);
468 }
469
SetEffectParameters(UINT32 EffectIndex,const void * pParameters,UINT32 ParametersByteSize,UINT32 OperationSet=FAUDIO_COMMIT_NOW)470 COM_METHOD(HRESULT) SetEffectParameters(
471 UINT32 EffectIndex,
472 const void *pParameters,
473 UINT32 ParametersByteSize,
474 UINT32 OperationSet = FAUDIO_COMMIT_NOW
475 ) {
476 return FAudioVoice_SetEffectParameters(
477 faudio_voice,
478 EffectIndex,
479 pParameters,
480 ParametersByteSize,
481 OperationSet);
482 }
483
GetEffectParameters(UINT32 EffectIndex,void * pParameters,UINT32 ParametersByteSize)484 COM_METHOD(HRESULT) GetEffectParameters(
485 UINT32 EffectIndex,
486 void *pParameters,
487 UINT32 ParametersByteSize)
488 {
489 return FAudioVoice_GetEffectParameters(
490 faudio_voice,
491 EffectIndex,
492 pParameters,
493 ParametersByteSize);
494 }
495
SetFilterParameters(const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)496 COM_METHOD(HRESULT) SetFilterParameters(
497 const XAUDIO2_FILTER_PARAMETERS *pParameters,
498 UINT32 OperationSet = FAUDIO_COMMIT_NOW)
499 {
500 return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet);
501 }
502
GetFilterParameters(XAUDIO2_FILTER_PARAMETERS * pParameters)503 COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters)
504 {
505 FAudioVoice_GetFilterParameters(faudio_voice, pParameters);
506 }
507
508 #if XAUDIO2_VERSION >= 4
SetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)509 COM_METHOD(HRESULT) SetOutputFilterParameters(
510 IXAudio2Voice *pDestinationVoice,
511 const XAUDIO2_FILTER_PARAMETERS *pParameters,
512 UINT32 OperationSet = FAUDIO_COMMIT_NOW
513 ) {
514 return FAudioVoice_SetOutputFilterParameters(
515 faudio_voice,
516 ((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice,
517 pParameters,
518 OperationSet);
519 }
520
GetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,XAUDIO2_FILTER_PARAMETERS * pParameters)521 COM_METHOD(void) GetOutputFilterParameters(
522 IXAudio2Voice *pDestinationVoice,
523 XAUDIO2_FILTER_PARAMETERS *pParameters
524 ) {
525 FAudioVoice_GetOutputFilterParameters(
526 faudio_voice,
527 ((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice,
528 pParameters);
529 }
530 #endif // XAUDIO2_VERSION >= 4
531
SetVolume(float Volume,UINT32 OperationSet=FAUDIO_COMMIT_NOW)532 COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
533 {
534 return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet);
535 }
536
GetVolume(float * pVolume)537 COM_METHOD(void) GetVolume(float *pVolume)
538 {
539 FAudioVoice_GetVolume(faudio_voice, pVolume);
540 }
541
SetChannelVolumes(UINT32 Channels,const float * pVolumes,UINT32 OperationSet=FAUDIO_COMMIT_NOW)542 COM_METHOD(HRESULT) SetChannelVolumes(
543 UINT32 Channels,
544 const float *pVolumes,
545 UINT32 OperationSet = FAUDIO_COMMIT_NOW
546 ) {
547 return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet);
548 }
549
GetChannelVolumes(UINT32 Channels,float * pVolumes)550 COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes)
551 {
552 FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes);
553 }
554
SetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,const float * pLevelMatrix,UINT32 OperationSet=FAUDIO_COMMIT_NOW)555 COM_METHOD(HRESULT) SetOutputMatrix(
556 IXAudio2Voice *pDestinationVoice,
557 UINT32 SourceChannels,
558 UINT32 DestinationChannels,
559 const float *pLevelMatrix,
560 UINT32 OperationSet = FAUDIO_COMMIT_NOW
561 ) {
562 FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL;
563 return FAudioVoice_SetOutputMatrix(
564 faudio_voice, dest, SourceChannels, DestinationChannels, pLevelMatrix, OperationSet);
565 }
566
567 #if XAUDIO2_VERSION >= 1
GetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,float * pLevelMatrix)568 COM_METHOD(void) GetOutputMatrix(
569 #else
570 COM_METHOD(HRESULT) GetOutputMatrix(
571 #endif
572 IXAudio2Voice *pDestinationVoice,
573 UINT32 SourceChannels,
574 UINT32 DestinationChannels,
575 float *pLevelMatrix
576 ) {
577 FAudioVoice_GetOutputMatrix(
578 faudio_voice,
579 pDestinationVoice->faudio_voice,
580 SourceChannels,
581 DestinationChannels,
582 pLevelMatrix);
583 #if XAUDIO2_VERSION < 1
584 return S_OK;
585 #endif // XAUDIO2_VERSION < 1
586 }
587
DestroyVoice()588 COM_METHOD(void) DestroyVoice()
589 {
590 FAudioVoice_DestroyVoice(faudio_voice);
591 // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS
592 if (voice_callback)
593 {
594 delete voice_callback;
595 }
596 free_voice_sends(voice_sends);
597 free_effect_chain(effect_chain);
598 delete this;
599 }
600
601 // IXAudio2SourceVoice
Start(UINT32 Flags=0,UINT32 OperationSet=FAUDIO_COMMIT_NOW)602 COM_METHOD(HRESULT) Start(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
603 {
604 return FAudioSourceVoice_Start(faudio_voice, Flags, OperationSet);
605 }
606
Stop(UINT32 Flags=0,UINT32 OperationSet=FAUDIO_COMMIT_NOW)607 COM_METHOD(HRESULT) Stop(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
608 {
609 return FAudioSourceVoice_Stop(faudio_voice, Flags, OperationSet);
610 }
611
SubmitSourceBuffer(const XAUDIO2_BUFFER * pBuffer,const XAUDIO2_BUFFER_WMA * pBufferWMA=NULL)612 COM_METHOD(HRESULT) SubmitSourceBuffer(
613 const XAUDIO2_BUFFER *pBuffer,
614 const XAUDIO2_BUFFER_WMA *pBufferWMA = NULL)
615 {
616 return FAudioSourceVoice_SubmitSourceBuffer(faudio_voice, pBuffer, pBufferWMA);
617 }
618
FlushSourceBuffers()619 COM_METHOD(HRESULT) FlushSourceBuffers()
620 {
621 return FAudioSourceVoice_FlushSourceBuffers(faudio_voice);
622 }
623
Discontinuity()624 COM_METHOD(HRESULT) Discontinuity()
625 {
626 return FAudioSourceVoice_Discontinuity(faudio_voice);
627 }
628
ExitLoop(UINT32 OperationSet=FAUDIO_COMMIT_NOW)629 COM_METHOD(HRESULT) ExitLoop(UINT32 OperationSet = FAUDIO_COMMIT_NOW)
630 {
631 return FAudioSourceVoice_ExitLoop(faudio_voice, OperationSet);
632 }
633
634 #if (XAUDIO2_VERSION <= 7)
GetState(XAUDIO2_VOICE_STATE * pVoiceState)635 COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState)
636 #else
637 COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags = 0)
638 #endif
639 {
640 #if (XAUDIO2_VERSION <= 7)
641 FAudioSourceVoice_GetState(faudio_voice, pVoiceState, 0);
642 #else
643 FAudioSourceVoice_GetState(faudio_voice, pVoiceState, Flags);
644 #endif
645 }
646
SetFrequencyRatio(float Ratio,UINT32 OperationSet=FAUDIO_COMMIT_NOW)647 COM_METHOD(HRESULT) SetFrequencyRatio(float Ratio, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
648 {
649 return FAudioSourceVoice_SetFrequencyRatio(faudio_voice, Ratio, OperationSet);
650 }
651
GetFrequencyRatio(float * pRatio)652 COM_METHOD(void) GetFrequencyRatio(float *pRatio)
653 {
654 FAudioSourceVoice_GetFrequencyRatio(faudio_voice, pRatio);
655 }
656
657 #if XAUDIO2_VERSION >= 4
SetSourceSampleRate(UINT32 NewSourceSampleRate)658 COM_METHOD(HRESULT) SetSourceSampleRate(UINT32 NewSourceSampleRate)
659 {
660 return FAudioSourceVoice_SetSourceSampleRate(faudio_voice, NewSourceSampleRate);
661 }
662 #endif // XAUDIO2_VERSION >= 4
663
664 private:
665 FAudioVoiceCppCallback *voice_callback;
666 FAudioVoiceSends *voice_sends;
667 FAudioEffectChain *effect_chain;
668 };
669
670 ///////////////////////////////////////////////////////////////////////////////
671 //
672 // IXAudio2SubmixVoice implementation
673 //
674
675 class XAudio2SubmixVoiceImpl : public IXAudio2SubmixVoice
676 {
677 public:
XAudio2SubmixVoiceImpl(FAudio * faudio,UINT32 InputChannels,UINT32 InputSampleRate,UINT32 Flags,UINT32 ProcessingStage,const XAUDIO2_VOICE_SENDS * pSendList,const XAUDIO2_EFFECT_CHAIN * pEffectChain)678 XAudio2SubmixVoiceImpl(
679 FAudio *faudio,
680 UINT32 InputChannels,
681 UINT32 InputSampleRate,
682 UINT32 Flags,
683 UINT32 ProcessingStage,
684 const XAUDIO2_VOICE_SENDS *pSendList,
685 const XAUDIO2_EFFECT_CHAIN *pEffectChain
686 ) {
687 voice_sends = unwrap_voice_sends(pSendList);
688 effect_chain = wrap_effect_chain(pEffectChain);
689 FAudio_CreateSubmixVoice(
690 faudio,
691 &faudio_voice,
692 InputChannels,
693 InputSampleRate,
694 Flags,
695 ProcessingStage,
696 voice_sends,
697 effect_chain);
698 }
699
700 // IXAudio2Voice
GetVoiceDetails(XAUDIO2_VOICE_DETAILS * pVoiceDetails)701 COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails)
702 {
703 #if XAUDIO2_VERSION > 7
704 FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails);
705 #else
706 FAudioVoiceDetails fDetails;
707 FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails);
708 pVoiceDetails->CreationFlags = fDetails.CreationFlags;
709 pVoiceDetails->InputChannels = fDetails.InputChannels;
710 pVoiceDetails->InputSampleRate = fDetails.InputSampleRate;
711 #endif // XAUDIO2_VERSION <= 7
712 }
713
SetOutputVoices(const XAUDIO2_VOICE_SENDS * pSendList)714 COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList)
715 {
716 free_voice_sends(voice_sends);
717 voice_sends = unwrap_voice_sends(pSendList);
718 return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends);
719 }
720
SetEffectChain(const XAUDIO2_EFFECT_CHAIN * pEffectChain)721 COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
722 {
723 free_effect_chain(effect_chain);
724 effect_chain = wrap_effect_chain(pEffectChain);
725 return FAudioVoice_SetEffectChain(faudio_voice, effect_chain);
726 }
727
EnableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)728 COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
729 {
730 return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet);
731 }
732
DisableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)733 COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
734 {
735 return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet);
736 }
737
GetEffectState(UINT32 EffectIndex,BOOL * pEnabled)738 COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled)
739 {
740 FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled);
741 }
742
SetEffectParameters(UINT32 EffectIndex,const void * pParameters,UINT32 ParametersByteSize,UINT32 OperationSet=FAUDIO_COMMIT_NOW)743 COM_METHOD(HRESULT) SetEffectParameters(
744 UINT32 EffectIndex,
745 const void *pParameters,
746 UINT32 ParametersByteSize,
747 UINT32 OperationSet = FAUDIO_COMMIT_NOW
748 ) {
749 return FAudioVoice_SetEffectParameters(
750 faudio_voice,
751 EffectIndex,
752 pParameters,
753 ParametersByteSize,
754 OperationSet);
755 }
756
GetEffectParameters(UINT32 EffectIndex,void * pParameters,UINT32 ParametersByteSize)757 COM_METHOD(HRESULT) GetEffectParameters(
758 UINT32 EffectIndex,
759 void *pParameters,
760 UINT32 ParametersByteSize
761 ) {
762 return FAudioVoice_GetEffectParameters(
763 faudio_voice,
764 EffectIndex,
765 pParameters,
766 ParametersByteSize);
767 }
768
SetFilterParameters(const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)769 COM_METHOD(HRESULT) SetFilterParameters(
770 const XAUDIO2_FILTER_PARAMETERS *pParameters,
771 UINT32 OperationSet = FAUDIO_COMMIT_NOW
772 ) {
773 return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet);
774 }
775
GetFilterParameters(XAUDIO2_FILTER_PARAMETERS * pParameters)776 COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters)
777 {
778 FAudioVoice_GetFilterParameters(faudio_voice, pParameters);
779 }
780
781 #if XAUDIO2_VERSION >= 4
SetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)782 COM_METHOD(HRESULT) SetOutputFilterParameters(
783 IXAudio2Voice *pDestinationVoice,
784 const XAUDIO2_FILTER_PARAMETERS *pParameters,
785 UINT32 OperationSet = FAUDIO_COMMIT_NOW
786 ) {
787 return FAudioVoice_SetOutputFilterParameters(
788 faudio_voice,
789 ((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice,
790 pParameters,
791 OperationSet);
792 }
793
GetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,XAUDIO2_FILTER_PARAMETERS * pParameters)794 COM_METHOD(void) GetOutputFilterParameters(
795 IXAudio2Voice *pDestinationVoice,
796 XAUDIO2_FILTER_PARAMETERS *pParameters
797 ) {
798 FAudioVoice_GetOutputFilterParameters(
799 faudio_voice, ((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice, pParameters);
800 }
801 #endif // XAUDIO2_VERSION >= 4
802
SetVolume(float Volume,UINT32 OperationSet=FAUDIO_COMMIT_NOW)803 COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
804 {
805 return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet);
806 }
807
GetVolume(float * pVolume)808 COM_METHOD(void) GetVolume(float *pVolume)
809 {
810 FAudioVoice_GetVolume(faudio_voice, pVolume);
811 }
812
SetChannelVolumes(UINT32 Channels,const float * pVolumes,UINT32 OperationSet=FAUDIO_COMMIT_NOW)813 COM_METHOD(HRESULT) SetChannelVolumes(
814 UINT32 Channels,
815 const float *pVolumes,
816 UINT32 OperationSet = FAUDIO_COMMIT_NOW
817 ) {
818 return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet);
819 }
820
GetChannelVolumes(UINT32 Channels,float * pVolumes)821 COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes)
822 {
823 FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes);
824 }
825
SetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,const float * pLevelMatrix,UINT32 OperationSet=FAUDIO_COMMIT_NOW)826 COM_METHOD(HRESULT) SetOutputMatrix(
827 IXAudio2Voice *pDestinationVoice,
828 UINT32 SourceChannels,
829 UINT32 DestinationChannels,
830 const float *pLevelMatrix,
831 UINT32 OperationSet = FAUDIO_COMMIT_NOW
832 ) {
833 FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL;
834 return FAudioVoice_SetOutputMatrix(
835 faudio_voice,
836 dest,
837 SourceChannels,
838 DestinationChannels,
839 pLevelMatrix,
840 OperationSet);
841 }
842
843 #if XAUDIO2_VERSION >= 1
GetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,float * pLevelMatrix)844 COM_METHOD(void) GetOutputMatrix(
845 #else
846 COM_METHOD(HRESULT) GetOutputMatrix(
847 #endif
848 IXAudio2Voice *pDestinationVoice,
849 UINT32 SourceChannels,
850 UINT32 DestinationChannels,
851 float *pLevelMatrix
852 ) {
853 FAudioVoice_GetOutputMatrix(
854 faudio_voice,
855 pDestinationVoice->faudio_voice,
856 SourceChannels,
857 DestinationChannels,
858 pLevelMatrix);
859 #if XAUDIO2_VERSION < 1
860 return S_OK;
861 #endif // XAUDIO2_VERSION < 1
862 }
863
DestroyVoice()864 COM_METHOD(void) DestroyVoice()
865 {
866 FAudioVoice_DestroyVoice(faudio_voice);
867 // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS
868 free_voice_sends(voice_sends);
869 free_effect_chain(effect_chain);
870 delete this;
871 }
872
873 private:
874 FAudioVoiceSends *voice_sends;
875 FAudioEffectChain *effect_chain;
876 };
877
878 ///////////////////////////////////////////////////////////////////////////////
879 //
880 // IXAudio2MasteringVoice implementation
881 //
882
883 #if (XAUDIO2_VERSION >= 8)
884 uint32_t device_index_from_device_id(FAudio *faudio, LPCWSTR deviceId);
885 #endif // (XAUDIO2_VERSION >= 8)
886
887 class XAudio2MasteringVoiceImpl : public IXAudio2MasteringVoice
888 {
889 public:
890 #if (XAUDIO2_VERSION <= 7)
XAudio2MasteringVoiceImpl(FAudio * faudio,UINT32 InputChannels,UINT32 InputSampleRate,UINT32 Flags,UINT32 DeviceIndex,const XAUDIO2_EFFECT_CHAIN * pEffectChain)891 XAudio2MasteringVoiceImpl(
892 FAudio *faudio,
893 UINT32 InputChannels,
894 UINT32 InputSampleRate,
895 UINT32 Flags,
896 UINT32 DeviceIndex,
897 const XAUDIO2_EFFECT_CHAIN *pEffectChain
898 ) {
899 voice_sends = NULL;
900 effect_chain = wrap_effect_chain(pEffectChain);
901 FAudio_CreateMasteringVoice(
902 faudio,
903 &faudio_voice,
904 InputChannels,
905 InputSampleRate,
906 Flags,
907 DeviceIndex,
908 effect_chain);
909 }
910 #else
911 XAudio2MasteringVoiceImpl(
912 FAudio *faudio,
913 UINT32 InputChannels,
914 UINT32 InputSampleRate,
915 UINT32 Flags,
916 LPCWSTR szDeviceId,
917 const XAUDIO2_EFFECT_CHAIN *pEffectChain,
918 int StreamCategory
919 ) {
920 uint32_t device_index = 0;
921
922 if (szDeviceId != NULL)
923 {
924 device_index = device_index_from_device_id(faudio, szDeviceId);
925 }
926
927 voice_sends = NULL;
928 effect_chain = wrap_effect_chain(pEffectChain);
929 FAudio_CreateMasteringVoice(
930 faudio,
931 &faudio_voice,
932 InputChannels,
933 InputSampleRate,
934 Flags,
935 device_index,
936 effect_chain);
937 }
938 #endif
939
940 // IXAudio2Voice
GetVoiceDetails(XAUDIO2_VOICE_DETAILS * pVoiceDetails)941 COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails)
942 {
943 #if XAUDIO2_VERSION > 7
944 FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails);
945 #else
946 FAudioVoiceDetails fDetails;
947 FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails);
948 pVoiceDetails->CreationFlags = fDetails.CreationFlags;
949 pVoiceDetails->InputChannels = fDetails.InputChannels;
950 pVoiceDetails->InputSampleRate = fDetails.InputSampleRate;
951 #endif // XAUDIO2_VERSION <= 7
952 }
953
SetOutputVoices(const XAUDIO2_VOICE_SENDS * pSendList)954 COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList)
955 {
956 free_voice_sends(voice_sends);
957 voice_sends = unwrap_voice_sends(pSendList);
958 return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends);
959 }
960
SetEffectChain(const XAUDIO2_EFFECT_CHAIN * pEffectChain)961 COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain)
962 {
963 free_effect_chain(effect_chain);
964 effect_chain = wrap_effect_chain(pEffectChain);
965 return FAudioVoice_SetEffectChain(faudio_voice, effect_chain);
966 }
967
EnableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)968 COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
969 {
970 return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet);
971 }
972
DisableEffect(UINT32 EffectIndex,UINT32 OperationSet=FAUDIO_COMMIT_NOW)973 COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
974 {
975 return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet);
976 }
977
GetEffectState(UINT32 EffectIndex,BOOL * pEnabled)978 COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled)
979 {
980 FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled);
981 }
982
SetEffectParameters(UINT32 EffectIndex,const void * pParameters,UINT32 ParametersByteSize,UINT32 OperationSet=FAUDIO_COMMIT_NOW)983 COM_METHOD(HRESULT) SetEffectParameters(
984 UINT32 EffectIndex,
985 const void *pParameters,
986 UINT32 ParametersByteSize,
987 UINT32 OperationSet = FAUDIO_COMMIT_NOW
988 ) {
989 return FAudioVoice_SetEffectParameters(
990 faudio_voice,
991 EffectIndex,
992 pParameters,
993 ParametersByteSize,
994 OperationSet);
995 }
996
GetEffectParameters(UINT32 EffectIndex,void * pParameters,UINT32 ParametersByteSize)997 COM_METHOD(HRESULT) GetEffectParameters(
998 UINT32 EffectIndex,
999 void *pParameters,
1000 UINT32 ParametersByteSize
1001 ) {
1002 return FAudioVoice_GetEffectParameters(
1003 faudio_voice,
1004 EffectIndex,
1005 pParameters,
1006 ParametersByteSize);
1007 }
1008
SetFilterParameters(const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)1009 COM_METHOD(HRESULT) SetFilterParameters(
1010 const XAUDIO2_FILTER_PARAMETERS *pParameters,
1011 UINT32 OperationSet = FAUDIO_COMMIT_NOW
1012 ) {
1013 return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet);
1014 }
1015
GetFilterParameters(XAUDIO2_FILTER_PARAMETERS * pParameters)1016 COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters)
1017 {
1018 FAudioVoice_GetFilterParameters(faudio_voice, pParameters);
1019 }
1020
1021 #if XAUDIO2_VERSION >= 4
SetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,const XAUDIO2_FILTER_PARAMETERS * pParameters,UINT32 OperationSet=FAUDIO_COMMIT_NOW)1022 COM_METHOD(HRESULT) SetOutputFilterParameters(
1023 IXAudio2Voice *pDestinationVoice,
1024 const XAUDIO2_FILTER_PARAMETERS *pParameters,
1025 UINT32 OperationSet = FAUDIO_COMMIT_NOW
1026 ) {
1027 return FAudioVoice_SetOutputFilterParameters(
1028 faudio_voice,
1029 ((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice,
1030 pParameters,
1031 OperationSet);
1032 }
1033
GetOutputFilterParameters(IXAudio2Voice * pDestinationVoice,XAUDIO2_FILTER_PARAMETERS * pParameters)1034 COM_METHOD(void) GetOutputFilterParameters(
1035 IXAudio2Voice *pDestinationVoice,
1036 XAUDIO2_FILTER_PARAMETERS *pParameters
1037 ) {
1038 FAudioVoice_GetOutputFilterParameters(
1039 faudio_voice,
1040 ((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice,
1041 pParameters);
1042 }
1043 #endif // XAUDIO2_VERSION >= 4
1044
SetVolume(float Volume,UINT32 OperationSet=FAUDIO_COMMIT_NOW)1045 COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW)
1046 {
1047 return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet);
1048 }
1049
GetVolume(float * pVolume)1050 COM_METHOD(void) GetVolume(float *pVolume)
1051 {
1052 FAudioVoice_GetVolume(faudio_voice, pVolume);
1053 }
1054
SetChannelVolumes(UINT32 Channels,const float * pVolumes,UINT32 OperationSet=FAUDIO_COMMIT_NOW)1055 COM_METHOD(HRESULT) SetChannelVolumes(
1056 UINT32 Channels,
1057 const float *pVolumes,
1058 UINT32 OperationSet = FAUDIO_COMMIT_NOW
1059 ) {
1060 return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet);
1061 }
1062
GetChannelVolumes(UINT32 Channels,float * pVolumes)1063 COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes)
1064 {
1065 FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes);
1066 }
1067
SetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,const float * pLevelMatrix,UINT32 OperationSet=FAUDIO_COMMIT_NOW)1068 COM_METHOD(HRESULT) SetOutputMatrix(
1069 IXAudio2Voice *pDestinationVoice,
1070 UINT32 SourceChannels,
1071 UINT32 DestinationChannels,
1072 const float *pLevelMatrix,
1073 UINT32 OperationSet = FAUDIO_COMMIT_NOW
1074 ) {
1075 FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL;
1076 return FAudioVoice_SetOutputMatrix(
1077 faudio_voice,
1078 dest,
1079 SourceChannels,
1080 DestinationChannels,
1081 pLevelMatrix,
1082 OperationSet);
1083 }
1084
1085 #if XAUDIO2_VERSION >= 1
GetOutputMatrix(IXAudio2Voice * pDestinationVoice,UINT32 SourceChannels,UINT32 DestinationChannels,float * pLevelMatrix)1086 COM_METHOD(void) GetOutputMatrix(
1087 #else
1088 COM_METHOD(HRESULT) GetOutputMatrix(
1089 #endif
1090 IXAudio2Voice *pDestinationVoice,
1091 UINT32 SourceChannels,
1092 UINT32 DestinationChannels,
1093 float *pLevelMatrix
1094 ) {
1095 FAudioVoice_GetOutputMatrix(
1096 faudio_voice,
1097 pDestinationVoice->faudio_voice,
1098 SourceChannels,
1099 DestinationChannels,
1100 pLevelMatrix);
1101 #if XAUDIO2_VERSION < 1
1102 return S_OK;
1103 #endif // XAUDIO2_VERSION < 1
1104 }
1105
DestroyVoice()1106 COM_METHOD(void) DestroyVoice()
1107 {
1108 FAudioVoice_DestroyVoice(faudio_voice);
1109 // FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS
1110 free_voice_sends(voice_sends);
1111 free_effect_chain(effect_chain);
1112 delete this;
1113 }
1114
1115 // IXAudio2MasteringVoice
1116 #if XAUDIO2_VERSION >= 8
GetChannelMask(uint32_t * pChannelmask)1117 COM_METHOD(HRESULT) GetChannelMask(uint32_t *pChannelmask)
1118 {
1119 return FAudioMasteringVoice_GetChannelMask(faudio_voice, pChannelmask);
1120 }
1121 #endif
1122
1123 private:
1124 FAudioVoiceSends *voice_sends;
1125 FAudioEffectChain *effect_chain;
1126 };
1127
1128 ///////////////////////////////////////////////////////////////////////////////
1129 //
1130 // IXAudio2 implementation
1131 //
1132
XAudio2_INTERNAL_Malloc(size_t size)1133 void* CDECL XAudio2_INTERNAL_Malloc(size_t size)
1134 {
1135 return CoTaskMemAlloc(size);
1136 }
XAudio2_INTERNAL_Free(void * ptr)1137 void CDECL XAudio2_INTERNAL_Free(void* ptr)
1138 {
1139 CoTaskMemFree(ptr);
1140 }
XAudio2_INTERNAL_Realloc(void * ptr,size_t size)1141 void* CDECL XAudio2_INTERNAL_Realloc(void* ptr, size_t size)
1142 {
1143 return CoTaskMemRealloc(ptr, size);
1144 }
1145
1146 class XAudio2Impl : public IXAudio2
1147 {
1148 public:
XAudio2Impl()1149 XAudio2Impl()
1150 {
1151 callback_list.com = NULL;
1152 callback_list.next = NULL;
1153 FAudioCOMConstructWithCustomAllocatorEXT(
1154 &faudio,
1155 XAUDIO2_VERSION,
1156 XAudio2_INTERNAL_Malloc,
1157 XAudio2_INTERNAL_Free,
1158 XAudio2_INTERNAL_Realloc
1159 );
1160 }
1161
XAudio2Impl(UINT32 Flags,XAUDIO2_PROCESSOR XAudio2Processor)1162 XAudio2Impl(UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor)
1163 {
1164 callback_list.com = NULL;
1165 callback_list.next = NULL;
1166 FAudioCreateWithCustomAllocatorEXT(
1167 &faudio,
1168 Flags,
1169 XAudio2Processor,
1170 XAudio2_INTERNAL_Malloc,
1171 XAudio2_INTERNAL_Free,
1172 XAudio2_INTERNAL_Realloc
1173 );
1174 }
1175
QueryInterface(REFIID riid,void ** ppvInterface)1176 COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface)
1177 {
1178 if (guid_equals(riid, IID_IXAudio2))
1179 {
1180 *ppvInterface = static_cast<IXAudio2 *>(this);
1181 }
1182 else if (guid_equals(riid, IID_IUnknown))
1183 {
1184 *ppvInterface = static_cast<IUnknown *>(this);
1185 }
1186 else
1187 {
1188 *ppvInterface = NULL;
1189 return E_NOINTERFACE;
1190 }
1191
1192 reinterpret_cast<IUnknown *>(*ppvInterface)->AddRef();
1193
1194 return S_OK;
1195 }
1196
AddRef()1197 COM_METHOD(ULONG) AddRef()
1198 {
1199 return FAudio_AddRef(faudio);
1200 }
1201
Release()1202 COM_METHOD(ULONG) Release()
1203 {
1204 ULONG refcount = FAudio_Release(faudio);
1205 if (refcount == 0)
1206 {
1207 delete this;
1208 }
1209 return 1;
1210 }
1211
1212 #if (XAUDIO2_VERSION <= 7)
GetDeviceCount(UINT32 * pCount)1213 COM_METHOD(HRESULT) GetDeviceCount(UINT32 *pCount)
1214 {
1215 return FAudio_GetDeviceCount(faudio, pCount);
1216 }
1217
GetDeviceDetails(UINT32 Index,XAUDIO2_DEVICE_DETAILS * pDeviceDetails)1218 COM_METHOD(HRESULT) GetDeviceDetails(UINT32 Index, XAUDIO2_DEVICE_DETAILS *pDeviceDetails)
1219 {
1220 return FAudio_GetDeviceDetails(faudio, Index, pDeviceDetails);
1221 }
1222
Initialize(UINT32 Flags=0,XAUDIO2_PROCESSOR XAudio2Processor=FAUDIO_DEFAULT_PROCESSOR)1223 COM_METHOD(HRESULT) Initialize(
1224 UINT32 Flags = 0,
1225 XAUDIO2_PROCESSOR XAudio2Processor = FAUDIO_DEFAULT_PROCESSOR
1226 ) {
1227 return FAudio_Initialize(faudio, Flags, XAudio2Processor);
1228 }
1229 #endif // XAUDIO2_VERSION <= 7
1230
RegisterForCallbacks(IXAudio2EngineCallback * pCallback)1231 COM_METHOD(HRESULT) RegisterForCallbacks(IXAudio2EngineCallback *pCallback)
1232 {
1233 FAudioCppEngineCallback *cb = wrap_engine_callback(pCallback);
1234 cb->next = callback_list.next;
1235 callback_list.next = cb;
1236
1237 return FAudio_RegisterForCallbacks(faudio, reinterpret_cast<FAudioEngineCallback *>(cb));
1238 }
1239
UnregisterForCallbacks(IXAudio2EngineCallback * pCallback)1240 COM_METHOD(void) UnregisterForCallbacks(IXAudio2EngineCallback *pCallback)
1241 {
1242 FAudioCppEngineCallback *cb = find_and_remove_engine_callback(&callback_list, pCallback);
1243
1244 if (cb == NULL)
1245 {
1246 return;
1247 }
1248
1249 FAudio_UnregisterForCallbacks(faudio, reinterpret_cast<FAudioEngineCallback *>(cb));
1250 delete cb;
1251 }
1252
CreateSourceVoice(IXAudio2SourceVoice ** ppSourceVoice,const WAVEFORMATEX * pSourceFormat,UINT32 Flags=0,float MaxFrequencyRatio=FAUDIO_DEFAULT_FREQ_RATIO,IXAudio2VoiceCallback * pCallback=NULL,const XAUDIO2_VOICE_SENDS * pSendList=NULL,const XAUDIO2_EFFECT_CHAIN * pEffectChain=NULL)1253 COM_METHOD(HRESULT) CreateSourceVoice(
1254 IXAudio2SourceVoice **ppSourceVoice,
1255 const WAVEFORMATEX *pSourceFormat,
1256 UINT32 Flags = 0,
1257 float MaxFrequencyRatio = FAUDIO_DEFAULT_FREQ_RATIO,
1258 IXAudio2VoiceCallback *pCallback = NULL,
1259 const XAUDIO2_VOICE_SENDS *pSendList = NULL,
1260 const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL
1261 ) {
1262 *ppSourceVoice = new XAudio2SourceVoiceImpl(
1263 faudio, pSourceFormat, Flags, MaxFrequencyRatio, pCallback, pSendList, pEffectChain);
1264 return S_OK;
1265 }
1266
CreateSubmixVoice(IXAudio2SubmixVoice ** ppSubmixVoice,UINT32 InputChannels,UINT32 InputSampleRate,UINT32 Flags=0,UINT32 ProcessingStage=0,const XAUDIO2_VOICE_SENDS * pSendList=NULL,const XAUDIO2_EFFECT_CHAIN * pEffectChain=NULL)1267 COM_METHOD(HRESULT) CreateSubmixVoice(
1268 IXAudio2SubmixVoice **ppSubmixVoice,
1269 UINT32 InputChannels,
1270 UINT32 InputSampleRate,
1271 UINT32 Flags = 0,
1272 UINT32 ProcessingStage = 0,
1273 const XAUDIO2_VOICE_SENDS *pSendList = NULL,
1274 const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL
1275 ) {
1276 *ppSubmixVoice = new XAudio2SubmixVoiceImpl(
1277 faudio,
1278 InputChannels,
1279 InputSampleRate,
1280 Flags,
1281 ProcessingStage,
1282 pSendList,
1283 pEffectChain);
1284 return S_OK;
1285 }
1286
1287 #if (XAUDIO2_VERSION <= 7)
CreateMasteringVoice(IXAudio2MasteringVoice ** ppMasteringVoice,UINT32 InputChannels=FAUDIO_DEFAULT_CHANNELS,UINT32 InputSampleRate=FAUDIO_DEFAULT_SAMPLERATE,UINT32 Flags=0,UINT32 DeviceIndex=0,const XAUDIO2_EFFECT_CHAIN * pEffectChain=NULL)1288 COM_METHOD(HRESULT) CreateMasteringVoice(
1289 IXAudio2MasteringVoice **ppMasteringVoice,
1290 UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS,
1291 UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE,
1292 UINT32 Flags = 0,
1293 UINT32 DeviceIndex = 0,
1294 const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL
1295 ) {
1296 *ppMasteringVoice = new XAudio2MasteringVoiceImpl(
1297 faudio, InputChannels, InputSampleRate, Flags, DeviceIndex, pEffectChain);
1298 return S_OK;
1299 }
1300 #else
CreateMasteringVoice(IXAudio2MasteringVoice ** ppMasteringVoice,UINT32 InputChannels=FAUDIO_DEFAULT_CHANNELS,UINT32 InputSampleRate=FAUDIO_DEFAULT_SAMPLERATE,UINT32 Flags=0,LPCWSTR szDeviceId=NULL,const XAUDIO2_EFFECT_CHAIN * pEffectChain=NULL,int StreamCategory=6)1301 COM_METHOD(HRESULT) CreateMasteringVoice(
1302 IXAudio2MasteringVoice **ppMasteringVoice,
1303 UINT32 InputChannels = FAUDIO_DEFAULT_CHANNELS,
1304 UINT32 InputSampleRate = FAUDIO_DEFAULT_SAMPLERATE,
1305 UINT32 Flags = 0,
1306 LPCWSTR szDeviceId = NULL,
1307 const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL,
1308 int StreamCategory = 6
1309 ) {
1310 *ppMasteringVoice = new XAudio2MasteringVoiceImpl(
1311 faudio,
1312 InputChannels,
1313 InputSampleRate,
1314 Flags,
1315 szDeviceId,
1316 pEffectChain,
1317 StreamCategory);
1318 return S_OK;
1319 }
1320 #endif
1321
StartEngine()1322 COM_METHOD(HRESULT) StartEngine()
1323 {
1324 return FAudio_StartEngine(faudio);
1325 }
1326
StopEngine()1327 COM_METHOD(void) StopEngine()
1328 {
1329 FAudio_StopEngine(faudio);
1330 }
1331
CommitChanges(UINT32 OperationSet)1332 COM_METHOD(HRESULT) CommitChanges(UINT32 OperationSet)
1333 {
1334 return FAudio_CommitOperationSet(faudio, OperationSet);
1335 }
1336
GetPerformanceData(XAUDIO2_PERFORMANCE_DATA * pPerfData)1337 COM_METHOD(void) GetPerformanceData(XAUDIO2_PERFORMANCE_DATA *pPerfData)
1338 {
1339 #if XAUDIO2_VERSION >= 3
1340 FAudio_GetPerformanceData(faudio, pPerfData);
1341 #else
1342 FAudioPerformanceData fPerfData;
1343 FAudio_GetPerformanceData(faudio, &fPerfData);
1344
1345 pPerfData->AudioCyclesSinceLastQuery = fPerfData.AudioCyclesSinceLastQuery;
1346 pPerfData->TotalCyclesSinceLastQuery = fPerfData.TotalCyclesSinceLastQuery;
1347 pPerfData->MinimumCyclesPerQuantum = fPerfData.MinimumCyclesPerQuantum;
1348 pPerfData->MaximumCyclesPerQuantum = fPerfData.MaximumCyclesPerQuantum;
1349 pPerfData->MemoryUsageInBytes = fPerfData.MemoryUsageInBytes;
1350 pPerfData->CurrentLatencyInSamples = fPerfData.CurrentLatencyInSamples;
1351 pPerfData->GlitchesSinceEngineStarted = fPerfData.GlitchesSinceEngineStarted;
1352 pPerfData->ActiveSourceVoiceCount = fPerfData.ActiveSourceVoiceCount;
1353 pPerfData->TotalSourceVoiceCount = fPerfData.TotalSourceVoiceCount;
1354 pPerfData->ActiveSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount;
1355 pPerfData->TotalSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount;
1356 pPerfData->ActiveXmaSourceVoices = fPerfData.ActiveXmaSourceVoices;
1357 pPerfData->ActiveXmaStreams = fPerfData.ActiveXmaStreams;
1358 #endif // XAUDIO2_VERSION >= 3
1359 }
1360
1361 COM_METHOD(void)
SetDebugConfiguration(XAUDIO2_DEBUG_CONFIGURATION * pDebugConfiguration,void * pReserved=NULL)1362 SetDebugConfiguration(
1363 XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration,
1364 void *pReserved = NULL
1365 ) {
1366 FAudio_SetDebugConfiguration(
1367 faudio,
1368 pDebugConfiguration,
1369 pReserved);
1370 }
1371
1372 private:
1373 FAudio *faudio;
1374 FAudioCppEngineCallback callback_list;
1375 };
1376
1377 ///////////////////////////////////////////////////////////////////////////////
1378 //
1379 // Create function
1380 //
1381
CreateXAudio2Internal()1382 void *CreateXAudio2Internal()
1383 {
1384 return new XAudio2Impl();
1385 }
1386
1387 #if XAUDIO2_VERSION >= 8
1388
XAudio2Create(IXAudio2 ** ppXAudio2,UINT32 Flags,XAUDIO2_PROCESSOR XAudio2Processor)1389 extern "C" FAUDIOCPP_API XAudio2Create(IXAudio2 **ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor)
1390 {
1391 // FAudio only accepts one processor
1392 *ppXAudio2 = new XAudio2Impl(Flags, FAUDIO_DEFAULT_PROCESSOR);
1393 return S_OK;
1394 }
1395
1396 #endif // XAUDIO2_VERSION >= 8
1397