I am trying to make an EQ with auto makup gain. The idea is that as a band’s gain is increased, an output knob turns the master for that channel gain down (left or right). I had the idea of trying to store the magnitude of the samples before and after the processing using
auto inputLeftOutputGain = buffer.getMagnitude(0, 0, buffer.getNumSamples());
but everytime I do this, I end up with chatter or silence. I believe this is because I am not getting individual stores of the magnitude of the buffer before and after processing, even if I put the previous line above the following line in the chain.
I don’t know if this would be a horrible idea but I would approach this by:
using getMagnitudeForFrequencyArray on your coefficients
Finding the average level of the frequencies
Calculate the gain you need to bring it to the correct level
Apply gain
This is of course you’re wanting a theoretical autogain rather than one that is responding to the actual incoming frequencies of your processes. It does mean that you wouldn’t be reliant on monitoring levels on input and output but the accuracy would be restricted to the number of frequencies in your array.
The problem is that the attenuation of the eq depends on the signal routed through. Imagine a HighPass set to 1kHz on a piccolo flute. Attenuation = 0dB because no frequency below 1kHz was there in the first place. Put it on a bass drum and almost nothing is left.
auto outputLeftOutputGain = buffer.getRMSLevel(0, 0, buffer.getNumSamples());
auto outputRightOutputGain = buffer.getRMSLevel(1, 0, buffer.getNumSamples());
auto currentLeftOutputGain = 1.f - outputLeftOutputGain; //1.f being nominal gain
auto currentRightOutputGain = 1.f - outputRightOutputGain;
if (currentLeftOutputGain == previousLeftOutputGain)
{
buffer.applyGain(0, 0, buffer.getNumSamples(), currentLeftOutputGain);
} else {
buffer.applyGainRamp(0, 0, buffer.getNumSamples(), previousLeftOutputGain, currentLeftOutputGain);
previousLeftOutputGain = currentLeftOutputGain;
}
if (currentRightOutputGain == previousRightOutputGain)
{
buffer.applyGain(1, 0, buffer.getNumSamples(), currentRightOutputGain);
} else {
buffer.applyGainRamp(1, 0, buffer.getNumSamples(), previousRightOutputGain, currentRightOutputGain);
previousRightOutputGain = currentRightOutputGain;
}
There isn’t any distortion which is great, and the RMS level does move up when I move a band’s gain. I feel like I’m doing something wrong in this part. Maybe I just don’t know how to calculate the gain offset.
auto currentLeftOutputGain = 1.f - outputLeftOutputGain; //1.f being nominal gain
auto currentRightOutputGain = 1.f - outputRightOutputGain;
I like your code! It makes sense. For some reason, when pushing up the gain on a slider, I still get a change in RMS gain overall. Maybe I’m misunderstanding something. Here’s my process block, if that helps to see where I’m going wrong. Is there something I need to put in to prepare to play?
I’ve been utilizing this thread to achieve an auto-makeup after convolution with an IR. I did have to switch it to input/output to calculate makeup like baintonaj did.
However, now my gain is actually too powerful, and I appear to be increasing beyond the input gain. Any ideas why this might be?
I had the same issue, eventually I was able to make it work
I’m still very new to C++ and JUCE, I might got some things wrong here, still I thought I’ll share incase it’s helpful for anyone else.
This is what I ended up with and it works well:
before the process:
float inputLevel = 0.f;
for (int i = 0; i < numChannels; i++)
{
inputLevel = buffer.getRMSLevel(i, 0, numSamples);
}
after the process:
float outputLevel = 0.f;
for (int i = 0; i < numChannels; I++)
{
outputLevel = buffer.getRMSLevel(i, 0, numSamples);
}
and apply the makeup gain:
const auto makeup = (inputLevel > 0.0) ? inputLevel / outputLevel : 1.0;
autoGainSmoothing.setTargetValue(makeup);
const auto makeupSmooth = autoGainSmoothing.getNextValue();
for (int i = 0; i < numChannels; ++i)
{
buffer.applyGain(i, 0, numSamples, makeupSmooth);
}
I used smoothed value for the makeup because I got some type of clipping if I didn’t use it.
It also works with buffer.applyGainRamp, if you store the previous value as shown here.
easiest way to make autogain for a filter is just to run the filter on pink noise at different parameter values and then fill an array with rms ratios between the dry and wet noise. this can all be done in prepareToPlay and in processBlock you just read from that array and multiply it with your isgnal
Actually I take that back, I still get a wired sound when using smooth value as well as applyGainRamp.
I should mention I’m using this after a waveshaper, maybe it’s not a good use case for this type of auto-gain?