Gain safe distortion algorithm


Say I have a simple distortion algorithm:

//  drive >= 1.0
float distortion(float input, float drive){
    return tanh(input *  drive);

As drive increases, so does the distortion level but also the volume of the signal. I’d like to make a distortion algorithm that automatically keeps the total volume (or better yet, if possible, the perceived loudness i.e. LUFS) of the signal approximately the same regardless of the distortion level. I was curious if anyone was aware of any algorithms that implemented this or had any thoughts on the matter.

The reason I’d like to do this is that it would be nice for users to be able to crank up the distortion during a live performance without having to worry about unwanted volume increase.


I’ve used things like this - they will get loud, but shouldn’t clip:

// For distortion models
#define INV_ARCTAN_1 1.273239544735163
#define INV_TANH_1   1.313035285499331
// no effort made here to avoid aliasing due to harmonics introduced by waveshaping/clipping
switch(cur_output_mode) {
  case NONE:
  case EXP_DIST:
    to_out = SGN(to_out) * (1 - expf(-fabsf(to_out)));
  case TANH:
    to_out = tanhf(to_out) * INV_TANH_1;
  case ARCTAN:
    to_out = atanf(to_out) * INV_ARCTAN_1;

I know csound has a balance opcode that takes the original signal and the modified signal and adjusts the gain of the modified signal so that both signals have the same RMS power - you might be able to implement something like that if you really want to keep the loudness quite similar.



The balance opcode looks like it will accomplish what I want to do, I’ll check it out.

Thanks for the reply!