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

dsp_module

#1

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)
        {
            newValue=minimumVal;
        };
        
        if (target != newValue)
        {
            target = newValue;
            countdown = stepsToTarget;
            
            if (countdown <= 0)
                currentValue = target;
            else
           
                step =  exp(( log(target) - log(currentValue) ) / (float) countdown );
                
            return true;
        }
		return false;
    }
    
    float getNextValue() noexcept
    {
        if (countdown <= 0)
            return target;
        
        --countdown;
        currentValue *= step;
      
        return currentValue;
    }

#2

+1


#3

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


#4

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


#5

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


#6

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.


#7

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: