diff --git a/filter/gain_control.c b/filter/gain_control.c index 40d7e16..6dd36c7 100644 --- a/filter/gain_control.c +++ b/filter/gain_control.c @@ -1,37 +1,35 @@ #include "gain_control.h" void initAGC(AGC* agc, int sampleRate, float targetLevel, float minGain, float maxGain, float attackTime, float releaseTime) { - agc->sampleRate = sampleRate; - agc->targetLevel = targetLevel; - agc->minGain = minGain; - agc->maxGain = maxGain; - agc->attackTime = attackTime; - agc->releaseTime = releaseTime; + agc->targetLevel = targetLevel; + agc->minGain = minGain; + agc->maxGain = maxGain; - agc->attackCoef = expf(-1.0f / (sampleRate * attackTime)); - agc->releaseCoef = expf(-1.0f / (sampleRate * releaseTime)); + agc->attackCoef = expf(-1.0f / (sampleRate * attackTime)); + agc->releaseCoef = expf(-1.0f / (sampleRate * releaseTime)); + agc->rmsAlpha = expf(-1.0f / (sampleRate * 0.025f)); + agc->rmsBeta = 1.0f - agc->rmsAlpha; - agc->currentGain = 1.0f; - agc->currentLevel = 0.0f; - - agc->rms_buffer = 0.0f; - agc->rmsAlpha = expf(-1.0f / (sampleRate * 0.025f)); + agc->currentGain = 1.0f; + agc->currentLevel = 0.0f; } float process_agc(AGC* agc, float sidechain) { - float x2 = sidechain * sidechain; + const float signalPower = sidechain * sidechain; - agc->rms_buffer = agc->rmsAlpha * agc->rms_buffer + (1.0f - agc->rmsAlpha) * x2; - const float instantLevel = sqrtf(agc->rms_buffer); - - const float levelAlpha = (instantLevel > agc->currentLevel) ? agc->attackCoef : agc->releaseCoef; - agc->currentLevel = levelAlpha * agc->currentLevel + (1.0f - levelAlpha) * instantLevel; + agc->rmsBuffer = agc->rmsAlpha * agc->rmsBuffer + agc->rmsBeta * signalPower; + + const float rmsLevel = sqrtf(agc->rmsBuffer); + + const float levelAlpha = (rmsLevel > agc->currentLevel) ? agc->attackCoef : agc->releaseCoef; + agc->currentLevel = levelAlpha * agc->currentLevel + (1.0f - levelAlpha) * rmsLevel; - float desiredGain = agc->targetLevel / (agc->currentLevel + 1e-10f); - desiredGain = fminf(fmaxf(desiredGain, agc->minGain), agc->maxGain); + float desiredGain = agc->targetLevel / (agc->currentLevel + 1e-9f); - const float gainAlpha = (desiredGain > agc->currentGain) ? agc->attackCoef : agc->releaseCoef; - agc->currentGain = gainAlpha * agc->currentGain + (1.0f - gainAlpha) * desiredGain; + desiredGain = fminf(fmaxf(desiredGain, agc->minGain), agc->maxGain); - return agc->currentGain; + const float gainAlpha = (desiredGain < agc->currentGain) ? agc->attackCoef : agc->releaseCoef; + agc->currentGain = gainAlpha * agc->currentGain + (1.0f - gainAlpha) * desiredGain; + + return agc->currentGain; } \ No newline at end of file diff --git a/filter/gain_control.h b/filter/gain_control.h index d6a7b0c..63f017c 100644 --- a/filter/gain_control.h +++ b/filter/gain_control.h @@ -15,8 +15,9 @@ typedef struct { float attackCoef; float releaseCoef; - float rms_buffer; + float rmsBuffer; float rmsAlpha; + float rmsBeta; } AGC; void initAGC(AGC* agc, int sampleRate, float targetLevel, float minGain, float maxGain, float attackTime, float releaseTime);