Shouldn't AudioProcessorGraph dispatch prepareToPlay() to all nodes?


#1

Just struggled with an issue that resulted from prepareToPlay() not being dispatched to all nodes of an AudioProcessorGraph().

Since reset(), releaseResources() and others are dispatched to all nodes, what is the reason for not doing this also with prepareToPlay() ?

Background: I’m running a graph with multiple synths (implemented as AudioProcessor) inside a plugin and auval crashes due to wrong buffer sizes in the graph after increasing the block size for render tests. (Juce 4.3.0). Still struggling how to fix this.


#2

It should…

in AudioProcessorGraph::buildRenderingSequence() it loops through all the nodes and calls AudioProcessorGraph::Node::prepare() which calls each node’s setRateAndBufferSizeDetails() and also prepareToPlay()

You may need to force the graph to rebuild the rendering sequence… I added a public method:

void refreshGraph() { triggerAsyncUpdate(); }

which I use to do that when required.

Rail


#3

Ok, found it. However the nodes do so only if they think they are not prepared yet (local state).

It currently looks to me that, once a graph was prepared with some sample rate and buffer size, it will never re-prepare its nodes with a different rate again. So if a host call goes to prepareToPlay() twice, the second call will have no effect on the nodes.


#4

Hence the

refreshGraph()

method I added which lets you refresh the graph when needed.

Rail


#5

Of course you don’t want to do that every time you receive a prepareToPlay() in your main processor…

Rather do something like:

void MainContentComponent::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
if (m_dSampleRate != sampleRate)
    {
    m_dSampleRate = sampleRate;
    
    :
    }

m_iBufferSize = samplesPerBlockExpected;

m_MidiCollector.reset (m_dSampleRate);

m_KeyboardState.reset();

m_TransportSource.prepareToPlay (m_iBufferSize, m_dSampleRate);

m_pMainGraph->setRateAndBufferSizeDetails (m_dSampleRate, m_iBufferSize);

m_pMainGraph->prepareToPlay (m_dSampleRate, m_iBufferSize);
}

which is not ASynchronous.

Rail


#6

It’s even easier: A simple setRateAndBufferSizeDetails() sent to the graph will do it:

void MyAudioProcessor::prepareToPlay (double sampleRate_, int blockSize_)
{
  graph.setRateAndBufferSizeDetails (sampleRate_, blockSize_);
  graph.prepareToPlay (sampleRate_, blockSize_);
}

That fixed it. Thanks so much for pointing me into that direction.