A Base Processor class and APVTS

In an effort to reduce boilerplate code in my plug-in projects, I’ve been playing with creating a base class for plug-in Processors. And it works fine for handling simple stuff like acceptsMidi(), producesMidi(), isMidiEffect(), etc.

However, I also wanted this ProcessorBase class to handle implementing getStateInformation and setStateInformation, for which it would need access to the project’s AudioProcessorValueTreeState (APVTS). And that got trickier.

I tried having the APVTS be a member of the ProcessorBase class, but although it builds OK, that doesn’t work for DAWs to see the parameters. (In the APVTS constructor you have to provide a processorToConnectTo argument, and it probably doesn’t work to have that be a different type than what you initially passed back to a DAW in the createPluginFilter method… I didn’t fully dig through the layers to find the source of the conflict, just guessing there.)

So another idea I had was to have the derived Processor class own the APVTS member, but then have the ProcessorBase class own an AudioProcessorValueTreeState pointer. In the derived Processor’s constructor, it could set that pointer to its own APVTS member.

As a partial example of this approach:

BaseProcessor.h would include

protected:
    AudioProcessorValueTreeState* apvtsPtr;

public:
	void getStateInformation (juce::MemoryBlock& destData) override
	{
		jassert (apvtsPtr != nullptr);
		auto state = apvtsPtr->copyState();
		std::unique_ptr<juce::XmlElement> xml (state.createXml());
		copyXmlToBinary (*xml, destData);
	}

And the derived ProjectProcessor.h would include

    AudioProcessorValueTreeState apvts;

    // in constructor:
    apvtsPtr = &apvts;

    // in destructor:
    apvtsPtr = nullptr;

So if was setting up a new project, and forgot to set the apvtsPtr in the ProjectProcessor’s constructor, then getStateInformation would assert and let me know. Or, if I wanted to implement something different for getStateInformation for a particular project, then I override it in the derived processor, and that apvtsPtr just sits unused in the base processor (no harm done).

OK, so, questions:

  1. Does a Base class owning a pointer to a Derived class member inherently have a bad code smell?
  2. Is there a more common or convenient CPP idiom for doing this?

Well I’ll answer my own question: yes.

After a bit more playing around with this, realized that a more graceful solution for giving a base class access to a member of a derived class is to declare a pure virtual getter method in the base class. E.g.:

virtual AudioProcessorValueTreeState& getApvts() = 0;

No more need for checking/asserting for a nullptr. And a clear compiler error if I forget to implement getApvts() in the derived class.

Thank you, this has been another episode of Late Nights with the Autodidact.

1 Like

Glad you found a solution – a virtual member function seems like a solid C++ way of doing somthing like that.

In case you or other readers are looking for some inspiration on a different approach to that, I’ve managed it with a templated base processor class, where the template type is a ParameterProvider struct which e.g. is required to have a function like
AudioProcessorValueTreeState::ParameterLayout createParameterLayout() (and some more in my case, like e.g. a list of parameters that should mark a preset “dirty” if they are changed or the bypass parameter).

The plugins processor is then instantiated like

class MyProcessor : public ProcessorBase<MyParameterProvider>
{

}

The processor base class then contains the APVTS as a public member

This is my base class

And this is an example parameters struct

1 Like

Hey, that looks pretty great too. Thanks for sharing your approach to it!