Usage of AudioProcessorParameter::setValue and setValueNotifyingHost

I created a sub class of AudioProcessorParameter to wrap an Atomic<float>. I override setValue to set the wrapped float atomicly. The setValueNotifyingHost I leave alone.

I realized, when I use setValue directly, the DAW does not realize that the project has changed, so I can't call save. That's why I used setValueNotifyingHost, and it worked well for Reaper (VST3).

Switching back to AAX, the value could not be changed at all. I could only fix it calling both, setValue AND setValueNotifyingHost. But checking the docs it says setValueNotifyingHost calls implicitly setValue. Did I miss something?

Here is my code:

void MyAudioProcessor::setValueNotifyingHost (const int index, const float value)
{
    if (AudioProcessorParameter* parameter = getParameters()[index]) {
        String name = parameter->getName(255);  // for debugging
        parameter->setValue (value);
        parameter->setValueNotifyingHost (value);
    }
}

I use the 3.2.0 stable, not the github version.

Sorry, I need to learn to phrase proper questions ;-)

a) Is it correct, that AudioProcessorParameter::setValueNotifyingHost calls implicit AudioProcessorParameter::setValue?

b) is it possible, that this behaviour is wrapper dependent or even host dependent?

c) was there a change since last stable version juce 3.2.0?

Thanks for the answers

setValueNotifyingHost isn't virtual - you shouldn't be trying to override it (??)

But yes, it's very host-dependent, and it's likely that things have changed since the 3.2.0 release - you should certainly use the latest tip for testing.

 

setValueNotifyingHost isn't virtual - you shouldn't be trying to override it (??)

No I don't, it's a helper in AudioProcessor, not AudioProcessorValue, so I can call from the Editor directly...

I realized, that AudioProcessor::setValueNotifyingHost already exists, but not as part of the API, so I renamed my version, but still, AudioProcessorParameter::setValue is not called (verified with breakpoint, doublecheck: AudioProcessorParameter::getValue() -> the breakpoint is hit):

void MyAudioProcessor::setValueNotifyingHostMe (const int index, const float value)
{
    if (AudioProcessorParameter* parameter = getParameters()[index]) {
        String name = parameter->getName(255);
        //parameter->setValue (value);
        parameter->setValueNotifyingHost (value);
    }
}

Could the way I access the AudioProcessorParameter be a problem? I realize in Array I would work here on a copy, but the parameters is an OwnedArray, where I get a reference by [] operator, right?

But yes, it's very host-dependent, and it's likely that things have changed since the 3.2.0 release - you should certainly use the latest tip for testing.

Ok, I pulled the latest git, last commit: 

commit 7b606e2e3ff9f942d1a12972ad2024967929d900
Author: jules <jules@juce.com>
Date:   Mon Oct 12 18:16:07 2015 +0100

 

Unfortunately when I call AudioProcessorParameter::setValueNotifyingHost (the original), the AudioProcessorParameter::setValue is not called:

void AudioProcessorParameterFloat::setValue (float newValue)
{
    m_value.set (newValue);
}

I use AAX SDK 2p2p0 running in ProTools 12.2.1x41 3P-Dev build

For completeness I attach my AudioProcessorParameterFloat class:

class AudioProcessorParameterFloat : public AudioProcessorParameter
{
public:
    AudioProcessorParameterFloat (String name, float defaultValue=0.0, String label=String());
    ~AudioProcessorParameterFloat();
    
    float  getValue () const override;
    void   setValue (float newValue) override;
    float  getDefaultValue () const override;
    String getName (int maximumStringLength) const override;
    String getLabel () const override;
    float  getValueForText (const String &text) const override;
    
private:
    Atomic<float>   m_value;
    String          m_name;
    float           m_default;
    String          m_label; 
};

AudioProcessorParameterFloat::AudioProcessorParameterFloat (String name, float defaultValue, String label)
: m_name(name), m_default(defaultValue), m_label(label)
{
    
}

AudioProcessorParameterFloat::~AudioProcessorParameterFloat() {}

float AudioProcessorParameterFloat::getValue () const
{
    return m_value.get();
}

void AudioProcessorParameterFloat::setValue (float newValue)
{
    m_value.set (newValue);
}

float AudioProcessorParameterFloat::getDefaultValue () const
{
    return m_default;
}

String AudioProcessorParameterFloat::getName (int maximumStringLength) const
{
    return m_name;
}

String AudioProcessorParameterFloat::getLabel () const
{
    return m_label;
}

float AudioProcessorParameterFloat::getValueForText (const String &text) const
{
    return text.getFloatValue();
}

And I use it like:

MyAudioProcessor::MyAudioProcessor()
{
    addParameter (new AudioProcessorParameterFloat ("MidLevel", 0.8));
    addParameter (new AudioProcessorParameterFloat ("MidSpread", 0.3));
}

 

 

 

 

 

 

 

Everything works as expected, as long as I don't override the setParameter / getParameter etc. methods. Those were in my project from the template, but I didn't implement them (as they are no longer needed because of AudioProcessorParameter). I kept the stubs, because I thought they were pure virtual...

How could I miss that, I'm a little embarrased...