AUTO Make-up Gain for Compressor

Hello, everyone;
I am finishing work on a compressor that I am writing based on scientific work (Michael Massberg). The last thing left for me to do is write an implementation for automatically Make-up. I have the Massberg`s code for example and all the formulas I need, but I don’t understand what numbers need to be inserted into these formulas. If we talk about the compressor without taking into account automatic make-up, it works very well, but when it comes to the last parameter, I stop understanding what I need to do. Please, help me.

Code for one sample, only for example:

float sample_rate = 44100;
float input_gain_in_db = -5.24;
float input_gain = std::pow(10.0, input_gain_in_db / 20.0);    //res = 0.547016
float log_input_gain = std::log(input_gain );       //res = -0.603277
float threshold = -10.14;
float log_threshold = std::log(std::pow(10.0, threshold / 20.0)); //res = -1.167411
float ratio = 8.0;

float attack_time = 0.025;   //25 ms
float release_time = 0.274;  //274 ms

float alpha_attack = 1.0 - std::exp(-1.0 / (sample_rate * attack_time));  //res = 0.000907
float alpha_release = 1.0 - std::exp(-1.0 / (sample_rate * attack_time));  // res = 0.000083

//Method which calculates samples from buffer.
void DevilPumperInfinityAudioProcessor::compressorMath(AudioSampleBuffer& buffer)
{
   //Buffer is initialized & all prepare to calc. Soft Knee is absent
  
   float log_output_gian = log_threshold + (log_input_gain - log_threshold ) / ratio;    //res = -1.096894
   float log_input_level = log_input_gain - log_output_gain;  // res = 0.493617
   float log_output_level = alpha_attack * log_input_level;   //res = 0.000448

  float control_voltage = std::exp(-log_output_level);  //res = 0.999552

}

The compression has occurred. What do I need make to calculate auto-make-up gain???

Also I have this formulas from Massberg`s book. But no matter what values I checked them with, I never managed to achieve the desired result. Either the signal disappears, or goes into distortion, or no noticeable changes occur:

CVavg[n] = CVavg[n-1] + alpha_avg * (CV[n] - CVest - CVavg[n-1]);
CVmake-up = CV[n] - (CVavg[n] + CVest);

Where:
CVavg - average value of control voltage;
[n] - current sample;
[n-1] - previous sample;
alpha_avg - alpha-coefficient of average value of the time constant (not attack or release). The number is chosen empirically;
CV - current control voltage. (In code - log_output_level);
CVest - estimation of control voltage. Using for biasing the averaging filter. Calculating from: theshold * -slope / 2.0;
CVmake-up - The final value that is fed to VCA => out = input * std::exp(CVmake-up);

I don’t have the book (didn’t know there was one), I have the paper (Parameter Automation in a Dynamic Range Compressor). c_est estimates the average of the compressor’s gain c. c_dev is the average deviation of the actual gain around the estimate. You set c_est as threshold * (1 - 1 / ratio) / 2 (half the max reduction). Then c_dev is computed lowpassing the difference between c and c_est: a * c_dev[n - 1] + (1 - a) * (c[n] - c_est). a (alpha) is computed from the filter’s time constant as exp (-1 / (sampleRate * time)). The time chosen has to be slow but not excessively -they propose 2 seconds. Then your make-up gain is -(c_dev[n] + c_est) -the estimate average gain plus the actual, slow deviation around it. You apply this gain to the output y.

I think, though, there’s a mistake in the paper. They compute c_est using threshold in dB, so c_est is in log space. But c[n] = 10 ^ (M - yL[n]) / 20, so c is in linear space and it already includes the make-up gain M. I think c_dev shouldn’t work on c but on -yL: a * c_dev[n - 1] - (1 - a) * (yL[n] + c_est).

1 Like

YES! IT WORKS! Thank you, very much!