What is the proper "JUCE" way of solving this problem? (Parameter normalization)


#1

I'm brand new to JUCE, so apologies if there's an easier way that I didn't find for me to answer this than asking a dumb question!

I've got a (VST only, not concerned with AU at the moment) plugin with a GUI gain slider and associated parameter representing gain.  As far as I can tell, that parameter can be modified from 3 general causes:  The GUI's slider component, host automation, and directly in the JUCE Processor for any other reason.  While the GUI slider and processor can utilize an arbitrary range for the gain parameter, host automation ALWAYS returns a value between 0 and 1 and does not allow for anything else.  Because of this, I decided to restrict my GUI slider's range to the same (0 to 1).  I want my GUI display to show decibels and allow the user to type new values into the text field in decibels.  I did that by converting decibels/gain back and forth in the getTextFromValue/getValueFromText methods and it worked fine.  Using JUCE's Decibel class for conversions only works if you want to map parameter 1.0 to 0.0db gain, so I had to just roll my own for the decibel range I wanted (-96 to 12) and set a skew for the slider to look normal.

My problem came when I realized that my host automation now (correctly) logarithmically mapped 0 decibels to ~0.2, which is mathematically correct but pretty functionally unusable.  I fixed that by using a pair of linear transforms to remap the values such that 0 decibels mapped to 0.5 instead.

It all technically "works" properly now, but I feel like there HAS to be a better way to accomplish this than the one I used.  What would be the proper way to handle parameter transforms in JUCE?  Should I just start building a generalized library for this sort of stuff?  Thanks for any help!


#2

I'd map the slider so that it has useful values for your processor and run a quick conversion when sending or receiving values from the host.  

So for a gain slider, maybe values between 0.0 and 2.0.  Then you can use the juce conversion for decibels (using the getTextFromValue() etc.) and use the value directly in your audio processor. 

Conversion looks something like: 


    ParamFloat normalizeToHost (ParamFloat internalValue) const
    {
        const ParamFloat f = (internalValue - minValue) / minMaxRange;
        const ParamFloat result = skewValueToHost (f);
        jassert (! isnan (result));
        return result;
    }

    ParamFloat denormalizeFromHost (ParamFloat normalizedValue) const
    {
        const ParamFloat f = skewValueFromHost (normalizedValue) * minMaxRange;
        return f + minValue;
    }
    ParamFloat skewValueFromHost (ParamFloat value) const
    {
        if (skew != 1.0 && value > 0.0)
            value = expf (logf (value) / skew);
        return value;
    }
    ParamFloat skewValueToHost (ParamFloat v) const
    {
        if (v <= 0.0) return 0.0;
        return skew == 1.0 ? v : powf (v, skew);
    

I hear there's a plot to add some more parameter handling functionality to JUCE shortly.  And there may have been things added already that I've not noticed :)

 


#3

Oh man that is PERFECT, exactly what I was needing!  Thank you so much!