#pragma once #include "CoreMinimal.h" class FSampler; struct FSamplePeak { float Min = 0; float Max = 0; void operator+=(const FSamplePeak& Other) { if (Min > Other.Min) Min = Other.Min; if (Max < Other.Max) Max = Other.Max; } }; class FPeakBlock { public: uint16 BlockNum; uint16 Size; uint16 Res; uint16 Resolution; TArray Buffer; uint16 MaxLevel; }; struct FWaveformBuffer { TArray Buffer; void* HiResBuffer; TArray RMSBuffer; }; class FWaveformRenderData { public: explicit FWaveformRenderData(int32 BlockSize) : BlockSize(BlockSize) { } virtual ~FWaveformRenderData() = default; virtual void Generate(const TArray>& Data); int32 GetMemSize() const { int32 Size = 0; for (const auto& Array : Buffer) { Size += Array.GetAllocatedSize(); } return Buffer.GetAllocatedSize() + Size; } const FSamplePeak& GetPeak(const uint16 Channel, const uint64 Frame) const { const int32 BlockIndex = Frame / BlockSize; return Buffer[Channel][BlockIndex]; } TArrayView GetPeakFromRange(const uint16 Channel, uint64 StartFrame, uint64 EndFrame) const { const int32 StartBlockIndex = StartFrame / BlockSize; int32 EndBlockIndex = EndFrame / BlockSize; EndBlockIndex = FMath::Min(EndBlockIndex, Buffer[Channel].Num() - 1); // TArray Out; // Out.SetNum(EndBlockIndex - StartBlockIndex + 1); // FMemory::Memcpy(Out.GetData(), Buffer[Channel].GetData() + StartBlockIndex, Out.Num() * sizeof(FSamplePeak)); return MakeArrayView(&Buffer[Channel][StartBlockIndex], EndBlockIndex - StartBlockIndex + 1); } TArray> Buffer; const int32 BlockSize; // 每一个块包含多少个Frame }; class FWaveform { public: FWaveform(int32 LevelNum, int32 MaxBlockSize = 128 * 128); ~FWaveform(); void UpdatePeak(const TArray>& SampleBuffer); int32 GetMemSize() const { int32 Size = 0; for (int i = 0; i < RenderData.Num(); ++i) Size += RenderData[i]->GetMemSize(); return Size; } TArrayView GetPeakFromRange(const uint16 Channel, const int32 Width, const uint64 StartFrame, const uint64 EndFrame) const { const uint64 FrameCount = EndFrame - StartFrame; const int32 BlockSize = FrameCount / Width; for (int i = 0; i < RenderData.Num(); ++i) if (RenderData[i]->BlockSize <= BlockSize) return RenderData[i]->GetPeakFromRange(Channel, StartFrame, EndFrame); return RenderData.Last()->GetPeakFromRange(Channel, StartFrame, EndFrame); } TArray RenderData; };