60 float compressedSample;
72 return compressedSample;
78 int rate,
float pregain,
float threshold,
float knee,
float ratio,
float attack,
float release,
89 int delaybufsize = rate * predelay;
98 std::fill(delaybuf, delaybuf+delaybufsize, 0.0f);
102 float linearpregain =
db2lin(pregain);
103 float linearthreshold =
db2lin(threshold);
104 float slope = 1.0f / ratio;
105 float attacksamples = rate * attack;
106 float attacksamplesinv = 1.0f / attacksamples;
107 float releasesamples = rate * release;
108 float satrelease = 0.0025f;
109 float satreleasesamplesinv = 1.0f / ((float)rate * satrelease);
110 float dry = 1.0f - wet;
113 float metergain = 1.0f;
114 float meterfalloff = 0.325f;
115 float meterrelease = 1.0f - expf(-1.0f / ((
float)rate * meterfalloff));
119 float kneedboffset = 0.0f;
120 float linearthresholdknee = 0.0f;
124 float xknee =
db2lin(threshold + knee);
126 float maxk = 10000.0f;
129 for (
int i = 0;
i < 15;
i++)
131 if (
kneeslope(xknee, k, linearthreshold) < slope) {
137 k = sqrtf(mink * maxk);
141 linearthresholdknee =
db2lin(threshold + knee);
145 float fulllevel =
compcurve(1.0f, k, slope, linearthreshold, linearthresholdknee, threshold, knee, kneedboffset);
146 float mastergain =
db2lin(postgain) * powf(1.0f / fulllevel, 0.6f);
151 float y1 = releasesamples * releasezone1;
152 float y2 = releasesamples * releasezone2;
153 float y3 = releasesamples * releasezone3;
154 float y4 = releasesamples * releasezone4;
155 float a = (-y1 + 3.0f * y2 - 3.0f * y3 + y4) / 6.0f;
156 float b = y1 - 2.5f * y2 + 2.0f * y3 - 0.5f * y4;
157 float c = (-11.0f * y1 + 18.0f * y2 - 9.0f * y3 + 2.0f * y4) / 6.0f;
161 this->metergain = 1.0f;
162 this->meterrelease = meterrelease;
163 this->threshold = threshold;
166 this->linearpregain = linearpregain;
167 this->linearthreshold = linearthreshold;
169 this->attacksamplesinv = attacksamplesinv;
170 this->satreleasesamplesinv = satreleasesamplesinv;
173 this->kneedboffset = kneedboffset;
174 this->linearthresholdknee = linearthresholdknee;
175 this->mastergain = mastergain;
180 this->detectoravg = 0.0f;
181 this->compgain = 1.0f;
182 this->maxcompdiffdb = -1.0f;
183 this->delaybufsize = delaybufsize;
184 this->delaywritepos = 0;
185 this->delayreadpos = delaybufsize > 1 ? 1 : 0;
194 float knee = state->
knee;
197 float slope = state->
slope;
200 float wet = state->
wet;
201 float dry = state->
dry;
219 int chunks = size / samplesperchunk;
220 float ang90 = (float)
M_PI * 0.5f;
221 float ang90inv = 2.0f / (float)
M_PI;
225 for (
int ch = 0; ch < chunks; ch++)
227 detectoravg =
fixf(detectoravg, 1.0f);
228 float desiredgain = detectoravg;
229 float scaleddesiredgain = asinf(desiredgain) * ang90inv;
230 float compdiffdb =
lin2db(compgain / scaleddesiredgain);
234 if (compdiffdb < 0.0f)
236 compdiffdb =
fixf(compdiffdb, -1.0f);
240 float x = (
clampf(compdiffdb, -12.0f, 0.0f) + 12.0f) * 0.25f;
242 enveloperate =
db2lin(spacingdb / releasesamples);
246 compdiffdb =
fixf(compdiffdb, 1.0f);
247 if (maxcompdiffdb == -1 || maxcompdiffdb < compdiffdb)
248 maxcompdiffdb = compdiffdb;
249 float attenuate = maxcompdiffdb;
250 if (attenuate < 0.5f)
252 enveloperate = 1.0f - powf(0.25f / attenuate, attacksamplesinv);
256 for (
int chi = 0; chi < samplesperchunk; chi++, samplepos++,
257 delayreadpos = (delayreadpos + 1) % delaybufsize,
258 delaywritepos = (delaywritepos + 1) % delaybufsize)
261 float inputL = input[samplepos] * linearpregain;
262 delaybuf[delaywritepos] = inputL;
264 inputL =
absf(inputL);
265 float inputmax = inputL;
268 if (inputmax < 0.0001f)
272 float inputcomp =
compcurve(inputmax, k, slope, linearthreshold,
273 linearthresholdknee, threshold, knee, kneedboffset);
274 attenuation = inputcomp / inputmax;
278 if (attenuation > detectoravg)
280 float attenuationdb = -
lin2db(attenuation);
281 if (attenuationdb < 2.0f)
282 attenuationdb = 2.0f;
283 float dbpersample = attenuationdb * satreleasesamplesinv;
284 rate =
db2lin(dbpersample) - 1.0f;
289 detectoravg += (attenuation - detectoravg) * rate;
290 if (detectoravg > 1.0f)
292 detectoravg =
fixf(detectoravg, 1.0f);
294 if (enveloperate < 1)
295 compgain += (scaleddesiredgain - compgain) * enveloperate;
298 compgain *= enveloperate;
304 float premixgain = sinf(ang90 * compgain);
305 float gain = dry + wet * mastergain * premixgain;
308 float premixgaindb =
lin2db(premixgain);
309 if (premixgaindb < metergain)
310 metergain = premixgaindb;
312 metergain += (premixgaindb - metergain) * meterrelease;
315 output[samplepos] = delaybuf[delayreadpos] * gain;
#define AUDIOCOMPRESSORSND_SF_COMPRESSOR_MAXDELAY
#define AUDIOCOMPRESSORSND_SF_COMPRESSOR_SPACINGDB
static float kneecurve(float x, float k, float linearthreshold)
#define AUDIOCOMPRESSORSND_SF_COMPRESSOR_CHUNKSIZE
CompressorState m_compressorState
static float absf(float v)
float satreleasesamplesinv
static float fixf(float v, float def)
void sf_advancecomp(int rate, float pregain, float threshold, float knee, float ratio, float attack, float release, float predelay, float releasezone1, float releasezone2, float releasezone3, float releasezone4, float postgain, float wet)
static float adaptivereleasecurve(float x, float a, float b, float c, float d)
static float compcurve(float x, float k, float slope, float linearthreshold, float linearthresholdknee, float threshold, float knee, float kneedboffset)
float m_storageBuffer[AUDIOCOMPRESSORSND_SF_COMPRESSOR_CHUNKSIZE]
static float lin2db(float lin)
float delaybuf[AUDIOCOMPRESSORSND_SF_COMPRESSOR_MAXDELAY]
static float kneeslope(float x, float k, float linearthreshold)
static void sf_compressor_process(CompressorState *state, int size, float *input, float *output)
static float clampf(float v, float min, float max)
float m_processedBuffer[AUDIOCOMPRESSORSND_SF_COMPRESSOR_CHUNKSIZE]
float linearthresholdknee
static float db2lin(float db)
float compress(float sample)
#define AUDIOCOMPRESSORSND_SF_COMPRESSOR_SPU