Artifacts when automating gain parameter

hi, i’m working on a wavetable synth and i tried to figure out how to apply gain parameter properly and make it work with a slider.

is this technically correct way of applying gain changes? as far as i have read using applyGain method on a buffer within processBlock function should do the job but it doesn’t seem to work neither in PluginProcessor class nor WavetableSynth class i made. or maybe did i just miss something?

float WavetableOscillator::getSample()
{
    jassert(isPlaying());
    index = std::fmod(index, static_cast<float>(waveTable.size()));
    const auto sample = interpolateLinearly() * gain * velocity;
    index += indexIncrement;
    return sample;
}

here are my processBlock methods

void WavetableSynth::processBlock(juce::AudioBuffer<float>& buffer, 
                                  juce::MidiBuffer& midiMessages)
{
    auto currentSample = 0;

    buffer.applyGain(0.3f);  // hardcoded random value to see if it actually works

    for (const auto midiMetadata : midiMessages)
    {
        const auto message = midiMetadata.getMessage();
        const auto messagePosition = static_cast<int>(message.getTimeStamp());

        render(buffer, currentSample, messagePosition);
        currentSample = messagePosition;
        handleMidiEvent(message);
    }


    render(buffer, currentSample, buffer.getNumSamples());
}

void WavetableSynthAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;

    for (auto i = 0; i < buffer.getNumChannels(); ++i)
        buffer.clear(i, 0, buffer.getNumSamples());

    auto gSlider = valueTreeState.getRawParameterValue("gain")->load();

    synth.applyGain(gSlider);

    synth.processBlock(buffer, midiMessages);
}

the first implementation deep down in the WavetableOscillator actually works, but it generates a lot of artifacts as the parameter gets automated, hence the question. is this because of improper way of implementing gain change or do i just need to do some upsampling?

to prevent artifacts, changes to a gain parameter need to be upsampled to the audio rate.

A common method of doing this is to ramp the gain value over a few ms to the new value. i.e. make the changes to the gain smooth.

You can use the class juce::dsp::Gain<>.