#include "PeakFile.h" #include "Async.h" #include "PluginHost/Sampler.h" #define MID_TO_LOW (16 * 16) DEFINE_LOG_CATEGORY(LogPeakFile); TArray> GenPeakData(const TArray>& Data, int32 BlockSize) { TArray> Out; Out.SetNum(Data.Num()); for (int64 Channel = 0; Channel < Data.Num(); ++Channel) { const uint64 SourceNum = Data[Channel].Num(); uint64 BlockNum = SourceNum / BlockSize; BlockNum += SourceNum % BlockSize ? 1 : 0; Out[Channel].SetNum(BlockNum); uint64 Index = 0; for (uint64 j = 0; j < BlockNum; j++) { float Max = FLT_MIN_EXP; float Min = FLT_MAX; for (uint64 S = 0; S < BlockSize; ++S) { if (Index >= SourceNum) break; const float& Sample = Data[Channel][Index]; if (Max < Sample) Max = Sample; if (Min > Sample) Min = Sample; ++Index; } Out[Channel][j].Max = Max; Out[Channel][j].Min = Min; } } return Out; } void FWaveformRenderData::Generate(const TArray>& Data) { Buffer = GenPeakData(Data, BlockSize); } FWaveform::FWaveform(int32 LevelNum, int32 MaxBlockSize) { RenderData.SetNum(LevelNum); int32 BeginBlock = MaxBlockSize; for (int i = 0; i < LevelNum; ++i) { RenderData[i] = new FWaveformRenderData(BeginBlock); BeginBlock /= 4; } } FWaveform::~FWaveform() { for (int i = 0; i < RenderData.Num(); ++i) delete RenderData[i]; } void FWaveform::UpdatePeak(const TArray>& SampleBuffer) { Processing = true; Async(EAsyncExecution::TaskGraph, [this, &SampleBuffer]() { for (int i = 0; i < RenderData.Num(); ++i) RenderData[i]->Generate(SampleBuffer); const float MemSize = GetMemSize(); UE_LOG(LogPeakFile, Log, TEXT("Waveform MemSize: %f MB"), MemSize / 1024 / 1024); // 创建一个主线程TaskGraph任务, 用于通知UI线程更新 Async(EAsyncExecution::TaskGraphMainThread, [this]() { OnPostUpdatePeak.Broadcast(); }); Processing = false; }); }