*request* dsp::Oscillator should use a log frequency fade

dsp::Oscillator uses a linear ramp for the frequencies, but this is not how it works for frequencies, obviously

wrong (lin) -> 10, 20, 30, 40, 50, 60
right (log) -> 10, 14, 20, 29, 42, 60

LinearSmoothedValue, needs a sister class, LogSmoothedValue which could be used by dsp::Oscilliator

Here are the most important building blocks for this class

    void reset (double sampleRate, double fadeLengthSeconds) noexcept
        jassert (sampleRate > 0 && fadeLengthSeconds >= 0);
        stepsToTarget = (int) std::floor (fadeLengthSeconds * sampleRate);
        currentValue = target;
        countdown = 0;
    bool setValue (float newValue) noexcept
        if (newValue<minimumVal)
        if (target != newValue)
            target = newValue;
            countdown = stepsToTarget;
            if (countdown <= 0)
                currentValue = target;
                step =  exp(( log(target) - log(currentValue) ) / (float) countdown );
            return true;
		return false;
    float getNextValue() noexcept
        if (countdown <= 0)
            return target;
        currentValue *= step;
        return currentValue;


Also it needs a setRampDurationSeconds (double newDurationSeconds) like Gain and Bias

A few other additions would be nice,

  • for multiple channels, it seems to be a waste of resources to calc the oscillator again for every channel

  • access to set and get the current phase position (for lfo syncing)

  • adjustable channel phase difference

There are already a few classes in JUCE for log fades, they are called IIRFilter, dsp::IIR and dsp::StateVariableFilter :slight_smile:

Hi Ivan,

i was referring to the current parameter smoothing which is used inside oscillator class, which i think is not right for frequencies (the same goes also for linear gain-values too, because the loudness perception is also logarithmic )
If you here the sweep, it goes to fast to the higher values.

But it also should have a defined target value, which you don’t get with filters.

Linear Fade:
You calculate the single step with
step = (target - currentValue) / (FloatType) countdown;
and for every step
currentValue += step;

10, 20, 30, 40, 50, 60

-> But for frequencies we need to use a logarithmic fade

You calculate the single step with
step = std::exp(( std::log(target) - std::log(currentValue) ) / (float) countdown )
and for every step
currentValue *= step;

10, 14, 20, 29, 42, 60

I’ve done it for my self, but i want to share it with you, because i think the current implementation is not right.

Yes I guessed so already, but anyway a few classes in the current dsp module were created by Fabian as simple examples of the new Processor classes or the waveshaper stuff. For a proper Oscillator class, we would need to provide a lot of additional features such as anti-aliasing.

However, I guess a LogSmoothedValue class with a proper target value might be a nice addition as well :wink:

1 Like