Files
UnrealEngine/Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Private/MetasoundTrigger.cpp
2025-05-18 13:04:45 +08:00

159 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MetasoundTrigger.h"
#include "MetasoundDataReference.h"
#include "MetasoundDataTypeRegistrationMacro.h"
#include "MetasoundOperatorSettings.h"
namespace Metasound
{
FTrigger::FTrigger(const FOperatorSettings& InSettings, bool bShouldTrigger)
: NumFramesPerBlock(InSettings.GetNumFramesPerBlock())
, SampleRate(InSettings.GetSampleRate())
{
if (bShouldTrigger)
{
TriggerFrame(0);
}
}
FTrigger::FTrigger(const FOperatorSettings& InSettings, int32 InFrameToTrigger)
: NumFramesPerBlock(InSettings.GetNumFramesPerBlock())
, SampleRate(InSettings.GetSampleRate())
{
TriggerFrame(InFrameToTrigger);
}
FTrigger::FTrigger(const FOperatorSettings& InSettings)
: FTrigger(InSettings, false)
{}
void FTrigger::AssignRawParameter(const void* ParamPackPayload)
{
// We don't even need to check the payload. If the parameter pack contained
// a Trigger bool, it must be true. There is no concept of "un-trigger" :-)
TriggerFrame(0);
}
void FTrigger::TriggerFrame(int32 InFrameToTrigger)
{
// Insert trigger frame index into sorted triggered frames
TriggeredFrames.Insert(InFrameToTrigger, Algo::LowerBound(TriggeredFrames, InFrameToTrigger));
if (InFrameToTrigger < NumFramesPerBlock)
{
UpdateLastTriggerIndexInBlock();
}
bHasTrigger = true;
}
void FTrigger::AdvanceBlock()
{
Advance(NumFramesPerBlock);
}
void FTrigger::Advance(int32 InNumFrames)
{
if (bHasTrigger)
{
const int32 NumToRemove = Algo::LowerBound(TriggeredFrames, InNumFrames);
if (NumToRemove)
{
TriggeredFrames.RemoveAt(0, NumToRemove, EAllowShrinking::No);
}
const int32 Num = TriggeredFrames.Num();
if (Num > 0)
{
for (int32 i = 0; i < Num; i++)
{
TriggeredFrames[i] -= InNumFrames;
}
}
else
{
bHasTrigger = false;
}
UpdateLastTriggerIndexInBlock();
}
}
int32 FTrigger::Num() const
{
return TriggeredFrames.Num();
}
int32 FTrigger::NumTriggeredInBlock() const
{
return LastTriggerIndexInBlock;
}
int32 FTrigger::operator[](int32 InTriggerIndex) const
{
return TriggeredFrames[InTriggerIndex];
}
int32 FTrigger::First() const
{
return TriggeredFrames.IsEmpty() ? INDEX_NONE : TriggeredFrames[0];
}
int32 FTrigger::Last() const
{
return TriggeredFrames.IsEmpty() ? INDEX_NONE : TriggeredFrames.Last();
}
bool FTrigger::IsTriggered() const
{
return bHasTrigger;
}
bool FTrigger::IsTriggeredInBlock() const
{
return LastTriggerIndexInBlock > 0;
}
FTrigger::operator bool() const
{
return IsTriggeredInBlock();
}
void FTrigger::Reset()
{
TriggeredFrames.Reset();
LastTriggerIndexInBlock = 0;
bHasTrigger = false;
}
void FTrigger::RemoveAfter(int32 InStartingFrame)
{
if (InStartingFrame <= 0)
{
Reset();
}
else if (TriggeredFrames.Num() > 0)
{
// Algo::UpperBound Returns index of first element > InStartingFrame
int32 BeginningIndex = Algo::UpperBound(TriggeredFrames, InStartingFrame);
int32 NumToRemove = TriggeredFrames.Num() - BeginningIndex;
if (NumToRemove > 0)
{
TriggeredFrames.RemoveAt(BeginningIndex, NumToRemove);
UpdateLastTriggerIndexInBlock();
bHasTrigger = TriggeredFrames.Num() > 0;
}
}
}
void FTrigger::UpdateLastTriggerIndexInBlock()
{
LastTriggerIndexInBlock = Algo::LowerBound(TriggeredFrames, NumFramesPerBlock);
}
}