Skip to content

Instantly share code, notes, and snippets.

@kode54
Created May 13, 2023 08:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kode54/2a718312193a532e349226de23c13041 to your computer and use it in GitHub Desktop.
Save kode54/2a718312193a532e349226de23c13041 to your computer and use it in GitHub Desktop.
Audio Soft Limiter
#include <math.h>
#include <float.h>
static inline float f_max(float v1,float v2)
{
return v1>v2 ? v1 : v2;
}
static const float limiter_max = (float)0.9999;
enum
{
bufPow=8,
bufLength=1<<bufPow,
bufMax = bufLength - 1,
};
class limiter
{
int bufPos;
float backbuffer[bufLength];
float buffer[bufLength*2];
float gain,minGainLP;
bool active;
public:
limiter()
{
bufPos = 0;
gain = 1.0f,
minGainLP = 1.0f;
active = false;
}
float process_sample(float in)
{
float max,out;
float val = (float)fabs(in);
if (val > limiter_max)
{
if (!active) memset(buffer,0,sizeof(buffer));
active = true;
}
{
if (active)
{
int offset = bufPos, level = bufPow;
do
{
float * ptr = buffer + bufLength*2 - (2<<level);
ptr[offset]=val;
val = f_max(val,ptr[offset^1]);
offset>>=1;
level--;
} while(level>0);
max = val;
if (max<=limiter_max) active = false;
}
backbuffer[bufPos] = in;
bufPos = (bufPos+1)&bufMax;
out = backbuffer[bufPos];
}
// attenute when getting close to the point of clipping
float minGain;
if(active)
minGain = limiter_max/max;
else
minGain = limiter_max;
// Low-pass filter of the control signal
minGainLP = 0.9f*minGainLP + 0.1f * minGain;
// choose the lesser of these two control signals
gain = 0.001f + 0.999f*gain;
if (minGainLP<gain) gain = minGainLP;
if (fabs(out*gain)>limiter_max) gain = (float)(limiter_max/fabs(out));
return out * gain;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment