How to pass a pointer to a node in AudioSourceGraph in order to access the custom parameters of the class inside the node later

Hello JUCE community,

I have a question: I’m actually working to a sort of mixer which permits to reproduce audio files and MIDI output. Is there a way to add a node through the definition of a pointer, in order to access the custom variables inside the node’s class, aside from the AudioParameters fields?

For example, is there a way to perform something like this?:

    std::unique_ptr<mixerChannel> mixerPtr;
    mixerPtr.reset(new mixerChannel());
    nodesForMixer.insert(idx, mainProcessor->addNode(mixerPtr.get()));

Actually, I’m adding mixerChannel nodes in this way:

nodesForMixer.insert(idx, mainProcessor->addNode(std::make_unique<mixerChannel>()));

Where idx is the channel of my mixer, and juce::ReferenceCountedArray<Node> nodesForMixer is a ReferenceCountedArray defined in my main audio processor header.

Your class “mixerChannel” should be named “MixerChannel” to distinguish between variables, structures, and so on. The class gets all capitals.

You’re using

…reset(new classname)

You should use

my_unique_ptr = std::make_unique<classname>(args..);

I’m unsure of what you’re really trying to do because it isn’t explained in too much detail, but what I can gather is you want to pass an object “mixer_object” to your mixer as a pointer?
Is there a reason you don’t want to deference it like

insertNode(*ptr)
1 Like

Hello HurricaneAudio. First of all, thank you for answering this post :slightly_smiling_face:

You’re right! I corrected immediately the name of the class! :grimacing:

I know, but actually I would like to mantain the pointer “externally”, in order to access it and modify the variables inside my class later during the execution of my program.

I’m developing a program able to perform the following things:

  1. To instantiate music by reading randomly in a folder some files written by a musician
  2. To instantiate a MIDI loop by reading the UV information of the visible constellations contained in a database. This task is accomplished through a Python script.
  3. Once all the requested tracks are added to the AudioSourceGraph, I would like to access the classes contained inside the nodes for modifying some parameters during the execution of the program (e.g.: the file read by the MixerChannel track or the UV information that has to be sonified by the “Constellation” track).

I hope that this could give you some hints.

E.g.: once added a node in my graph, like insert(*aNode<aClass>), I would like to access later the class aClass of that node. I implemented the addition of the node through the exploitation of a juce::ReferenceCountedArray<Node> since I read the tutorial on the AudioProcessorGraph available here: https://docs.juce.com/master/tutorial_audio_processor_graph.html

Ok, I found in the forum a topic which is quite similar to my problem:
https://forum.juce.com/t/access-an-audioprocessorgraph-ptr/36330

So: there’s no way to access the variables of the class inside the node. The only way is to declare AudioParameters variables and then use the getProcessor() -> getParameters() method: is it correct?

I don’t really get what you mean by

access the variables of the class inside the node

You can always do

auto mixerChannel = mixerPtr.get();
mainProcessor->addNode(mixerPtr);

and mixerChannel will be valid until mixerPtr is deleted by mainProcessor after you’ve
done mainProcessor->removeNode() or similar.

Is that what you’re after?

1 Like

Hello oxxyyd.

Yeah, I would like to obtain a pointer which remains external to the node, in order to access the class added to the node later.

However, with your code I get the following error: “there’s no conversion from std::unique_ptr<MixerChannel, std::default_delete<MixerChannel>> to std::unique_ptr<juce::AudioProcessor, std::default_delete<AudioProcessor>> defined by the user”

I think you have to reveal more of your code. What is mainProcessor e.g? I thought it was an audioProcessor of some kind, but as far as I can see, juce::AudioProcessor doesn’t have a member called addNode(), so I’m a little lost here…

1 Like

Oh sorry, I thought I would be clear even without the code.

mainProcessor is an AudioProcessorGraph. I was trying to add a node in my graph.

If it is necessary, I can share the code of my main AudioProcessor

Oh I thought so, but wasn’t sure. If you omit the class name of you variables it’s a good thing to name them after their classes, like mainAudioProcessorgraph or just audioProcessorgraph in short code excerpts.

Where do you get the error?

1 Like

Oh sorry, I’m a newbie in this forum :slightly_smiling_face:

I get the error at the third line:

    std::unique_ptr<MixerChannel> mixerPtr = std::make_unique<MixerChannel>();
    auto mixerChannel = mixerPtr.get();
    juce::AudioProcessorGraph mainProcessor->addNode(mixerPtr);

i.e. when I try to add the node in the AudioProcessorGraph called mainProcessor

Don’t be. Most of us have been that

What kind of beast is MixerChannel? The error code seems to complain about it’s not an AudioProcessor (or a descendent thereof).

1 Like

Since I followed the cascading-plugin effects tutorial (https://docs.juce.com/master/tutorial_audio_processor_graph.html), I implemented the ProcessorBase class:

#pragma once
#include <JuceHeader.h>

class ProcessorBase : public juce::AudioProcessor
{
public:
    //==============================================================================
    ProcessorBase()
        : AudioProcessor(BusesProperties().withInput("Input", juce::AudioChannelSet::stereo())
            .withOutput("Output", juce::AudioChannelSet::stereo()))
    {}

    //==============================================================================
    void prepareToPlay(double, int) override {}
    void releaseResources() override {}
    void processBlock(juce::AudioSampleBuffer&, juce::MidiBuffer&) override {}

    //==============================================================================
    juce::AudioProcessorEditor* createEditor() override { return nullptr; }
    bool hasEditor() const override { return false; }

    //==============================================================================
    const juce::String getName() const override { return {}; }
    bool acceptsMidi() const override { return false; }
    bool producesMidi() const override { return false; }
    double getTailLengthSeconds() const override { return 0; }

    //==============================================================================
    int getNumPrograms() override { return 0; }
    int getCurrentProgram() override { return 0; }
    void setCurrentProgram(int) override {}
    const juce::String getProgramName(int) override { return {}; }
    void changeProgramName(int, const juce::String&) override {}

    //==============================================================================
    void getStateInformation(juce::MemoryBlock&) override {}
    void setStateInformation(const void*, int) override {}

private:
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ProcessorBase)
};

Then, I implemented the MixerChannel class as it follows:

#include <JuceHeader.h>
#include "ProcessorBase.h"

class MixerChannel : public ProcessorBase
{
//  Rest of the code //
}

Hmm, if you update your code to below, will that compile?

auto mixerPtr = std::make_unique<MixerChannel>();
auto mixerChannel = mixerPtr.get();

juce::AudioProcessorGraph *mainProcessor;
mainProcessor->addNode(std::move(mixerPtr));

1 Like

Yes, the code compile, but now JUCE raises the following error:

JUCE Assertion failure in juce_ReferenceCountedObject.h:394

The error is reported in juce_ReferenceCountedObject.h, precisely here:

    ReferencedType* operator->() const noexcept
    {
        jassert (referencedObject != nullptr); // null pointer method call!
        return referencedObject;
    }

Why are you using a ReferenceCountedArray for nodesForMixer? The nodes are already handled by the AudioProcessorGraph. Why not use an ordinary juce::Array or a std::vector instead?

1 Like

oxxyyd, thank you! I found a way to add the node and access the class!!!

    auto mixerPtr = std::make_unique<MixerChannel>();
    auto mixerChannel = mixerPtr.get();

    juce::ReferenceCountedArray nodesForMixer.insert(idx, juce::AudioProcessorGraph mainProcessor->addNode(std::move(mixerPtr)));
    mixerChannel->transportPtr.get()->start();

Because otherwise the error that I reported in the previous post occurs. Onestly, I did not try with a standard vector… I will give it a chance