#pragma once #include "buffer.h" #include "delayline.h" #include struct SpeexResamplerState_; typedef struct SpeexResamplerState_ SpeexResamplerState; class Limiter { constexpr static int upsampleFactor = 2; constexpr static int resampleQuality = 7; constexpr static int workBufferSize = 4096; constexpr static int chunkSize = workBufferSize / upsampleFactor; const int sampleRate; const int channelCount; float attackSeconds; float releaseSeconds; float attackAlpha; float releaseAlpha; int lookaheadFrames; int delayFrames; // adjustable parameters float desiredAttackSeconds; float desiredReleaseSeconds; float desiredLookaheadSeconds; float preGainDb; bool bypass; float stereoLink; SpeexResamplerState *upsampler, *downsampler; BufferF32 workBuffer; std::unique_ptr lookaheadDelayLine; std::vector channelCurrentGainEnvelope; float linkedCurrentGainEnvelope; BufferF32 limiterWorkBuffer; std::vector deque; BufferF32 slidingWindowWorkBuffer; void updateParameters(); public: Limiter(int channelCount, int sampleRate, float lookaheadSeconds, float attackSeconds, float releaseSeconds, float preGainDb, bool bypass, float stereoLink); ~Limiter(); void setParameters(float lookaheadSeconds, float attackSeconds, float releaseSeconds, float preGainDb, bool bypass, float stereoLink); void process(BufferF32 buf); int getDelayFrames() const { return delayFrames; } };