Exemple for ParameterAttachment in JUCE 6

Hi all,

I would like to use the new ParameterAttachment class in my plugin to attache some custom GUI controls I have without having them to be displayed as automatable for the plugin host.

I see that we don’t need to use AudioProcessorValueTreeState anymore but should I pass the main AudioProcessoras an input parameter instead of AudioProcessorValueTreeState? I don’t think since it would mean to couple the processor and the gui.

What is the pattern to attach a GUI to the AudioProcessor using the new ParameterAttachment?

ParameterAttachments connect controls to AudioProcessor parameters -you can see that’s what the constructor takes. Parameters are part of the processor, whether there’s an APVTS or not. They’re an interface to the host, so they’re automatable unless explicitly made not, which some hosts ignore. APVTS just keeps the values of all parameters in a ValueTree, so that it’s easier to replace the whole state, or save it, or connect parameters to UI controls. If your parameters are actual AudioProcessorParameters, then ParameterAttachment is appropriate. If you need to connect a control to an internal value, there’s not much infrastructure in Juce to do it -I’ve seen different solutions.

Thanks for your reply @kamedin

I would like to use ParameterAttachment for 2 reasons:

  • I’ve a custom GUI attachement (double slider)
  • I don’t want the parameter to be visible by the host, since as you mentioned ( which some hosts ignore ), but I need to observe the value inside my audioProcessor.

ParameterAttachment seems to be a good candidate for this case.

My first try was to use the AudioProcessorValueTreeState with something like this:

// .h
RangeSliderComponent(AudioProcessorValueTreeState& apvts);
...
AudioProcessorValueTreeState& apvts_;
std::unique_ptr<TwoValueSliderAttachment> attachment_;

// .cpp
attachment_ = std::make_unique<TwoValueSliderAttachment>(apvts_,
                                                         parameterMinId,
                                                         parameterMaxId,
                                                         rangeSLider_);

but without any surprise, the two parameterId are visible by the host and can be automatized.

@reuk mentioned:

The part that is interesting is:

Also, even if you do decide to use an APVTS, you no longer need your editor to know about the APVTS or your parameterIDs when creating attachments (as you can pass parameter references instead), which reduces unnecessary coupling

So I’m wondering what should as input parameter instead of the current AudioProcessorValueTreeState

I’ll take that you mean a custom widget. ParameterAttachments are for connecting AudioProcessorParameters -those that are visible by the host. If you don’t want this parameter to be visible by the host, then it’s not an AudioProcessorParameter. It’s some value you want to keep in your processor. You need a different kind of attachment that’s not provided by Juce in a ready-made form. Which kind depends on the use you’ll make of it. I’ve made attachments to connect controls to ValueTrees, for UI parameters that are not used on the audio thread but should be stored in the plugin state. Daniel has an attachment to connect Values to atomics, for audio thread stuff. You could make one that connects both to an atomic and to a ValueTree, so that it can be used on the audio thread and also saved as state. None of these options are available in Juce, but you have the elements to make them.

Thanks you @kamedin for the detailed answer.

I’m sorry but I’ve more questions since I cannot find a good practice regarding this issue and a lot of people are asking it on the forum without any answer.

One good solution would be to use the class from @daniel foleys_AtomicValueAttachment, however @daniel could you show us an example of good practice for it? Does the ValueTree a member of the main AudioProcessor? Or do you do something else?

Also, in this thread called Non-automatable parameters and UI attachments? @reuk exaplicitely say that ParameterAttachment could be attached to hide parameter from the host without using AudioProcessValueTreeState. And this is this point that I cannot find any exemple.
@reuk could you please explain it a little more?

And one more thing also more confusing is the usage of the CachedValue. From what I understood it’s not thread safe (no mention in the codebase or even in the great presentation talking about ValueTree) but @jules mentioned something opposite (in the thread called Audio Thread and ValueTree/Value listeners)if I understand it well:

Well, all this to say that now, like a lot of people I guess, I’m lost :thinking:

Well, he didn’t explicitly said it, and it’s not very useful for these cases. Thing is, you could create say an AudioParameterFloat without adding it to the processor -just keeping it as a member variable. Then it wouldn’t be visible to the host, and you could use it with ParameterAttachment. It’s possible, but it adds quite a bit of complication to something that could be a simple variable. For example, APParameters get and set their value normalized to 0…1 because that’s what hosts expect. There are many threads asking for other types of attachments -I guess it’s not been done mainly because there’s no single solution for all cases.

Daniel’s attachment connects a Value with an atomic. Values and ValueTrees are different things. Widgets have an internal Value object you can get (with getValueObject for sliders, getToggleStateValue for buttons). You connect this attachment to that Value object.

foleys::AtomicValueAttachment<double> yourAtomic;
yourAtomic.attachToValue (someSlider.getValueObject());

Then the slider will update the internal atomic, whose value you can get from the audio thread with yourAtomic.get().

AFAIK, there’s nothing inherently thread-safe about CachedValue. It keeps a local copy of a property’s value, but it still could be updated from a different thread than the one you’re reading your copy from.

I can’t be more specific because I don’t know your usage -if it’s an UI only parameter, you may not even need thread safety.

The purpose of the ParameterAttachment class is to connect a RangedAudioParameter to a UI widget. It does not require an APVTS in order to function, but it does need to connect to a RangedAudioParameter. AudioParameters are designed to communicate parameter values between the plugin and the host, so ParameterAttachments may not be suitable if you want to hide a parameter from the host. If you still want to try this approach, AudioParameters do have an isAutomatable virtual function which can be overridden to disable host automation, which may be useful.