Show More
Commit Description:
Improve logging....
Commit Description:
Improve logging.
?Add logging for World.Draw (renderers)
?Keeping logging display from jumping around.
References:
File last commit:
Show/Diff file:
Action:
FNA/lib/FAudio/cpp/xaudio2.cpp
1396 lines | 36.3 KiB | text/x-c | CppLexer
1396 lines | 36.3 KiB | text/x-c | CppLexer
r0 | #include "xaudio2.h" | |||
#include "XAPO.h" | ||||
#include <FAPOBase.h> | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2VoiceCallback | ||||
// | ||||
struct FAudioVoiceCppCallback | ||||
{ | ||||
FAudioVoiceCallback callbacks; | ||||
IXAudio2VoiceCallback *com; | ||||
}; | ||||
static void FAUDIOCALL OnBufferEnd(FAudioVoiceCallback *callback, void *pBufferContext) | ||||
{ | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnBufferEnd(pBufferContext); | ||||
} | ||||
static void FAUDIOCALL OnBufferStart(FAudioVoiceCallback *callback, void *pBufferContext) | ||||
{ | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnBufferStart(pBufferContext); | ||||
} | ||||
static void FAUDIOCALL OnLoopEnd(FAudioVoiceCallback *callback, void *pBufferContext) | ||||
{ | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnLoopEnd(pBufferContext); | ||||
} | ||||
static void FAUDIOCALL OnStreamEnd(FAudioVoiceCallback *callback) | ||||
{ | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnStreamEnd(); | ||||
} | ||||
static void FAUDIOCALL OnVoiceError( | ||||
FAudioVoiceCallback *callback, | ||||
void *pBufferContext, | ||||
uint32_t Error | ||||
) { | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceError(pBufferContext, Error); | ||||
} | ||||
static void FAUDIOCALL OnVoiceProcessingPassEnd(FAudioVoiceCallback *callback) | ||||
{ | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassEnd(); | ||||
} | ||||
static void FAUDIOCALL OnVoiceProcessingPassStart( | ||||
FAudioVoiceCallback *callback, | ||||
uint32_t BytesRequired | ||||
) { | ||||
#if XAUDIO2_VERSION >= 1 | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassStart( | ||||
BytesRequired); | ||||
#else | ||||
reinterpret_cast<FAudioVoiceCppCallback *>(callback)->com->OnVoiceProcessingPassStart(); | ||||
#endif // XAUDIO2_VERSION >= 1 | ||||
} | ||||
FAudioVoiceCppCallback *wrap_voice_callback(IXAudio2VoiceCallback *com_interface) | ||||
{ | ||||
if (com_interface == NULL) | ||||
{ | ||||
return NULL; | ||||
} | ||||
FAudioVoiceCppCallback *cb = new FAudioVoiceCppCallback(); | ||||
cb->callbacks.OnBufferEnd = OnBufferEnd; | ||||
cb->callbacks.OnBufferStart = OnBufferStart; | ||||
cb->callbacks.OnLoopEnd = OnLoopEnd; | ||||
cb->callbacks.OnStreamEnd = OnStreamEnd; | ||||
cb->callbacks.OnVoiceError = OnVoiceError; | ||||
cb->callbacks.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd; | ||||
cb->callbacks.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart; | ||||
cb->com = com_interface; | ||||
return cb; | ||||
} | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2EngineCallback | ||||
// | ||||
struct FAudioCppEngineCallback | ||||
{ | ||||
FAudioEngineCallback callbacks; | ||||
IXAudio2EngineCallback *com; | ||||
FAudioCppEngineCallback *next; | ||||
}; | ||||
static void FAUDIOCALL OnCriticalError(FAudioEngineCallback *callback, uint32_t Error) | ||||
{ | ||||
reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnCriticalError(Error); | ||||
} | ||||
static void FAUDIOCALL OnProcessingPassEnd(FAudioEngineCallback *callback) | ||||
{ | ||||
reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnProcessingPassEnd(); | ||||
} | ||||
static void FAUDIOCALL OnProcessingPassStart(FAudioEngineCallback *callback) | ||||
{ | ||||
reinterpret_cast<FAudioCppEngineCallback *>(callback)->com->OnProcessingPassStart(); | ||||
} | ||||
static FAudioCppEngineCallback *wrap_engine_callback(IXAudio2EngineCallback *com_interface) | ||||
{ | ||||
if (com_interface == NULL) | ||||
{ | ||||
return NULL; | ||||
} | ||||
FAudioCppEngineCallback *cb = new FAudioCppEngineCallback(); | ||||
cb->callbacks.OnCriticalError = OnCriticalError; | ||||
cb->callbacks.OnProcessingPassEnd = OnProcessingPassEnd; | ||||
cb->callbacks.OnProcessingPassStart = OnProcessingPassStart; | ||||
cb->com = com_interface; | ||||
cb->next = NULL; | ||||
return cb; | ||||
} | ||||
static FAudioCppEngineCallback *find_and_remove_engine_callback( | ||||
FAudioCppEngineCallback *list, | ||||
IXAudio2EngineCallback *com | ||||
) { | ||||
FAudioCppEngineCallback *last = list; | ||||
for (FAudioCppEngineCallback *it = list->next; it != NULL; it = it->next) | ||||
{ | ||||
if (it->com == com) | ||||
{ | ||||
last->next = it->next; | ||||
return it; | ||||
} | ||||
last = it; | ||||
} | ||||
return NULL; | ||||
} | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// XAUDIO2_VOICE_SENDS / XAUDIO2_SEND_DESCRIPTOR => FAudio | ||||
// | ||||
static FAudioVoiceSends *unwrap_voice_sends(const XAUDIO2_VOICE_SENDS *x_sends) | ||||
{ | ||||
if (x_sends == NULL) | ||||
{ | ||||
return NULL; | ||||
} | ||||
FAudioVoiceSends *f_sends = new FAudioVoiceSends; | ||||
f_sends->SendCount = x_sends->SendCount; | ||||
f_sends->pSends = new FAudioSendDescriptor[f_sends->SendCount]; | ||||
for (uint32_t i = 0; i < f_sends->SendCount; ++i) | ||||
{ | ||||
#if XAUDIO2_VERSION >= 4 | ||||
f_sends->pSends[i].Flags = x_sends->pSends[i].Flags; | ||||
f_sends->pSends[i].pOutputVoice = x_sends->pSends[i].pOutputVoice->faudio_voice; | ||||
#else | ||||
f_sends->pSends[i].Flags = 0; | ||||
f_sends->pSends[i].pOutputVoice = x_sends->pSends[i]->faudio_voice; | ||||
#endif // XAUDIO2_VERSION >= 4 | ||||
} | ||||
return f_sends; | ||||
} | ||||
static void free_voice_sends(FAudioVoiceSends *f_sends) | ||||
{ | ||||
if (f_sends != NULL) | ||||
{ | ||||
delete[] f_sends->pSends; | ||||
delete f_sends; | ||||
} | ||||
} | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// XAUDIO2_EFFECT_CHAIN / XAUDIO2_EFFECT_DESCRIPTOR => FAudio | ||||
// | ||||
struct FAPOCppBase | ||||
{ | ||||
FAPO fapo; | ||||
IXAPO *xapo; | ||||
IXAPOParameters *xapo_params; | ||||
LONG refcount; | ||||
}; | ||||
static int32_t FAPOCALL AddRef(void *fapo) | ||||
{ | ||||
FAPOCppBase *base = reinterpret_cast<FAPOCppBase *>(fapo); | ||||
return ++base->refcount; | ||||
} | ||||
static int32_t FAPOCALL Release(void *fapo) | ||||
{ | ||||
FAPOCppBase *base = reinterpret_cast<FAPOCppBase *>(fapo); | ||||
IXAPO *xapo = base->xapo; | ||||
LONG ref = --base->refcount; | ||||
if (ref == 0) | ||||
{ | ||||
xapo->Release(); | ||||
if (base->xapo_params != NULL) | ||||
{ | ||||
base->xapo_params->Release(); | ||||
} | ||||
delete base; | ||||
} | ||||
return ref; | ||||
} | ||||
static uint32_t FAPOCALL GetRegistrationProperties( | ||||
void *fapo, | ||||
FAPORegistrationProperties **ppRegistrationProperties) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->GetRegistrationProperties(ppRegistrationProperties); | ||||
} | ||||
static uint32_t FAPOCALL IsInputFormatSupported( | ||||
void *fapo, | ||||
const FAudioWaveFormatEx *pOutputFormat, | ||||
const FAudioWaveFormatEx *pRequestedInputFormat, | ||||
FAudioWaveFormatEx **ppSupportedInputFormat | ||||
) { | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->IsInputFormatSupported( | ||||
pOutputFormat, | ||||
pRequestedInputFormat, | ||||
ppSupportedInputFormat); | ||||
} | ||||
static uint32_t FAPOCALL IsOutputFormatSupported( | ||||
void *fapo, | ||||
const FAudioWaveFormatEx *pInputFormat, | ||||
const FAudioWaveFormatEx *pRequestedOutputFormat, | ||||
FAudioWaveFormatEx **ppSupportedOutputFormat | ||||
) { | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->IsOutputFormatSupported( | ||||
pInputFormat, | ||||
pRequestedOutputFormat, | ||||
ppSupportedOutputFormat); | ||||
} | ||||
static uint32_t FAPOCALL Initialize(void *fapo, const void *pData, uint32_t DataByteSize) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->Initialize(pData, DataByteSize); | ||||
} | ||||
static void FAPOCALL Reset(void *fapo) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
xapo->Reset(); | ||||
} | ||||
static uint32_t FAPOCALL LockForProcess( | ||||
void *fapo, | ||||
uint32_t InputLockedParameterCount, | ||||
const FAPOLockForProcessBufferParameters *pInputLockedParameters, | ||||
uint32_t OutputLockedParameterCount, | ||||
const FAPOLockForProcessBufferParameters *pOutputLockedParameters | ||||
) { | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->LockForProcess( | ||||
InputLockedParameterCount, | ||||
pInputLockedParameters, | ||||
OutputLockedParameterCount, | ||||
pOutputLockedParameters); | ||||
} | ||||
static void FAPOCALL UnlockForProcess(void *fapo) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
xapo->UnlockForProcess(); | ||||
} | ||||
static void FAPOCALL Process( | ||||
void *fapo, | ||||
uint32_t InputProcessParameterCount, | ||||
const FAPOProcessBufferParameters *pInputProcessParameters, | ||||
uint32_t OutputProcessParameterCount, | ||||
FAPOProcessBufferParameters *pOutputProcessParameters, | ||||
int32_t IsEnabled | ||||
) { | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
xapo->Process( | ||||
InputProcessParameterCount, | ||||
pInputProcessParameters, | ||||
OutputProcessParameterCount, | ||||
pOutputProcessParameters, | ||||
IsEnabled); | ||||
} | ||||
static uint32_t FAPOCALL CalcInputFrames(void *fapo, uint32_t OutputFrameCount) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->CalcInputFrames(OutputFrameCount); | ||||
} | ||||
static uint32_t FAPOCALL CalcOutputFrames(void *fapo, uint32_t InputFrameCount) | ||||
{ | ||||
IXAPO *xapo = reinterpret_cast<FAPOCppBase *>(fapo)->xapo; | ||||
return xapo->CalcOutputFrames(InputFrameCount); | ||||
} | ||||
static void FAPOCALL SetParameters( | ||||
void *fapoParameters, | ||||
const void *pParameters, | ||||
uint32_t ParameterByteSize | ||||
) { | ||||
IXAPOParameters *xapo_params = reinterpret_cast<FAPOCppBase *>(fapoParameters)->xapo_params; | ||||
return xapo_params->SetParameters(pParameters, ParameterByteSize); | ||||
} | ||||
static void FAPOCALL GetParameters(void *fapoParameters, void *pParameters, uint32_t ParameterByteSize) | ||||
{ | ||||
IXAPOParameters *xapo_params = reinterpret_cast<FAPOCppBase *>(fapoParameters)->xapo_params; | ||||
return xapo_params->GetParameters(pParameters, ParameterByteSize); | ||||
} | ||||
static FAPO *wrap_xapo_effect(IUnknown *xapo) | ||||
{ | ||||
if (xapo == NULL) | ||||
{ | ||||
return NULL; | ||||
} | ||||
// FIXME: assumes that all effects are derived from CXAPOParametersBase | ||||
FAPOCppBase *f_effect = new FAPOCppBase; | ||||
f_effect->refcount = 1; | ||||
xapo->QueryInterface(IID_IXAPO, (void **)&f_effect->xapo); | ||||
xapo->QueryInterface(IID_IXAPOParameters, (void **)&f_effect->xapo_params); | ||||
f_effect->fapo.AddRef = AddRef; | ||||
f_effect->fapo.Release = Release; | ||||
f_effect->fapo.GetRegistrationProperties = GetRegistrationProperties; | ||||
f_effect->fapo.IsInputFormatSupported = IsInputFormatSupported; | ||||
f_effect->fapo.IsOutputFormatSupported = IsOutputFormatSupported; | ||||
f_effect->fapo.Initialize = Initialize; | ||||
f_effect->fapo.Reset = Reset; | ||||
f_effect->fapo.LockForProcess = LockForProcess; | ||||
f_effect->fapo.UnlockForProcess = UnlockForProcess; | ||||
f_effect->fapo.Process = Process; | ||||
f_effect->fapo.CalcInputFrames = CalcInputFrames; | ||||
f_effect->fapo.CalcOutputFrames = CalcOutputFrames; | ||||
f_effect->fapo.GetParameters = GetParameters; | ||||
f_effect->fapo.SetParameters = SetParameters; | ||||
return &f_effect->fapo; | ||||
} | ||||
static FAudioEffectChain *wrap_effect_chain(const XAUDIO2_EFFECT_CHAIN *x_chain) | ||||
{ | ||||
if (x_chain == NULL) | ||||
{ | ||||
return NULL; | ||||
} | ||||
FAudioEffectChain *f_chain = new FAudioEffectChain; | ||||
f_chain->EffectCount = x_chain->EffectCount; | ||||
f_chain->pEffectDescriptors = new FAudioEffectDescriptor[f_chain->EffectCount]; | ||||
for (uint32_t i = 0; i < f_chain->EffectCount; ++i) | ||||
{ | ||||
f_chain->pEffectDescriptors[i].InitialState = x_chain->pEffectDescriptors[i].InitialState; | ||||
f_chain->pEffectDescriptors[i].OutputChannels = | ||||
x_chain->pEffectDescriptors[i].OutputChannel; | ||||
f_chain->pEffectDescriptors[i].pEffect = | ||||
wrap_xapo_effect(x_chain->pEffectDescriptors[i].pEffect); | ||||
} | ||||
return f_chain; | ||||
} | ||||
static void free_effect_chain(FAudioEffectChain *f_chain) | ||||
{ | ||||
if (f_chain != NULL) | ||||
{ | ||||
delete[] f_chain->pEffectDescriptors; | ||||
delete f_chain; | ||||
} | ||||
} | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2SourceVoice implementation | ||||
// | ||||
class XAudio2SourceVoiceImpl : public IXAudio2SourceVoice | ||||
{ | ||||
public: | ||||
XAudio2SourceVoiceImpl( | ||||
FAudio *faudio, | ||||
const WAVEFORMATEX *pSourceFormat, | ||||
UINT32 Flags, | ||||
float MaxFrequencyRatio, | ||||
IXAudio2VoiceCallback *pCallback, | ||||
const XAUDIO2_VOICE_SENDS *pSendList, | ||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain) | ||||
{ | ||||
voice_callback = wrap_voice_callback(pCallback); | ||||
voice_sends = unwrap_voice_sends(pSendList); | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
FAudio_CreateSourceVoice( | ||||
faudio, | ||||
&faudio_voice, | ||||
pSourceFormat, | ||||
Flags, | ||||
MaxFrequencyRatio, | ||||
reinterpret_cast<FAudioVoiceCallback *>(voice_callback), | ||||
voice_sends, | ||||
effect_chain); | ||||
} | ||||
// IXAudio2Voice | ||||
COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) | ||||
{ | ||||
#if XAUDIO2_VERSION > 7 | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); | ||||
#else | ||||
FAudioVoiceDetails fDetails; | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); | ||||
pVoiceDetails->CreationFlags = fDetails.CreationFlags; | ||||
pVoiceDetails->InputChannels = fDetails.InputChannels; | ||||
pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; | ||||
#endif // XAUDIO2_VERSION <= 7 | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) | ||||
{ | ||||
free_voice_sends(voice_sends); | ||||
voice_sends = unwrap_voice_sends(pSendList); | ||||
return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) | ||||
{ | ||||
free_effect_chain(effect_chain); | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); | ||||
} | ||||
COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) | ||||
{ | ||||
FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
const void *pParameters, | ||||
UINT32 ParametersByteSize, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) GetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
void *pParameters, | ||||
UINT32 ParametersByteSize) | ||||
{ | ||||
return FAudioVoice_GetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize); | ||||
} | ||||
COM_METHOD(HRESULT) SetFilterParameters( | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) | ||||
{ | ||||
FAudioVoice_GetFilterParameters(faudio_voice, pParameters); | ||||
} | ||||
#if XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetOutputFilterParameters( | ||||
faudio_voice, | ||||
((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice, | ||||
pParameters, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(void) GetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
XAUDIO2_FILTER_PARAMETERS *pParameters | ||||
) { | ||||
FAudioVoice_GetOutputFilterParameters( | ||||
faudio_voice, | ||||
((XAudio2SourceVoiceImpl *)pDestinationVoice)->faudio_voice, | ||||
pParameters); | ||||
} | ||||
#endif // XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetVolume(float *pVolume) | ||||
{ | ||||
FAudioVoice_GetVolume(faudio_voice, pVolume); | ||||
} | ||||
COM_METHOD(HRESULT) SetChannelVolumes( | ||||
UINT32 Channels, | ||||
const float *pVolumes, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) | ||||
{ | ||||
FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputMatrix( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
const float *pLevelMatrix, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; | ||||
return FAudioVoice_SetOutputMatrix( | ||||
faudio_voice, dest, SourceChannels, DestinationChannels, pLevelMatrix, OperationSet); | ||||
} | ||||
#if XAUDIO2_VERSION >= 1 | ||||
COM_METHOD(void) GetOutputMatrix( | ||||
#else | ||||
COM_METHOD(HRESULT) GetOutputMatrix( | ||||
#endif | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
float *pLevelMatrix | ||||
) { | ||||
FAudioVoice_GetOutputMatrix( | ||||
faudio_voice, | ||||
pDestinationVoice->faudio_voice, | ||||
SourceChannels, | ||||
DestinationChannels, | ||||
pLevelMatrix); | ||||
#if XAUDIO2_VERSION < 1 | ||||
return S_OK; | ||||
#endif // XAUDIO2_VERSION < 1 | ||||
} | ||||
COM_METHOD(void) DestroyVoice() | ||||
{ | ||||
FAudioVoice_DestroyVoice(faudio_voice); | ||||
// FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS | ||||
if (voice_callback) | ||||
{ | ||||
delete voice_callback; | ||||
} | ||||
free_voice_sends(voice_sends); | ||||
free_effect_chain(effect_chain); | ||||
delete this; | ||||
} | ||||
// IXAudio2SourceVoice | ||||
COM_METHOD(HRESULT) Start(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioSourceVoice_Start(faudio_voice, Flags, OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) Stop(UINT32 Flags = 0, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioSourceVoice_Stop(faudio_voice, Flags, OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) SubmitSourceBuffer( | ||||
const XAUDIO2_BUFFER *pBuffer, | ||||
const XAUDIO2_BUFFER_WMA *pBufferWMA = NULL) | ||||
{ | ||||
return FAudioSourceVoice_SubmitSourceBuffer(faudio_voice, pBuffer, pBufferWMA); | ||||
} | ||||
COM_METHOD(HRESULT) FlushSourceBuffers() | ||||
{ | ||||
return FAudioSourceVoice_FlushSourceBuffers(faudio_voice); | ||||
} | ||||
COM_METHOD(HRESULT) Discontinuity() | ||||
{ | ||||
return FAudioSourceVoice_Discontinuity(faudio_voice); | ||||
} | ||||
COM_METHOD(HRESULT) ExitLoop(UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioSourceVoice_ExitLoop(faudio_voice, OperationSet); | ||||
} | ||||
#if (XAUDIO2_VERSION <= 7) | ||||
COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState) | ||||
#else | ||||
COM_METHOD(void) GetState(XAUDIO2_VOICE_STATE *pVoiceState, UINT32 Flags = 0) | ||||
#endif | ||||
{ | ||||
#if (XAUDIO2_VERSION <= 7) | ||||
FAudioSourceVoice_GetState(faudio_voice, pVoiceState, 0); | ||||
#else | ||||
FAudioSourceVoice_GetState(faudio_voice, pVoiceState, Flags); | ||||
#endif | ||||
} | ||||
COM_METHOD(HRESULT) SetFrequencyRatio(float Ratio, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioSourceVoice_SetFrequencyRatio(faudio_voice, Ratio, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetFrequencyRatio(float *pRatio) | ||||
{ | ||||
FAudioSourceVoice_GetFrequencyRatio(faudio_voice, pRatio); | ||||
} | ||||
#if XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetSourceSampleRate(UINT32 NewSourceSampleRate) | ||||
{ | ||||
return FAudioSourceVoice_SetSourceSampleRate(faudio_voice, NewSourceSampleRate); | ||||
} | ||||
#endif // XAUDIO2_VERSION >= 4 | ||||
private: | ||||
FAudioVoiceCppCallback *voice_callback; | ||||
FAudioVoiceSends *voice_sends; | ||||
FAudioEffectChain *effect_chain; | ||||
}; | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2SubmixVoice implementation | ||||
// | ||||
class XAudio2SubmixVoiceImpl : public IXAudio2SubmixVoice | ||||
{ | ||||
public: | ||||
XAudio2SubmixVoiceImpl( | ||||
FAudio *faudio, | ||||
UINT32 InputChannels, | ||||
UINT32 InputSampleRate, | ||||
UINT32 Flags, | ||||
UINT32 ProcessingStage, | ||||
const XAUDIO2_VOICE_SENDS *pSendList, | ||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain | ||||
) { | ||||
voice_sends = unwrap_voice_sends(pSendList); | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
FAudio_CreateSubmixVoice( | ||||
faudio, | ||||
&faudio_voice, | ||||
InputChannels, | ||||
InputSampleRate, | ||||
Flags, | ||||
ProcessingStage, | ||||
voice_sends, | ||||
effect_chain); | ||||
} | ||||
// IXAudio2Voice | ||||
COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) | ||||
{ | ||||
#if XAUDIO2_VERSION > 7 | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); | ||||
#else | ||||
FAudioVoiceDetails fDetails; | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); | ||||
pVoiceDetails->CreationFlags = fDetails.CreationFlags; | ||||
pVoiceDetails->InputChannels = fDetails.InputChannels; | ||||
pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; | ||||
#endif // XAUDIO2_VERSION <= 7 | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) | ||||
{ | ||||
free_voice_sends(voice_sends); | ||||
voice_sends = unwrap_voice_sends(pSendList); | ||||
return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) | ||||
{ | ||||
free_effect_chain(effect_chain); | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); | ||||
} | ||||
COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) | ||||
{ | ||||
FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
const void *pParameters, | ||||
UINT32 ParametersByteSize, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) GetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
void *pParameters, | ||||
UINT32 ParametersByteSize | ||||
) { | ||||
return FAudioVoice_GetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize); | ||||
} | ||||
COM_METHOD(HRESULT) SetFilterParameters( | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) | ||||
{ | ||||
FAudioVoice_GetFilterParameters(faudio_voice, pParameters); | ||||
} | ||||
#if XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetOutputFilterParameters( | ||||
faudio_voice, | ||||
((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice, | ||||
pParameters, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(void) GetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
XAUDIO2_FILTER_PARAMETERS *pParameters | ||||
) { | ||||
FAudioVoice_GetOutputFilterParameters( | ||||
faudio_voice, ((XAudio2SubmixVoiceImpl *)pDestinationVoice)->faudio_voice, pParameters); | ||||
} | ||||
#endif // XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetVolume(float *pVolume) | ||||
{ | ||||
FAudioVoice_GetVolume(faudio_voice, pVolume); | ||||
} | ||||
COM_METHOD(HRESULT) SetChannelVolumes( | ||||
UINT32 Channels, | ||||
const float *pVolumes, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) | ||||
{ | ||||
FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputMatrix( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
const float *pLevelMatrix, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; | ||||
return FAudioVoice_SetOutputMatrix( | ||||
faudio_voice, | ||||
dest, | ||||
SourceChannels, | ||||
DestinationChannels, | ||||
pLevelMatrix, | ||||
OperationSet); | ||||
} | ||||
#if XAUDIO2_VERSION >= 1 | ||||
COM_METHOD(void) GetOutputMatrix( | ||||
#else | ||||
COM_METHOD(HRESULT) GetOutputMatrix( | ||||
#endif | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
float *pLevelMatrix | ||||
) { | ||||
FAudioVoice_GetOutputMatrix( | ||||
faudio_voice, | ||||
pDestinationVoice->faudio_voice, | ||||
SourceChannels, | ||||
DestinationChannels, | ||||
pLevelMatrix); | ||||
#if XAUDIO2_VERSION < 1 | ||||
return S_OK; | ||||
#endif // XAUDIO2_VERSION < 1 | ||||
} | ||||
COM_METHOD(void) DestroyVoice() | ||||
{ | ||||
FAudioVoice_DestroyVoice(faudio_voice); | ||||
// FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS | ||||
free_voice_sends(voice_sends); | ||||
free_effect_chain(effect_chain); | ||||
delete this; | ||||
} | ||||
private: | ||||
FAudioVoiceSends *voice_sends; | ||||
FAudioEffectChain *effect_chain; | ||||
}; | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2MasteringVoice implementation | ||||
// | ||||
#if (XAUDIO2_VERSION >= 8) | ||||
uint32_t device_index_from_device_id(FAudio *faudio, LPCWSTR deviceId); | ||||
#endif // (XAUDIO2_VERSION >= 8) | ||||
class XAudio2MasteringVoiceImpl : public IXAudio2MasteringVoice | ||||
{ | ||||
public: | ||||
#if (XAUDIO2_VERSION <= 7) | ||||
XAudio2MasteringVoiceImpl( | ||||
FAudio *faudio, | ||||
UINT32 InputChannels, | ||||
UINT32 InputSampleRate, | ||||
UINT32 Flags, | ||||
UINT32 DeviceIndex, | ||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain | ||||
) { | ||||
voice_sends = NULL; | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
FAudio_CreateMasteringVoice( | ||||
faudio, | ||||
&faudio_voice, | ||||
InputChannels, | ||||
InputSampleRate, | ||||
Flags, | ||||
DeviceIndex, | ||||
effect_chain); | ||||
} | ||||
#else | ||||
XAudio2MasteringVoiceImpl( | ||||
FAudio *faudio, | ||||
UINT32 InputChannels, | ||||
UINT32 InputSampleRate, | ||||
UINT32 Flags, | ||||
LPCWSTR szDeviceId, | ||||
const XAUDIO2_EFFECT_CHAIN *pEffectChain, | ||||
int StreamCategory | ||||
) { | ||||
uint32_t device_index = 0; | ||||
if (szDeviceId != NULL) | ||||
{ | ||||
device_index = device_index_from_device_id(faudio, szDeviceId); | ||||
} | ||||
voice_sends = NULL; | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
FAudio_CreateMasteringVoice( | ||||
faudio, | ||||
&faudio_voice, | ||||
InputChannels, | ||||
InputSampleRate, | ||||
Flags, | ||||
device_index, | ||||
effect_chain); | ||||
} | ||||
#endif | ||||
// IXAudio2Voice | ||||
COM_METHOD(void) GetVoiceDetails(XAUDIO2_VOICE_DETAILS *pVoiceDetails) | ||||
{ | ||||
#if XAUDIO2_VERSION > 7 | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, (FAudioVoiceDetails*) pVoiceDetails); | ||||
#else | ||||
FAudioVoiceDetails fDetails; | ||||
FAudioVoice_GetVoiceDetails(faudio_voice, &fDetails); | ||||
pVoiceDetails->CreationFlags = fDetails.CreationFlags; | ||||
pVoiceDetails->InputChannels = fDetails.InputChannels; | ||||
pVoiceDetails->InputSampleRate = fDetails.InputSampleRate; | ||||
#endif // XAUDIO2_VERSION <= 7 | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputVoices(const XAUDIO2_VOICE_SENDS *pSendList) | ||||
{ | ||||
free_voice_sends(voice_sends); | ||||
voice_sends = unwrap_voice_sends(pSendList); | ||||
return FAudioVoice_SetOutputVoices(faudio_voice, voice_sends); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectChain(const XAUDIO2_EFFECT_CHAIN *pEffectChain) | ||||
{ | ||||
free_effect_chain(effect_chain); | ||||
effect_chain = wrap_effect_chain(pEffectChain); | ||||
return FAudioVoice_SetEffectChain(faudio_voice, effect_chain); | ||||
} | ||||
COM_METHOD(HRESULT) EnableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_EnableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) DisableEffect(UINT32 EffectIndex, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_DisableEffect(faudio_voice, EffectIndex, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetEffectState(UINT32 EffectIndex, BOOL *pEnabled) | ||||
{ | ||||
FAudioVoice_GetEffectState(faudio_voice, EffectIndex, pEnabled); | ||||
} | ||||
COM_METHOD(HRESULT) SetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
const void *pParameters, | ||||
UINT32 ParametersByteSize, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(HRESULT) GetEffectParameters( | ||||
UINT32 EffectIndex, | ||||
void *pParameters, | ||||
UINT32 ParametersByteSize | ||||
) { | ||||
return FAudioVoice_GetEffectParameters( | ||||
faudio_voice, | ||||
EffectIndex, | ||||
pParameters, | ||||
ParametersByteSize); | ||||
} | ||||
COM_METHOD(HRESULT) SetFilterParameters( | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetFilterParameters(faudio_voice, pParameters, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetFilterParameters(XAUDIO2_FILTER_PARAMETERS *pParameters) | ||||
{ | ||||
FAudioVoice_GetFilterParameters(faudio_voice, pParameters); | ||||
} | ||||
#if XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
const XAUDIO2_FILTER_PARAMETERS *pParameters, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetOutputFilterParameters( | ||||
faudio_voice, | ||||
((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice, | ||||
pParameters, | ||||
OperationSet); | ||||
} | ||||
COM_METHOD(void) GetOutputFilterParameters( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
XAUDIO2_FILTER_PARAMETERS *pParameters | ||||
) { | ||||
FAudioVoice_GetOutputFilterParameters( | ||||
faudio_voice, | ||||
((XAudio2MasteringVoiceImpl *)pDestinationVoice)->faudio_voice, | ||||
pParameters); | ||||
} | ||||
#endif // XAUDIO2_VERSION >= 4 | ||||
COM_METHOD(HRESULT) SetVolume(float Volume, UINT32 OperationSet = FAUDIO_COMMIT_NOW) | ||||
{ | ||||
return FAudioVoice_SetVolume(faudio_voice, Volume, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetVolume(float *pVolume) | ||||
{ | ||||
FAudioVoice_GetVolume(faudio_voice, pVolume); | ||||
} | ||||
COM_METHOD(HRESULT) SetChannelVolumes( | ||||
UINT32 Channels, | ||||
const float *pVolumes, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
return FAudioVoice_SetChannelVolumes(faudio_voice, Channels, pVolumes, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetChannelVolumes(UINT32 Channels, float *pVolumes) | ||||
{ | ||||
FAudioVoice_GetChannelVolumes(faudio_voice, Channels, pVolumes); | ||||
} | ||||
COM_METHOD(HRESULT) SetOutputMatrix( | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
const float *pLevelMatrix, | ||||
UINT32 OperationSet = FAUDIO_COMMIT_NOW | ||||
) { | ||||
FAudioVoice *dest = (pDestinationVoice) ? pDestinationVoice->faudio_voice : NULL; | ||||
return FAudioVoice_SetOutputMatrix( | ||||
faudio_voice, | ||||
dest, | ||||
SourceChannels, | ||||
DestinationChannels, | ||||
pLevelMatrix, | ||||
OperationSet); | ||||
} | ||||
#if XAUDIO2_VERSION >= 1 | ||||
COM_METHOD(void) GetOutputMatrix( | ||||
#else | ||||
COM_METHOD(HRESULT) GetOutputMatrix( | ||||
#endif | ||||
IXAudio2Voice *pDestinationVoice, | ||||
UINT32 SourceChannels, | ||||
UINT32 DestinationChannels, | ||||
float *pLevelMatrix | ||||
) { | ||||
FAudioVoice_GetOutputMatrix( | ||||
faudio_voice, | ||||
pDestinationVoice->faudio_voice, | ||||
SourceChannels, | ||||
DestinationChannels, | ||||
pLevelMatrix); | ||||
#if XAUDIO2_VERSION < 1 | ||||
return S_OK; | ||||
#endif // XAUDIO2_VERSION < 1 | ||||
} | ||||
COM_METHOD(void) DestroyVoice() | ||||
{ | ||||
FAudioVoice_DestroyVoice(faudio_voice); | ||||
// FIXME: in theory FAudioVoice_DestroyVoice can fail but how would we ever now ? -JS | ||||
free_voice_sends(voice_sends); | ||||
free_effect_chain(effect_chain); | ||||
delete this; | ||||
} | ||||
// IXAudio2MasteringVoice | ||||
#if XAUDIO2_VERSION >= 8 | ||||
COM_METHOD(HRESULT) GetChannelMask(uint32_t *pChannelmask) | ||||
{ | ||||
return FAudioMasteringVoice_GetChannelMask(faudio_voice, pChannelmask); | ||||
} | ||||
#endif | ||||
private: | ||||
FAudioVoiceSends *voice_sends; | ||||
FAudioEffectChain *effect_chain; | ||||
}; | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// IXAudio2 implementation | ||||
// | ||||
void* CDECL XAudio2_INTERNAL_Malloc(size_t size) | ||||
{ | ||||
return CoTaskMemAlloc(size); | ||||
} | ||||
void CDECL XAudio2_INTERNAL_Free(void* ptr) | ||||
{ | ||||
CoTaskMemFree(ptr); | ||||
} | ||||
void* CDECL XAudio2_INTERNAL_Realloc(void* ptr, size_t size) | ||||
{ | ||||
return CoTaskMemRealloc(ptr, size); | ||||
} | ||||
class XAudio2Impl : public IXAudio2 | ||||
{ | ||||
public: | ||||
XAudio2Impl() | ||||
{ | ||||
callback_list.com = NULL; | ||||
callback_list.next = NULL; | ||||
FAudioCOMConstructWithCustomAllocatorEXT( | ||||
&faudio, | ||||
XAUDIO2_VERSION, | ||||
XAudio2_INTERNAL_Malloc, | ||||
XAudio2_INTERNAL_Free, | ||||
XAudio2_INTERNAL_Realloc | ||||
); | ||||
} | ||||
XAudio2Impl(UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor) | ||||
{ | ||||
callback_list.com = NULL; | ||||
callback_list.next = NULL; | ||||
FAudioCreateWithCustomAllocatorEXT( | ||||
&faudio, | ||||
Flags, | ||||
XAudio2Processor, | ||||
XAudio2_INTERNAL_Malloc, | ||||
XAudio2_INTERNAL_Free, | ||||
XAudio2_INTERNAL_Realloc | ||||
); | ||||
} | ||||
COM_METHOD(HRESULT) QueryInterface(REFIID riid, void **ppvInterface) | ||||
{ | ||||
if (guid_equals(riid, IID_IXAudio2)) | ||||
{ | ||||
*ppvInterface = static_cast<IXAudio2 *>(this); | ||||
} | ||||
else if (guid_equals(riid, IID_IUnknown)) | ||||
{ | ||||
*ppvInterface = static_cast<IUnknown *>(this); | ||||
} | ||||
else | ||||
{ | ||||
*ppvInterface = NULL; | ||||
return E_NOINTERFACE; | ||||
} | ||||
reinterpret_cast<IUnknown *>(*ppvInterface)->AddRef(); | ||||
return S_OK; | ||||
} | ||||
COM_METHOD(ULONG) AddRef() | ||||
{ | ||||
return FAudio_AddRef(faudio); | ||||
} | ||||
COM_METHOD(ULONG) Release() | ||||
{ | ||||
ULONG refcount = FAudio_Release(faudio); | ||||
if (refcount == 0) | ||||
{ | ||||
delete this; | ||||
} | ||||
return 1; | ||||
} | ||||
#if (XAUDIO2_VERSION <= 7) | ||||
COM_METHOD(HRESULT) GetDeviceCount(UINT32 *pCount) | ||||
{ | ||||
return FAudio_GetDeviceCount(faudio, pCount); | ||||
} | ||||
COM_METHOD(HRESULT) GetDeviceDetails(UINT32 Index, XAUDIO2_DEVICE_DETAILS *pDeviceDetails) | ||||
{ | ||||
return FAudio_GetDeviceDetails(faudio, Index, pDeviceDetails); | ||||
} | ||||
COM_METHOD(HRESULT) Initialize( | ||||
UINT32 Flags = 0, | ||||
XAUDIO2_PROCESSOR XAudio2Processor = FAUDIO_DEFAULT_PROCESSOR | ||||
) { | ||||
return FAudio_Initialize(faudio, Flags, XAudio2Processor); | ||||
} | ||||
#endif // XAUDIO2_VERSION <= 7 | ||||
COM_METHOD(HRESULT) RegisterForCallbacks(IXAudio2EngineCallback *pCallback) | ||||
{ | ||||
FAudioCppEngineCallback *cb = wrap_engine_callback(pCallback); | ||||
cb->next = callback_list.next; | ||||
callback_list.next = cb; | ||||
return FAudio_RegisterForCallbacks(faudio, reinterpret_cast<FAudioEngineCallback *>(cb)); | ||||
} | ||||
COM_METHOD(void) UnregisterForCallbacks(IXAudio2EngineCallback *pCallback) | ||||
{ | ||||
FAudioCppEngineCallback *cb = find_and_remove_engine_callback(&callback_list, pCallback); | ||||
if (cb == NULL) | ||||
{ | ||||
return; | ||||
} | ||||
FAudio_UnregisterForCallbacks(faudio, reinterpret_cast<FAudioEngineCallback *>(cb)); | ||||
delete cb; | ||||
} | ||||
COM_METHOD(HRESULT) 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 | ||||
) { | ||||
*ppSourceVoice = new XAudio2SourceVoiceImpl( | ||||
faudio, pSourceFormat, Flags, MaxFrequencyRatio, pCallback, pSendList, pEffectChain); | ||||
return S_OK; | ||||
} | ||||
COM_METHOD(HRESULT) 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 | ||||
) { | ||||
*ppSubmixVoice = new XAudio2SubmixVoiceImpl( | ||||
faudio, | ||||
InputChannels, | ||||
InputSampleRate, | ||||
Flags, | ||||
ProcessingStage, | ||||
pSendList, | ||||
pEffectChain); | ||||
return S_OK; | ||||
} | ||||
#if (XAUDIO2_VERSION <= 7) | ||||
COM_METHOD(HRESULT) 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 | ||||
) { | ||||
*ppMasteringVoice = new XAudio2MasteringVoiceImpl( | ||||
faudio, InputChannels, InputSampleRate, Flags, DeviceIndex, pEffectChain); | ||||
return S_OK; | ||||
} | ||||
#else | ||||
COM_METHOD(HRESULT) 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 | ||||
) { | ||||
*ppMasteringVoice = new XAudio2MasteringVoiceImpl( | ||||
faudio, | ||||
InputChannels, | ||||
InputSampleRate, | ||||
Flags, | ||||
szDeviceId, | ||||
pEffectChain, | ||||
StreamCategory); | ||||
return S_OK; | ||||
} | ||||
#endif | ||||
COM_METHOD(HRESULT) StartEngine() | ||||
{ | ||||
return FAudio_StartEngine(faudio); | ||||
} | ||||
COM_METHOD(void) StopEngine() | ||||
{ | ||||
FAudio_StopEngine(faudio); | ||||
} | ||||
COM_METHOD(HRESULT) CommitChanges(UINT32 OperationSet) | ||||
{ | ||||
return FAudio_CommitOperationSet(faudio, OperationSet); | ||||
} | ||||
COM_METHOD(void) GetPerformanceData(XAUDIO2_PERFORMANCE_DATA *pPerfData) | ||||
{ | ||||
#if XAUDIO2_VERSION >= 3 | ||||
FAudio_GetPerformanceData(faudio, pPerfData); | ||||
#else | ||||
FAudioPerformanceData fPerfData; | ||||
FAudio_GetPerformanceData(faudio, &fPerfData); | ||||
pPerfData->AudioCyclesSinceLastQuery = fPerfData.AudioCyclesSinceLastQuery; | ||||
pPerfData->TotalCyclesSinceLastQuery = fPerfData.TotalCyclesSinceLastQuery; | ||||
pPerfData->MinimumCyclesPerQuantum = fPerfData.MinimumCyclesPerQuantum; | ||||
pPerfData->MaximumCyclesPerQuantum = fPerfData.MaximumCyclesPerQuantum; | ||||
pPerfData->MemoryUsageInBytes = fPerfData.MemoryUsageInBytes; | ||||
pPerfData->CurrentLatencyInSamples = fPerfData.CurrentLatencyInSamples; | ||||
pPerfData->GlitchesSinceEngineStarted = fPerfData.GlitchesSinceEngineStarted; | ||||
pPerfData->ActiveSourceVoiceCount = fPerfData.ActiveSourceVoiceCount; | ||||
pPerfData->TotalSourceVoiceCount = fPerfData.TotalSourceVoiceCount; | ||||
pPerfData->ActiveSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount; | ||||
pPerfData->TotalSubmixVoiceCount = fPerfData.ActiveSubmixVoiceCount; | ||||
pPerfData->ActiveXmaSourceVoices = fPerfData.ActiveXmaSourceVoices; | ||||
pPerfData->ActiveXmaStreams = fPerfData.ActiveXmaStreams; | ||||
#endif // XAUDIO2_VERSION >= 3 | ||||
} | ||||
COM_METHOD(void) | ||||
SetDebugConfiguration( | ||||
XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration, | ||||
void *pReserved = NULL | ||||
) { | ||||
FAudio_SetDebugConfiguration( | ||||
faudio, | ||||
pDebugConfiguration, | ||||
pReserved); | ||||
} | ||||
private: | ||||
FAudio *faudio; | ||||
FAudioCppEngineCallback callback_list; | ||||
}; | ||||
/////////////////////////////////////////////////////////////////////////////// | ||||
// | ||||
// Create function | ||||
// | ||||
void *CreateXAudio2Internal() | ||||
{ | ||||
return new XAudio2Impl(); | ||||
} | ||||
#if XAUDIO2_VERSION >= 8 | ||||
extern "C" FAUDIOCPP_API XAudio2Create(IXAudio2 **ppXAudio2, UINT32 Flags, XAUDIO2_PROCESSOR XAudio2Processor) | ||||
{ | ||||
// FAudio only accepts one processor | ||||
*ppXAudio2 = new XAudio2Impl(Flags, FAUDIO_DEFAULT_PROCESSOR); | ||||
return S_OK; | ||||
} | ||||
#endif // XAUDIO2_VERSION >= 8 | ||||