How to prevent 'parameter creep' due to VST float 0..1 range

I’ve made small templated class to help with the mapping of parameters into the VST 0…1 range; however I’m having issues with float rounding, which is causing the plugin provided UI to update the processor parameter values with a value which is marginally too small. As a consequence, in the UI Timer callback, which updates the UI from the processor parameter values, the UI parameters creep downwards towards the parameter minimum on each timer interval.

Does anyone have any tips on how to avoid this? I’ve pasted here my VSTParameter<> class template; I usually instantiate this with VSTParameter( … ) or VSTParameter( … )

template <class Numeric>
class VSTParameter
{
public:
	VSTParameter() {};
	VSTParameter(const String _name, const Numeric _min, const Numeric _max, const Numeric _default) :
		name(new String(_name)),
		min(_min), max(_max), range(_max-_min), value(_default)
	{};
	~VSTParameter() {};

	String getName() const
	{
		return *(name.get());
	};

	void setValue(const Numeric v)
	{
		if (v < min)
			value = min;
		else if (v > max)
			value = max;
		else
			value = v;
	};
	Numeric getValue()
	{
		return value;
	};

	void setNormalisedValue(const float v)
	{
		if (v < 0.f)
			value = min;
		else if (v > 1.f)
			value = max;
		else
			value = (Numeric)v * (range + min);
	};
	float getNormalisedValue()
	{
		return normaliseValue(value);
	};

	float normaliseValue(const Numeric v)
	{
		return ((float)v-(float)min)/(float)range;
	};

private:
	std::tr1::shared_ptr<String> name;
	Numeric min, max, range, value;
};

Ah, nevermind, I’ve pretty much eliminated the issue by using the ‘normalised’ value as the reference one. Below is the re-written VSTParameter class template

template <class Numeric>
class VSTParameter
{
public:
	VSTParameter() {};
	VSTParameter(const String _name, const Numeric _min, const Numeric _max, const Numeric _default) :
		name(new String(_name)),
		min(_min), max(_max), range(_max-_min), value_norm(normaliseValue(_default))
	{};
	~VSTParameter() {};

	String getName() const
	{
		return *(name.get());
	};

	void setValue(const Numeric v)
	{
		if (v < min)
			value_norm = 0.f;
		else if (v > max)
			value_norm = 1.f;
		else
			value_norm = normaliseValue(v);
	};
	Numeric getValue()
	{
		return (Numeric)( (value_norm*range)+min );
	};

	void setNormalisedValue(const float v)
	{
		if (v < 0.f)
			value_norm = 0.f;
		else if (v > 1.f)
			value_norm = 1.f;
		else
			value_norm = v;
	};
	float getNormalisedValue()
	{
		return value_norm;
	};

	float normaliseValue(const Numeric v)
	{
		return value_norm = ((float)v-(float)min)/(float)range;
	};

private:
	std::tr1::shared_ptr<String> name;
	Numeric min, max, range;
	float value_norm;
};

Yes, I had a similar problem and also solved it by treating the 0…1 value as the “master” value.

I haven’t tried templating it though, have just implemented for floats because my class isn’t as neat as yours - mine has bloated out with a third value type for the GUI and handling of VST programs (i.e. the class holds an array of parameter values sized according to the number of programs).