102 lines
2.5 KiB
C++

#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<void*> Buffer;
uint16 MaxLevel;
};
struct FWaveformBuffer
{
TArray<int16> Buffer;
void* HiResBuffer;
TArray<int8> RMSBuffer;
};
class FWaveformRenderData
{
public:
explicit FWaveformRenderData(int32 BlockSize)
: BlockSize(BlockSize)
{
}
virtual ~FWaveformRenderData() = default;
virtual void Generate(const TArray<TArray64<float>>& 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<const FSamplePeak> 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<FSamplePeak> 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<TArray<FSamplePeak>> Buffer;
const int32 BlockSize; // 每一个块包含多少个Frame
};
class FWaveform
{
public:
FWaveform(int32 LevelNum, int32 MaxBlockSize = 128 * 128);
~FWaveform();
void UpdatePeak(const TArray<TArray64<float>>& SampleBuffer);
int32 GetMemSize() const
{
int32 Size = 0;
for (int i = 0; i < RenderData.Num(); ++i)
Size += RenderData[i]->GetMemSize();
return Size;
}
TArrayView<const FSamplePeak> 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<FWaveformRenderData*> RenderData;
};