Files
2026-05-04 14:32:29 +10:00

72 lines
1.9 KiB
C++

#pragma once
#include <array>
#include <cstdint>
#include <deque>
#include <mutex>
#include <vector>
constexpr unsigned kAudioSampleRate = 48000;
constexpr unsigned kAudioChannelCount = 2;
constexpr unsigned kAudioTextureWidth = 64;
constexpr unsigned kAudioTextureHeight = 2;
struct AudioFrameBlock
{
std::vector<int32_t> interleavedSamples;
std::size_t frameCount() const
{
return interleavedSamples.size() / kAudioChannelCount;
}
};
struct AudioAnalysisSnapshot
{
std::array<float, 2> rms = { 0.0f, 0.0f };
std::array<float, 2> peak = { 0.0f, 0.0f };
float monoRms = 0.0f;
float monoPeak = 0.0f;
std::array<float, 4> bands = { 0.0f, 0.0f, 0.0f, 0.0f };
std::array<float, kAudioTextureWidth * kAudioTextureHeight * 4> texture = {};
};
struct AudioStatusSnapshot
{
bool enabled = false;
unsigned bufferedSampleFrames = 0;
uint64_t underrunCount = 0;
AudioAnalysisSnapshot analysis;
};
class AudioDelayBuffer
{
public:
void Reset(unsigned delaySampleFrames);
void PushInterleaved(const int32_t* samples, std::size_t sampleFrameCount);
AudioFrameBlock Pop(std::size_t sampleFrameCount, bool& underrun);
unsigned BufferedSampleFrames() const;
uint64_t UnderrunCount() const;
private:
mutable std::mutex mMutex;
std::deque<int32_t> mSamples;
uint64_t mUnderrunCount = 0;
};
class AudioAnalyzer
{
public:
void Reset();
AudioAnalysisSnapshot Analyze(const AudioFrameBlock& block);
const AudioAnalysisSnapshot& Current() const { return mCurrent; }
private:
std::deque<float> mMonoHistory;
std::array<float, 4> mSmoothedBands = { 0.0f, 0.0f, 0.0f, 0.0f };
AudioAnalysisSnapshot mCurrent;
};
uint64_t AudioSampleTimeForVideoFrame(uint64_t videoFrameIndex, uint64_t frameDuration, uint64_t frameTimescale, uint64_t audioSampleRate = kAudioSampleRate);
unsigned AudioSamplesForVideoFrame(uint64_t videoFrameIndex, uint64_t frameDuration, uint64_t frameTimescale, uint64_t audioSampleRate = kAudioSampleRate);