Still glitchy/zipping noises after using smoothedvalue

Im a beginner and im trying to keep a smooth sound when changing parameters through a gui. I made a couple of filters, based on the WolfSound tutorial on youtube about filters. I used the smoothedvalue class, but theres still some zipping or glitchy sound when changing parameters. In particular the cutofffrequency parameter.

My pluginprocessor class uses the AudioProcessorValueTreeState Class to keep my parameters. The stepsize for the cutofffrequency is 0.01 hz, which seems small enough to me. So thats not the problem.

Then every block i call this once:

const auto cutOffFrequency = cutOffFrequencyParameter->load();
filter.setCutOffFrequency(cutOffFrequency, buffer.getNumSamples());

where the cutOffFrequency instance variable of the filter class is this:

juce::SmoothedValue<float, juce::ValueSmoothingTypes::Multiplicative> cutOffFrequency;

and where filter.setCutOffFrequency() is defined like this:

void LowHighPassFilter::setCutOffFrequency(float cutOffFrequency, int steps)
{
    this->cutOffFrequency.reset(steps);
    this->cutOffFrequency.setTargetValue(cutOffFrequency);
}

Then when calculating the filter output i do this for every next sample:

  • I call cutOffFrequency.getNextValue() and put it in a variable
  • I use this variable inside the calculation of the filteroutput sample

Question 1:
Shouldnt this smoothen parameter changes?

Question 2:
I know i register a parameter change only every block, but i thought since i use smoothedvalue it shouldnt really matter because the value that is registered the next block will smoothly ramped towards in the calculations. Is this correct?

Question 3:
Since im a beginner. If there is something unusual about my code,methods,architecture,patterns, could you please give me tips or point me towards standard/best practices regarding audio parameters. Also tips regarding performance would be great, if there is any.

Don’t reset() the smoother when the cut-off frequency changes.

You shouldn’t to call reset every time you call setCutoffFrequency. Reset sets the ramp length (the amount of time either in samples or seconds it takes for your smoothed parameter to reach the target value). It would be better to initialize the ramp value of the filter in the prepareToPlay method of the PluginProcessor using an init function.

void LowHighPassFilter::init(const double sampleRate, const double rampLength, const float initCutoff)
{
    cutoffFrequency.reset(sampleRate, rampLength);
    setCutoffFrequency (initCutoff);
}


void LowHighPassFilter::setCutoffFrequency(float cutoffFrequency)
{
    this->cutoffFrequency.setTargetValue(cutoffFrequency);
}

void PluginProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    const double rampLength = 0.02;
    filter.init(sampleRate, rampLength, cutOffFrequencyParameter.getDefaultValue());
}

Hope that helps! Everything else is looking good :+1:

Thank you for the replies. To clearify, i load the cutofffrequency from the parameter every block and then i do filter.setCutoffFrequency(). I dont call anything from the gui. But how do you set the number of steps for the smoothed value to ramp over then? I remember reading somewhere that the bufferlength can vary per block. So dont i need to pass the buffer length to the smoothed value every block?

The ramp length is not dependent on the block rate. It’s dependent on the sample rate when setting the ramp length in seconds and only needs to be initialized when the sample rate is changed (in host programs, a change in sample rate will call the prepareToPlay method). The only thing you need to call every block is the setTargetValue method.

1 Like