AudioProcessorGraph for a VST Plugin

Guys, I’m trying to use AudioProcessorGraph instead of AudioProcessor for my ST Plugin. So I can play back several VSTs connected to each other. But, I’m a bit lost on how I make this to work. In my Filter class, I switched AudioProcessor for AudioProcessorGraph.

class FilterComponent : public AudioProcessorGraph,//AudioProcessor, public ChangeBroadcaster

Everything works out, but there’s no sound. Here’s how I add the first VST and connect it out:

[code]FilterComponent::FilterComponent()
{
// Load VST //
File vstLoad = T("\TEST.DLL"));
AudioPluginFormatManager::getInstance()->addDefaultFormats();
String errorMessage;
PluginDescription PlugDesc;
PlugDesc.pluginFormatName = T(“vst”);
PlugDesc.fileOrIdentifier = vstLoad.getFullPathName();

	AudioProcessorGraph::Node* node = 0;

	uint32 AUDIOINID = 0;
	uint32 VSTID = 0;
	uint32 MIDIINID = 0;
	uint32 AUDIOOUTID = 0;

	
	VstInstance = AudioPluginFormatManager::getInstance()->createPluginInstance (PlugDesc, errorMessage);
	node = addNode(VstInstance);
	VSTID = node->id;

	{
		AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);
		p.fillInPluginDescription (PlugDesc);
		node = addNode(AudioPluginFormatManager::getInstance()->createPluginInstance (PlugDesc, errorMessage));
		AUDIOINID = node->id;
	}

	{
		AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);
		p.fillInPluginDescription (PlugDesc);
		node = addNode(AudioPluginFormatManager::getInstance()->createPluginInstance (PlugDesc, errorMessage));
		MIDIINID = node->id;
	}

	{
		AudioProcessorGraph::AudioGraphIOProcessor p (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
		p.fillInPluginDescription (PlugDesc);
		node = addNode(AudioPluginFormatManager::getInstance()->createPluginInstance (PlugDesc, errorMessage));
		AUDIOOUTID = node->id;
	}

	if (!addConnection(AUDIOINID,0,VSTID,0)) Alert;
	if (!addConnection(AUDIOINID,1,VSTID,1)) Alert;

	if (!addConnection(MIDIINID,midiChannelIndex,VSTID,midiChannelIndex)) Alert;

	if (!addConnection(VSTID,0,AUDIOOUTID,0)) Alert;
	if (!addConnection(VSTID,1,AUDIOOUTID,1)) Alert;

}[/code]

Any help would be much appreciated.

Best Regards, WilliamK

I’ve pasted some code from different places, so I hope it all makes sense.

This is the main filter: .h

[code]class MyFilter : public AudioProcessor,
public ChangeBroadcaster
{
public:
MyFilter();
~MyFilter();

void prepareToPlay (double sampleRate, int samplesPerBlock);
void releaseResources();

void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);

AudioProcessorEditor* createEditor();

const String getName() const;

int getNumParameters();

float getParameter (int index);
void setParameter (int index, float newValue);

const String getParameterName (int index);
const String getParameterText (int index);

const String getInputChannelName (const int channelIndex) const;
const String getOutputChannelName (const int channelIndex) const;
bool isInputChannelStereoPair (int index) const;
bool isOutputChannelStereoPair (int index) const;

bool acceptsMidi() const;
bool producesMidi() const;

int getNumPrograms()                                        { return 0; }
int getCurrentProgram()                                     { return 0; }
void setCurrentProgram (int index)                          { }
const String getProgramName (int index)                     { return String::empty; }
void changeProgramName (int index, const String& newName)   { }

void getStateInformation (MemoryBlock& destData);
void setStateInformation (const void* data, int sizeInBytes);

juce_UseDebuggingNewOperator

private:
AudioProcessorGraph graph;

AudioProcessorGraph::AudioGraphIOProcessor* ioProcIn;
AudioProcessorGraph::AudioGraphIOProcessor* ioProcOut;
AudioProcessorGraph::AudioGraphIOProcessor* ioProcMidiIn;

AudioProcessorGraph::Node* ioProcInNode;
AudioProcessorGraph::Node* ioProcOutNode;
AudioProcessorGraph::Node* ioProcMidiInNode;

MyAudioProcessor* myProcessor;

};[/code]
.cpp

[code]MyFilter::MyFilter()
: ioProcIn (0),
ioProcOut (0),
ioProcMidiIn (0),
ioProcOutNode (0),
ioProcMidiInNode (0)
{
ioProcOut = new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
ioProcMidiIn = new AudioProcessorGraph::AudioGraphIOProcessor (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);

ioProcOutNode = graph.addNode (ioProcOut);
ioProcMidiInNode = graph.addNode (ioProcMidiIn);

AudioProcessorGraph::Node* sbNode = graph.addNode (myProcessor = new MyAudioProcessor());
myProcessor->setNodeID (sbNode->id);

}

MyFilter::~MyFilter()
{
}

//==============================================================================
const String MyFilter::getName() const
{
return “My Plugin”;
}

int MyFilter::getNumParameters()
{
return 1;
}

float MyFilter::getParameter (int index)
{
return 0.0f;
}

void MyFilter::setParameter (int index, float newValue)
{
}

const String MyFilter::getParameterName (int index)
{
return String::empty;
}

const String MyFilter::getParameterText (int index)
{
return String::empty;
}

const String MyFilter::getInputChannelName (const int channelIndex) const
{
return String (channelIndex + 1);
}

const String MyFilter::getOutputChannelName (const int channelIndex) const
{
return String (channelIndex + 1);
}

bool MyFilter::isInputChannelStereoPair (int index) const
{
return false;
}

bool MyFilter::isOutputChannelStereoPair (int index) const
{
return false;
}

bool MyFilter::acceptsMidi() const
{
return true;
}

bool MyFilter::producesMidi() const
{
return true;
}

//==============================================================================
void MyFilter::prepareToPlay (double sampleRate, int samplesPerBlock)
{
// do your pre-playback setup stuff here…
graph.setPlayConfigDetails (getNumInputChannels(), getNumOutputChannels(), sampleRate, samplesPerBlock);

graph.prepareToPlay (sampleRate, samplesPerBlock);


graph.addConnection (myProcessor->getNodeID(), 0, ioProcOutNode->id, 0);
graph.addConnection (myProcessor->getNodeID(), 1, ioProcOutNode->id, 1);

}

void MyFilter::releaseResources()
{
// when playback stops, you can use this as an opportunity to free up any
// spare memory, etc.

graph.releaseResources();

}

void MyFilter::processBlock (AudioSampleBuffer& buffer,
MidiBuffer& midiMessages)
{
graph.processBlock (buffer, midiMessages);
}

//==============================================================================
AudioProcessorEditor* MyFilter::createEditor()
{
return new MainEditorComponent (this);
}

//==============================================================================
void MyFilter::getStateInformation (MemoryBlock& destData)
{
}

void MyFilter::setStateInformation (const void* data, int sizeInBytes)
{
}[/code]

And I’m hooking up a MyAudioProcessor* in to the grap, just for this example I’m making all the connections in prepareToPlay method.

Here’s MyAudioProcessor .h

[code]class MyAudioProcessor : public AudioProcessor
{
public:
MyAudioProcessor();
~MyAudioProcessor();

const String getName() const;
void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
void releaseResources();
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);

const String getInputChannelName (const int channelIndex) const;
const String getOutputChannelName (const int channelIndex) const;

bool isInputChannelStereoPair (int index) const;
bool isOutputChannelStereoPair (int index) const;

bool acceptsMidi() const;
bool producesMidi() const;

AudioProcessorEditor* createEditor() { return 0; }

int getNumParameters() { return 1; }
const String getParameterName (int parameterIndex) { return String::empty; }
float getParameter (int parameterIndex) { return 0.0f; }
const String getParameterText (int parameterIndex) { return String::empty; }
void setParameter (int parameterIndex, float newValue) {  }

int getNumPrograms() { return 1; }
int getCurrentProgram() { return 0; }
void setCurrentProgram (int index) { }
const String getProgramName (int index) { return String::empty; }
void changeProgramName (int index, const String& newName) { }

void getStateInformation (MemoryBlock& destData) { }
void getCurrentProgramStateInformation (MemoryBlock& destData) { }
void setStateInformation (const void* data, int sizeInBytes) { }

void setNodeID (int32 newNodeID) { nodeID = newNodeID; }
int32 getNodeID() { return nodeID; }

private:
int32 nodeID;
MixerAudioSource* mixer;
};[/code]

.cpp

MyAudioProcessor::MyAudioProcessor() { } MyAudioProcessor::~MyAudioProcessor() { } const String MyAudioProcessor::getName() const { return "My Audio Processor"; } void MyAudioProcessor::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) { setPlayConfigDetails (0, 2, sampleRate, estimatedSamplesPerBlock); } void MyAudioProcessor::releaseResources() { } void MyAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { } const String MyAudioProcessor::getInputChannelName (const int channelIndex) const { return String (channelIndex + 1); } const String MyAudioProcessor::getOutputChannelName (const int channelIndex) const { return String (channelIndex + 1); } bool MyAudioProcessor::isInputChannelStereoPair (int index) const { return false; } bool MyAudioProcessor::isOutputChannelStereoPair (int index) const { return false; } bool MyAudioProcessor::acceptsMidi() const { return false; } bool MyAudioProcessor::producesMidi() const { return false; }

HTH


That's how I actually got everything to sound, when I was playing around with the graph stuff...

That’s how I actually got everything to sound, when I was playing around with the graph stuff…

Thanks guys, I’m checking it out right now. :mrgreen:

Best Regards, WilliamK

IT WORKS!!! Now I just need to clean up the mess so I can share the code up. :oops:

Thanks for the help, much appreciated. I was doing things the wrong way, now its all clear and I understand how to do it the right way. 8)

Wk

Well I’m not 100% percent sure that it’s the right way, but it certainly works.

The docs for:

setPlayConfigDetails

say that it’s:

This was brought up here:
http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=4188&p=22083&hilit=AudioProcessorGraph#p22083

but never answered…

This is really great, I see what you are doing there, creating your own nodes which can be volume or pan changes, or whatever is needed. This is cool. I also got some nice MIDI VST processors, which can also be handy with the AudioGraph. :mrgreen:

Thanks again. Give me some time now, prob later next week I will have something else to show. I need to check how I will handle a few things. For instance, the parameters for when you have multiple VSTs loaded. Right now Wusik Station uses 2,000 parameters, so imagine if you have 10 instances loaded. :shock: I could just set it to 999,999 parameters. But then there’s the program name, I guess that one could be the current active VST. :wink: I will figure out things eventually, as I do things.

Now is time to go, thanks.

Best Regards, WilliamK