ValueTree valueTreePropertyChanged problems identifying which property has changed

I am having trouble with identifying which parameter has been changed, I can find the new value, but how do I get the property which was changed (or rather I would like the ParameterID which changed)
If examining the property of the Listener I always get “value”…

void NewProjectAudioProcessor::valueTreePropertyChanged(ValueTree& treeWhosePropertyHasChanged, const Identifier& property) 
 {
     DBG("Change to ValueTree, Identifier: " + String(property.toString()) + ", Value: " + treeWhosePropertyHasChanged.getProperty(property).toString());


 }

If it’s a parameter change you’re interested in, don’t you just want to implement parameterChanged() in your processor, not valueTreePropertyChanged()? The parameterChanged() function includes the ParameterID and the new value in its parameter list.

1 Like

What Howard said. If you’re using AudioProcessorValueTreeState, you should listen to it, not to its ValueTree. ValueTree is an XML-like structure. For each parameter, APVTS saves a new child in its ValueTree -like an XML tag. Something like

<PARAM id="freq" value="250.0"/>

Because you’re listening to the ValueTree, it tells you that the property “value” has changed. To get the parameter name, you’d have to ask for the property “id”. It’s not the only problem though -you’ll also get notified late. APVTS updates its ValueTree on the message thread, with a Timer. You should use APVTS::Listener::parameterChanged to get synchronous calls.

1 Like

Thanks for the answers. But I am unsure as to how to get a callback for parameterChanged.
I cannot seem to attach a general listener to my APTVS. It offers a addParameterListener which requires a ParameterID - so I would have to generate a listener for each parameter instead of just one.

The timing issue is not that important in this instance as I just need the information for updating the GUI with feedback to the user about what current value was changed to what when they twiddle sliders.

You don’t need a different listener for each parameter, you can have the same listener for all of them. If you have your IDs stored somewhere, you can listen to all of them with something like

for (auto& id : parameterIDs)
    apvts.addParameterListener(id, this);

in, say, YourAudioProcessor constructor. Or, if you don’t have them stored

for (auto p : getParameters())
    apvts.addParameterListener(static_cast<AudioProcessorParameterWithID*>(p)->paramID, this);

Anyway, this is not very useful to update the UI, precisely because it’s synchronous. In your case, I’d link the UI components between them. If you already have a slider connected to a parameter (say, with a SliderAttachment), you can make your other component listen to the slider. Alternatively, you can link your other component to the parameter with another attachment. If it’s not a slider, a button or a combobox, you can use the new ParameterAttachment. These classes already handle the asynchronicity, and also deregister their listeners on destruction.

1 Like

Thank you Kamedin - this is gold :slight_smile: