Lost_Edge/Plugins/FMODStudio/Source/FMODAudioLink/Private/FMODAudioLinkSourcePushed.cpp

116 lines
5.1 KiB (Stored with Git LFS)
C++

// Copyright (c), Firelight Technologies Pty, Ltd. 2024-2024.
#include "FMODAudioLinkSourcePushed.h"
#include "FMODAudioLinkSettings.h"
#include "FMODAudioLinkInputClient.h"
#include "FMODAudioLinkLog.h"
#include "FMODEvent.h"
FFMODAudioLinkSourcePushed::FFMODAudioLinkSourcePushed(const IAudioLinkFactory::FAudioLinkSourcePushedCreateArgs& InArgs, IAudioLinkFactory* InFactory)
: CreateArgs(InArgs)
{
const FFMODAudioLinkSettingsProxy* FMODSettingsSP = static_cast<FFMODAudioLinkSettingsProxy*>(InArgs.Settings.Get());
IAudioLinkFactory::FPushedBufferListenerCreateParams Params;
Params.SizeOfBufferInFrames = InArgs.NumFramesPerBuffer;
Params.bShouldZeroBuffer = FMODSettingsSP->ShouldClearBufferOnReceipt();
ProducerSP = InFactory->CreatePushableBufferListener(Params);
ConsumerSP = MakeShared<FFMODAudioLinkInputClient, ESPMode::ThreadSafe>(ProducerSP, InArgs.Settings, InArgs.OwnerName);
// Unreal uses samples for 'Channels x samples' and frames for 'samples'
int32 BufferSizeInChannelSamples = FMODSettingsSP->GetReceivingBufferSizeInFrames() * InArgs.NumChannels;
int32 ReserveSizeInChannelSamples = (float)BufferSizeInChannelSamples * FMODSettingsSP->GetProducerConsumerBufferRatio();
int32 SilenceToAddToFirstBuffer = FMath::Min((float)BufferSizeInChannelSamples * FMODSettingsSP->GetInitialSilenceFillRatio(), ReserveSizeInChannelSamples);
// Set circular buffer ahead of first buffer.
ProducerSP->Reserve(ReserveSizeInChannelSamples, SilenceToAddToFirstBuffer);
UE_LOG(LogFMODAudioLink, Verbose,
TEXT("FFMODAudioLinkSourcePushed::Ctor() Name=%s, Producer=0x%p, Consumer=0x%p, p2c%%=%2.2f, PlayEvent=%s, TotalFramesForSource=%d, This=0x%p"),
*InArgs.OwnerName.GetPlainNameString(), ProducerSP.Get(),
ConsumerSP.Get(), FMODSettingsSP->GetProducerConsumerBufferRatio(), *FMODSettingsSP->GetLinkEvent()->GetName(),
CreateArgs.TotalNumFramesInSource, this);
}
FFMODAudioLinkSourcePushed::~FFMODAudioLinkSourcePushed()
{
UE_LOG(LogFMODAudioLink, Verbose,
TEXT("FFMODAudioLinkSourcePushed::Dtor() Name=%s, Producer=0x%p, Consumer=0x%p, RecievedFrames=%d/%d, This=0x%p"),
*CreateArgs.OwnerName.GetPlainNameString(), ProducerSP.Get(), ConsumerSP.Get(), NumFramesReceivedSoFar,
CreateArgs.TotalNumFramesInSource,this);
if (ConsumerSP.IsValid())
{
ConsumerSP->Stop();
}
}
void FFMODAudioLinkSourcePushed::OnNewBuffer(const FOnNewBufferParams& InArgs)
{
UE_LOG(LogFMODAudioLink, VeryVerbose,
TEXT("FFMODAudioLinkSourcePushed::OnNewBuffer() Name=%s, Producer=0x%p, Consumer=0x%p, SourceID=%d, RecievedFrames=%d/%d, This=0x%p"),
*CreateArgs.OwnerName.GetPlainNameString(), ProducerSP.Get(), ConsumerSP.Get(), SourceId, NumFramesReceivedSoFar,
CreateArgs.TotalNumFramesInSource, this);
NumFramesReceivedSoFar += CreateArgs.NumFramesPerBuffer;
if (SourceId == INDEX_NONE)
{
IBufferedAudioOutput::FBufferFormat AudioFormat = {};
AudioFormat.NumChannels = CreateArgs.NumChannels;
AudioFormat.NumSamplesPerBlock = CreateArgs.NumFramesPerBuffer;
AudioFormat.NumSamplesPerSec = CreateArgs.SampleRate;
ConsumerSP->SetFormat(&AudioFormat);
SourceId = InArgs.SourceId;
ProducerSP->Start(nullptr);
ConsumerSP->Start();
}
check(SourceId == InArgs.SourceId);
IPushableAudioOutput* Pushable = ProducerSP->GetPushableInterface();
if (ensure(Pushable))
{
IPushableAudioOutput::FOnNewBufferParams Params;
Params.AudioData = InArgs.Buffer.GetData();
Params.NumSamples = InArgs.Buffer.Num();
Params.Id = InArgs.SourceId;
Params.NumChannels = CreateArgs.NumChannels;
Params.SampleRate = CreateArgs.SampleRate;
Pushable->PushNewBuffer(Params);
}
}
void FFMODAudioLinkSourcePushed::OnSourceDone(const int32 InSourceId)
{
UE_LOG(LogFMODAudioLink, Verbose,
TEXT("FFMODAudioLinkSourcePushed::OnSourceDone() Name=%s, Producer=0x%p, Consumer=0x%p, RecievedFrames=%d/%d, This=0x%p"),
*CreateArgs.OwnerName.GetPlainNameString(), ProducerSP.Get(), ConsumerSP.Get(), NumFramesReceivedSoFar,
CreateArgs.TotalNumFramesInSource, this);
check(SourceId == InSourceId);
IPushableAudioOutput* Pushable = ProducerSP->GetPushableInterface();
if (ensure(Pushable))
{
Pushable->LastBuffer(SourceId);
}
SourceId = INDEX_NONE;
}
void FFMODAudioLinkSourcePushed::OnSourceReleased(const int32 InSourceId)
{
UE_LOG(LogFMODAudioLink, Verbose,
TEXT("FFMODAudioLinkSourcePushed::OnSourceReleased() Name=%s, Producer=0x%p, Consumer=0x%p, RecievedFrames=%d/%d, This=0x%p"),
*CreateArgs.OwnerName.GetPlainNameString(), ProducerSP.Get(), ConsumerSP.Get(), NumFramesReceivedSoFar,
CreateArgs.TotalNumFramesInSource,this);
}
// Called by the AudioThread, not the AudioRenderThread
void FFMODAudioLinkSourcePushed::OnUpdateWorldState(const FOnUpdateWorldStateParams& InParams)
{
FFMODAudioLinkInputClient::FWorldState UpdateParams;
UpdateParams.WorldTransform = InParams.WorldTransform;
ConsumerSP->UpdateWorldState(UpdateParams);
}