Using AudioProcessorValueTreeState

(I’m very new to this so please pardon my ignorance)

I’m trying to follow along with this tutorial:

And I’m having trouble getting the Audio ProcessorValueTreeState to actually work. It seems like a few things he’s using have been deprecated, in particular:

ScopedPointer<AudioProcessorValueTreeState::SliderAttachment> filterCutoffValue;
ScopedPointer<AudioProcessorValueTreeState::SliderAttachment> filterResValue;
    
ScopedPointer<AudioProcessorValueTreeState::ComboBoxAttachment> filterMenuChoice;

So I can’t figure out how to declare the tree attachments.

It also looks like

createAndAddParameter()

Is going to be deprecated and google has not yielded an alternative that I can understand.

I also seem to be getting a ton of errors with the AudioProcessorValueTreeState header file itself even though I haven’t touched it.

My questions are twofold:

  1. How do I fix my current issue?
  2. Can someone point me towards a video or something on using AudioProcessorValueTreeState so I can get a better handle on it?

The attachment classes are not deprecated, ScopedPointer is. Use std::unique_ptr instead.

The errors you’re seeing could be a number of things, you’ll have to be more specific. Which errors, on which platform?

The current way of creating parameters is passing a ParameterLayout to APVTS’ constructor. This usually involves having a free function that returns a ParameterLayout. The layout is filled with unique_ptrs containing each of your parameters, so your function may return a braced list with calls to std::make_unique:

juce::AudioProcessorValueTreeState::ParameterLayout createParameters()
{
    return { std::make_unique<juce::AudioParameterFloat> (/***/),
             std::make_unique<juce::AudioParameterChoice> (/***/),
             /* etc */ };
}

Alternatively, you could create a vector, add your parameters there, then return the begin/end iterators:

juce::AudioProcessorValueTreeState::ParameterLayout createParameters()
{
    std::vector<std::unique_ptr<juce::RangedAudioParameter>> parameters;
    parameters.reserve (/* nr of parameters */);
    parameters.push_back (std::make_unique<juce::AudioParameterFloat> (/***/));
    /* or */
    parameters.emplace_back (new juce::AudioParameterFloat (/***/));
    /* etc */
    return { parameters.begin(), parameters.end() };
}

Then in your processor:

class MyAudioProcessor : juce::AudioProcessor
{
    juce::UndoManager undoManager; // if you're using one
    juce::AudioProcessorValueTreeState apvts{ *this, &undoManager, "my plugin",
                                              createParameters() };
    /* etc */
}

Because this is all quite verbose, instead of a free function I use a function object with some helpers, so the code that actually adds the parameters gets a little more concise.

I seem to be getting these errors on even brand new projects now (using xcode):

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:45:53 Unknown type name 'StringFro'

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:45:74 Expected ')'

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:45:118 No member named 'attributes' in 'juce::AudioProcessorValueTreeStateParameterAttributes'

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:45:130 Use of undeclared identifier 'attributes'

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:45:181 Use of undeclared identifier 'x'

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:47:19 Expected member name or ';' after declaration specifiers

/Users/mbarbara/JUCE/modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h:500:76 No member named 'withLabel' in 'juce::AudioProcessorValueTreeStateParameterAttributes'

Did I break JUCE or something?

As for the rest of it, I’m going to try and wrap my head around that over the next day or so and poke you if I have any questions.

I seem to have resolved the errors by re-installing JUCE. I don’t quite understand why the following code is giving me an “error, no overloaded ‘=’” error though.

.cpp:

filterCutoffValue = new juce::AudioProcessorValueTreeState::SliderAttachment (audioProcessor.tree, "cutoff", mCutoffDial);
filterResValue = new juce::AudioProcessorValueTreeState::SliderAttachment (audioProcessor.tree, "resonance", mResdial);
filterMenuChoice = new juce::AudioProcessorValueTreeState::ComboBoxAttachment (audioProcessor.tree, "filterMenu", mFilterMenu)

.h:

std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> filterCutoffValue;
std::unique_ptr<juce::AudioProcessorValueTreeState::SliderAttachment> filterResValue;
std::unique_ptr<juce::AudioProcessorValueTreeState::ComboBoxAttachment> filterMenuChoice;

Again, super new to JUCE and CPP in general so I’m definitely doing something dumb.

There’s no implicit conversion to std::unique_ptr<T> from T* (a plain pointer, which is the return of new). That constructor (2) is marked explicit, precisely to avoid this kind of thing. You have these alternatives:

filterCutoffValue = std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment> (audioProcessor.tree, "cutoff", mCutoffDial);

filterCutoffValue.reset (new juce::AudioProcessorValueTreeState::SliderAttachment (audioProcessor.tree, "cutoff", mCutoffDial));

@kamedin I’ve attempted to use the vector of unique AudioParameterFloat pointers, but I’m getting an error related to referencing a deleted function in visual studio 2026.

I’d suggest copy/pasting the exact error you are getting with a snippet of the relevant code. It’s difficult to help otherwise.

@icebreakeraudio The exact error in visual studio 2026 is

error C2280: attempting to reference a deleted function

and the createLayout function definition

juce::AudioProcessorValueTreeState::ParameterLayout FftAudioProcessor::createParams(juce::AudioBuffer<float>* bufferPtr, float* channelData)
{
    std::string paramName = "frequency";
    std::vector<std::unique_ptr<juce::RangedAudioParameter>> paramPtrs = {};

        for (int i = 0; i < bufferPtr->getNumSamples(); i++)
    {
        juce::ParameterID id = juce::ParameterID("channel_data_" + std::to_string(i));
        juce::AudioParameterFloat parameter = juce::AudioParameterFloat(id, paramName, 20.0f, 20000.0f, channelData[i]);
        
        std::unique_ptr<juce::AudioParameterFloat> paramPtr = std::make_unique<juce::AudioParameterFloat>(parameter);
        
        paramPtrs.push_back(std::move(paramPtr));
    }

    return { paramPtrs.begin(), paramPtrs.end() };
}

AudioParameterFloat is non-copyable, per it’s declaration

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioParameterFloat)

You attempt to copy it when creating paramPtr

@cpr2323 I received the same error when passing make_unique directly to push_back. Would that be an implicit copy?

I believe I may have eliminated the error by passing the parameter info directly into make_unique.

Yes, you have eliminated the copy. You are now constructing the object in the unique_ptr, not copying it into the unique_ptr.