#pragma once #include #include #include class AudioCompressor { public: struct Config { int sampleRate = 48000; int channels = 1; int blockDurationMs = 20; int lookbackMs = 200; int lookaheadMs = 100; float maxGainDb = 30.0f; float riseRatePer500ms = 2.0f; float targetLevel = 0.25f; }; void configure(const Config& cfg); void reset(); void setEnabled(bool enabled) { m_enabled = enabled; } bool isEnabled() const { return m_enabled; } void push(const int16_t* samples, size_t count); const std::vector& outputBuffer() const { return m_output; } bool hasPending() const { return !m_pending.empty() || !m_accumulator.empty(); } void flush(); private: Config m_cfg; bool m_enabled = true; struct BlockLevel { float level; }; std::deque m_blockLevels; struct PendingBlock { std::vector samples; size_t levelIndex; }; std::deque m_pending; std::vector m_accumulator; std::vector m_output; int m_blockSamples = 960; int m_lookbackBlocks = 10; int m_lookaheadBlocks = 5; float m_riseFactorPerBlock = 1.0f; float m_maxGain = 31.62f; float m_gainSmoothed = 1.0f; int m_dbgCounter = 0; float computeBlockLevel(const int16_t* samples, size_t count) const; void processPendingBlock(); };