142 lines
3.9 KiB (Stored with Git LFS)
C++
142 lines
3.9 KiB (Stored with Git LFS)
C++
// Copyright (c), Firelight Technologies Pty, Ltd. 2024-2024.
|
|
|
|
#include "FMODAudioLinkSynchronizer.h"
|
|
#include "fmod_studio.hpp"
|
|
#include "FMODStudioModule.h"
|
|
#include "FMODAudioLinkLog.h"
|
|
|
|
#include "AudioDeviceManager.h"
|
|
|
|
FMOD_RESULT F_CALLBACK MixCallback(FMOD_SYSTEM* system, FMOD_SYSTEM_CALLBACK_TYPE type, void* commanddata1, void* commanddata2, void* userdata)
|
|
{
|
|
FFMODAudioLinkSynchronizer *Synchro = static_cast<FFMODAudioLinkSynchronizer*>(userdata);
|
|
if (Synchro)
|
|
{
|
|
FMOD::System *CoreSystem = (FMOD::System*)system;
|
|
|
|
FMOD::ChannelGroup *MasterGroup = NULL;
|
|
CoreSystem->getMasterChannelGroup(&MasterGroup);
|
|
uint64 dspClock = 0;
|
|
MasterGroup->getDSPClock(&dspClock, 0);
|
|
|
|
switch (type)
|
|
{
|
|
case FMOD_SYSTEM_CALLBACK_POSTMIX:
|
|
Synchro->ExecuteEndRender(dspClock);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return FMOD_OK;
|
|
}
|
|
|
|
FFMODAudioLinkSynchronizer::FFMODAudioLinkSynchronizer()
|
|
{
|
|
Bind();
|
|
}
|
|
|
|
FFMODAudioLinkSynchronizer::~FFMODAudioLinkSynchronizer()
|
|
{
|
|
Unbind();
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::ExecuteEndRender(uint64 dspClock)
|
|
{
|
|
FScopeLock Lock(&CallbackLock);
|
|
FOnRenderParams Params;
|
|
Params.BufferTickID = dspClock;
|
|
Params.NumFrames = dspBufferSize;
|
|
OnEndRender.Broadcast(Params);
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::ExecuteOpenStream()
|
|
{
|
|
UE_LOG(LogFMODAudioLink, Verbose, TEXT("FFMODAudioLinkSynchronizer::ExecuteOpenStream: Opening stream between Unreal and FMOD."));
|
|
|
|
int samplerate = 0, numchannels = 0;
|
|
FMOD_SPEAKERMODE speakerMode;
|
|
CoreSystem->getDSPBufferSize(&dspBufferSize, 0);
|
|
CoreSystem->getSoftwareFormat(&samplerate, &speakerMode, 0);
|
|
CoreSystem->getSpeakerModeChannels(speakerMode, &numchannels);
|
|
|
|
FOnOpenStreamParams Params;
|
|
Params.NumChannels = numchannels;
|
|
Params.SampleRate = samplerate;
|
|
Params.NumFrames = dspBufferSize;
|
|
Params.Name = TEXT("AudioLink for FMOD");
|
|
OnOpenStream.Broadcast(Params);
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::ExecuteCloseStream()
|
|
{
|
|
UE_LOG(LogFMODAudioLink, Verbose, TEXT("FFMODAudioLinkSynchronizer::ExecuteCloseStream: Closing stream between Unreal and FMOD."));
|
|
|
|
OnCloseStream.Broadcast();
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::ExecuteSuspend()
|
|
{
|
|
OnSuspend.Broadcast();
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::ExecuteResume()
|
|
{
|
|
OnResume.Broadcast();
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::Bind()
|
|
{
|
|
if (UNLIKELY(bIsBound))
|
|
{
|
|
UE_LOG(LogFMODAudioLink, Error, TEXT("FFMODAudioLinkSynchronizer::Bind: Already bound."));
|
|
return;
|
|
}
|
|
|
|
if (UNLIKELY(!IFMODStudioModule::Get().IsAvailable()))
|
|
{
|
|
UE_LOG(LogFMODAudioLink, Error, TEXT("FFMODAduioLinkSynchronizer::Bind: FMODStudioModule not available."));
|
|
return;
|
|
}
|
|
|
|
auto* StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime);
|
|
if (!StudioSystem)
|
|
{
|
|
StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Auditioning);
|
|
}
|
|
if (UNLIKELY(!StudioSystem))
|
|
{
|
|
UE_LOG(LogFMODAudioLink, Error, TEXT("FFMODAudioLinkSynchronizer::ExecuteOpenStream: No Studio System."));
|
|
return;
|
|
}
|
|
|
|
StudioSystem->getCoreSystem(&CoreSystem);
|
|
|
|
UE_LOG(LogFMODAudioLink, Verbose, TEXT("FFMODAudioLinkSynchronizer::Bind: Binding System Callbacks."));
|
|
|
|
CoreSystem->setUserData(this);
|
|
CoreSystem->setCallback(MixCallback, FMOD_SYSTEM_CALLBACK_POSTMIX);
|
|
|
|
ExecuteOpenStream();
|
|
|
|
bIsBound = true;
|
|
}
|
|
|
|
void FFMODAudioLinkSynchronizer::Unbind()
|
|
{
|
|
if (UNLIKELY(!bIsBound))
|
|
{
|
|
return;
|
|
}
|
|
if (UNLIKELY(!CoreSystem))
|
|
{
|
|
return;
|
|
}
|
|
|
|
UE_LOG(LogFMODAudioLink, Verbose, TEXT("FFMODAudioLinkSynchronizer::Bind: Unbinding."));
|
|
CoreSystem->setCallback(NULL, 0);
|
|
bIsBound = false;
|
|
|
|
ExecuteCloseStream();
|
|
}
|