Smoothing Delay Time Artefacts

Hi

I’m new to JUCE and trying to make a delay with feedback and a variable delay time. I’ve tried to use smoothvalue but get artefacts when I change the delay time. Any ideas what I’m doing wrong?

Thanks!

void TestAudioPluginAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();
    
    wetLevel = *apvts.getRawParameterValue("WET_LEVEL");
    delayFeedback = *apvts.getRawParameterValue("FEEDBACK");
    delayTimeMS = *apvts.getRawParameterValue("DELAY_TIME_MS");
    
    const float delayTimeSample = floor((delayTimeMS/1000.0f) * mSampleRate);
    
    if (delayTimeSample != delayTimeSampleSmoothed.getTargetValue()){
        delayTimeSampleSmoothed.setTargetValue(delayTimeSample);
    }
    
    
    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    const int bufferLength = buffer.getNumSamples();
    const int delayBufferLength = mDelayBuffer.getNumSamples();
    
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        
        const float* bufferData = buffer.getReadPointer(channel);
        const float* delayBufferData = mDelayBuffer.getReadPointer(channel);
        const float* wetBufferData = mWetTempBuffer.getReadPointer(channel);
        
        fillDelayBufferDry(buffer, channel, bufferLength, delayBufferLength, bufferData);
        getWetSignal(buffer, channel, bufferLength, delayBufferLength, delayBufferData);
        addFeedback(buffer, channel, bufferLength, delayBufferLength, wetBufferData);
    }
    mWritePosition += bufferLength;
    mWritePosition %= delayBufferLength;
    
}

void TestAudioPluginAudioProcessor::fillDelayBufferDry(juce::AudioBuffer<float>& buffer, int channel, const int bufferLength, const int delayBufferLength, const float* bufferData)
{
    if (delayBufferLength > bufferLength + mWritePosition)
    {
        mDelayBuffer.copyFrom(channel, mWritePosition, bufferData, bufferLength);
    }
    else
    {
        const int spaceAfterPointer = delayBufferLength - mWritePosition;
        
        mDelayBuffer.copyFrom(channel, mWritePosition, bufferData, spaceAfterPointer);
        mDelayBuffer.copyFrom(channel, 0, bufferData, bufferLength-spaceAfterPointer);
    }
}

    void TestAudioPluginAudioProcessor::getWetSignal(juce::AudioBuffer<float>& buffer, int channel, const int bufferLength, const int delayBufferLength, const float* delayBufferData)
    {
        for (int sample = 0; sample < bufferLength; sample++)
        {
            // Update the read pointer sample-wise
            float deltime = delayTimeSampleSmoothed.getNextValue();
            const float delayReadPointer = std::fmodf((delayBufferLength + mWritePosition + sample - deltime),  delayBufferLength);
            
            const int indexBelow = floor(delayReadPointer);
            const int indexAbove = (indexBelow + 1) % delayBufferLength;
            float fractionAbove = delayReadPointer - indexBelow;
            float fractionBelow = 1.0 - fractionAbove;
            
            // Read the wet signal for the current samples
            float wetSignal = fractionBelow * delayBufferData[indexBelow] + fractionAbove * delayBufferData[indexAbove];
            
            // Add wet signal to the output buffer
            buffer.addSample(channel, sample, wetSignal * wetLevel);
            mWetTempBuffer.setSample(channel, sample, wetSignal);
        }
    }