Crossfading with SmoothedValue doesn't loop back after use

Hi! I have been following examples on the forums and the tutorials to try to do a simple crossfade between buffers using SmoothedValue. The code works fine up until the second crossfade event, where a SmoothedValue object doesn’t revert its currentValue into 0, but instead caps on 1, making the crossfade useless. Here is how I’m using the class. First in the header, I define:

juce::SmoothedValue<double, juce::ValueSmoothingTypes::Linear> smoothedGain;

Then in the .cpp I declare and initialize it in prepareToPlay() as follows:

smoothedGain.reset(sampleRate, 0.01);
smoothedGain.setTargetValue(1);

And finally in getNextAudioBlock() I, at the beginning run this line (that I found from a forum post and don’t quite understand the reasoning of):

smoothedGain.setTargetValue(1);

And finally in the event of a crossfade, I do this:

if (CF_FLAG == true)
{
    float sampleCF = 0;
    lastFilterState = currentFilterState;
    CF_FLAG = false;

    auto* inBufferL = bufferToFill.buffer->getReadPointer(0,
                        bufferToFill.startSample);
    auto* inBufferR = bufferToFill.buffer->getReadPointer(1,
        bufferToFill.startSample);
    auto* cfBufferL = scratchBuffer.getReadPointer(0, 0);
    auto* cfBufferR = scratchBuffer.getReadPointer(1, 0);
    for (int i = 0; i < bufferToFill.numSamples; i++)
    {
        const auto gain = smoothedGain.getNextValue();
        sampleCF = cfBufferL[i] *
            (1.0 - gain) + inBufferL[i] * gain;
        block.setSample(0, i, sampleCF);

        sampleCF = cfBufferR[i] *
            (1.0 - gain) + inBufferR[i] * gain;
        block.setSample(1, i, sampleCF);
    }

What would be going wrong here? There doesn’t seem to be a method to reset the currentValue back to zero (it was said on another post that the .reset() should only be used in prepareToPlay() once).

Thank you!

I’m not sure if SmoothedValue is particularly well suited for this task, since it is not designed to be have its value jump around.

But from the docs, it looks like you can either create a new SmoothedValue instance with an initial value of 0 before a crossfade occurs, or you could potentially also use a combination of setTargetValue(0.0f) and skip(num_steps), where num_steps is the crossfade length in samples.

Thank you for the suggestions, I will try them. Aside from that, is there a standard way to do a crossfade like this in JUCE?

this is definitely one of those cases where you are better off writing your own little crossfader struct. it’s rather easy to let a value go from one point to another in a certain way logically and with your own implementation you could even get more creative, like adding a curvature to it or different kinds of optimizations specific to your project