Parameters don't work correctly

I use AudioParameterFloat like you in your tutorials.
If I change parameter value by automatization (draw a curve) or GUI (slider or text field) it works correctly.
But if I try to insert a value directly to host automatization text field, it doesn’t work properly.

For example: I have gain parameter with range from -20.0 dB to 20.0 dB and if I try to insert 10.0 to this field, host change it to -16.0, if i try to insert 20.0, host change it to -12.0 etc. I tried it in Cubase 5 and Cubase 8.

Thanks for answers

This can often indicate that something may be wrong with your editor: your editor is getting a callback when the text is changed and modifies a slider. The slider callback is then called which in turn sends the new value back to the host. If there is any conversion error along the way, then you’ll get an incorrect value in the host.

I’ve modified the juce demo plug-in to take a gain parameter range from -20db to 20db and it works fine (Cubase 8.5, VST3, see patch below if you want to try it out).

diff --git a/examples/audio plugin demo/Source/PluginEditor.cpp b/examples/audio plugin demo/Source/PluginEditor.cpp
index 8639737..80470f9 100644
--- a/examples/audio plugin demo/Source/PluginEditor.cpp
+++ b/examples/audio plugin demo/Source/PluginEditor.cpp
@@ -28,10 +28,12 @@ public:

void valueChanged() override
{
    +        const float newValue = (float) jmap (Slider::getValue(), getMinimum(), getMaximum(), 0.0, 1.0);
    +
    if (isMouseButtonDown())
        -            param.setValueNotifyingHost ((float) Slider::getValue());
    +            param.setValueNotifyingHost (newValue);
    else
        -            param.setValue ((float) Slider::getValue());
    +            param.setValue (newValue);
}

void timerCallback() override       { updateSliderPos(); }
@@ -44,7 +46,7 @@ public:

void updateSliderPos()
{
    -        const float newValue = param.getValue();
    +        const float newValue = (float) jmap ((double) param.getValue(), getMinimum(), getMaximum());
    
    if (newValue != (float) Slider::getValue() && ! isMouseButtonDown())
        Slider::setValue (newValue);
    diff --git a/examples/audio plugin demo/Source/PluginProcessor.cpp b/examples/audio plugin demo/Source/PluginProcessor.cpp
    index fd3c82f..ca54e2c 100644
    --- a/examples/audio plugin demo/Source/PluginProcessor.cpp
    +++ b/examples/audio plugin demo/Source/PluginProcessor.cpp
    @@ -160,7 +160,7 @@ JuceDemoPluginAudioProcessor::JuceDemoPluginAudioProcessor()
    // This creates our parameters. We'll keep some raw pointers to them in this class,
    // so that we can easily access them later, but the base class will take care of
    // deleting them for us.
    -    addParameter (gainParam  = new AudioParameterFloat ("gain",  "Gain",           0.0f, 1.0f, 0.9f));
    +    addParameter (gainParam  = new AudioParameterFloat ("gain",  "Gain",           -20.0f, 20.0f, 0.0f));
    addParameter (delayParam = new AudioParameterFloat ("delay", "Delay Feedback", 0.0f, 1.0f, 0.5f));
    
    initialiseSynth();
    @@ -271,7 +271,7 @@ template <typename FloatType>
    void JuceDemoPluginAudioProcessor::applyGain (AudioBuffer<FloatType>& buffer, AudioBuffer<FloatType>& delayBuffer)
    {
        ignoreUnused (delayBuffer);
        -    const float gainLevel = *gainParam;
        +    const float gainLevel = std::pow (10.0f, static_cast<float> (*gainParam) / 20.0f);
        
        for (int channel = 0; channel < getTotalNumInputChannels(); ++channel)
            buffer.applyGain (channel, 0, buffer.getNumSamples(), gainLevel);

I forgot to say that it is a VST2.
VST3 runs fine, but VST2 behaves as I wrote.