mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
AudioProcessorGraph: Allow triggering manual rebuild, and avoid rebuilding if nothing has changed
This commit is contained in:
parent
c56102f50a
commit
eaa6dfc3ee
2 changed files with 72 additions and 10 deletions
|
|
@ -351,14 +351,14 @@ public:
|
|||
/* Called from prepareToPlay and releaseResources with the PrepareSettings that should be
|
||||
used next time the graph is rebuilt.
|
||||
*/
|
||||
void setState (Optional<PrepareSettings> newSettings)
|
||||
void setState (std::optional<PrepareSettings> newSettings)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock (mutex);
|
||||
next = newSettings;
|
||||
}
|
||||
|
||||
/* Call from the audio thread only. */
|
||||
Optional<PrepareSettings> getLastRequestedSettings() const { return next; }
|
||||
std::optional<PrepareSettings> getLastRequestedSettings() const { return next; }
|
||||
|
||||
/* Call from the main thread only!
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ public:
|
|||
|
||||
Returns the settings that were applied to the nodes.
|
||||
*/
|
||||
Optional<PrepareSettings> applySettings (const Nodes& n)
|
||||
std::optional<PrepareSettings> applySettings (const Nodes& n)
|
||||
{
|
||||
const auto settingsChanged = [this]
|
||||
{
|
||||
|
|
@ -411,7 +411,7 @@ public:
|
|||
preparedNodes.clear();
|
||||
}
|
||||
|
||||
if (current.hasValue())
|
||||
if (current.has_value())
|
||||
{
|
||||
for (const auto& node : n.getNodes())
|
||||
{
|
||||
|
|
@ -433,7 +433,7 @@ public:
|
|||
private:
|
||||
std::mutex mutex;
|
||||
std::set<NodeID> preparedNodes;
|
||||
Optional<PrepareSettings> current, next;
|
||||
std::optional<PrepareSettings> current, next;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1447,6 +1447,40 @@ private:
|
|||
int latencySamples = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Holds information about a particular graph configuration, without sharing ownership of any
|
||||
graph nodes. Can be checked for equality with other RenderSequenceSignature instances to see
|
||||
whether two graph configurations match.
|
||||
*/
|
||||
class RenderSequenceSignature
|
||||
{
|
||||
auto tie() const { return std::tie (settings, connections, nodes); }
|
||||
|
||||
public:
|
||||
RenderSequenceSignature (const PrepareSettings s, const Nodes& n, const Connections& c)
|
||||
: settings (s), connections (c), nodes (getNodeIDs (n)) {}
|
||||
|
||||
bool operator== (const RenderSequenceSignature& other) const { return tie() == other.tie(); }
|
||||
bool operator!= (const RenderSequenceSignature& other) const { return tie() != other.tie(); }
|
||||
|
||||
private:
|
||||
static std::vector<AudioProcessorGraph::NodeID> getNodeIDs (const Nodes& n)
|
||||
{
|
||||
const auto& nodeRefs = n.getNodes();
|
||||
std::vector<AudioProcessorGraph::NodeID> result;
|
||||
result.reserve ((size_t) nodeRefs.size());
|
||||
|
||||
for (const auto& node : nodeRefs)
|
||||
result.push_back (node->nodeID);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PrepareSettings settings;
|
||||
Connections connections;
|
||||
std::vector<AudioProcessorGraph::NodeID> nodes;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/* Facilitates wait-free render-sequence updates.
|
||||
|
||||
|
|
@ -1687,6 +1721,14 @@ public:
|
|||
topologyChanged (UpdateKind::sync);
|
||||
}
|
||||
|
||||
void rebuild()
|
||||
{
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
handleAsyncUpdate();
|
||||
else
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
for (auto* n : getNodes())
|
||||
|
|
@ -1757,22 +1799,30 @@ private:
|
|||
for (const auto node : nodes.getNodes())
|
||||
setParentGraph (node->getProcessor());
|
||||
|
||||
auto sequence = std::make_unique<RenderSequence> (*newSettings, nodes, connections);
|
||||
owner->setLatencySamples (sequence->getLatencySamples());
|
||||
renderSequenceExchange.set (std::move (sequence));
|
||||
const RenderSequenceSignature newSignature (*newSettings, nodes, connections);
|
||||
|
||||
if (std::exchange (lastBuiltSequence, newSignature) != newSignature)
|
||||
{
|
||||
auto sequence = std::make_unique<RenderSequence> (*newSettings, nodes, connections);
|
||||
owner->setLatencySamples (sequence->getLatencySamples());
|
||||
renderSequenceExchange.set (std::move (sequence));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastBuiltSequence.reset();
|
||||
renderSequenceExchange.set (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AudioProcessorGraph* owner = nullptr;
|
||||
Nodes nodes;
|
||||
Connections connections;
|
||||
NodeStates nodeStates;
|
||||
RenderSequenceExchange renderSequenceExchange;
|
||||
NodeID lastNodeID;
|
||||
std::optional<RenderSequenceSignature> lastBuiltSequence;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1799,6 +1849,7 @@ AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (NodeID x) const
|
|||
bool AudioProcessorGraph::disconnectNode (NodeID nodeID, UpdateKind updateKind) { return pimpl->disconnectNode (nodeID, updateKind); }
|
||||
void AudioProcessorGraph::releaseResources() { return pimpl->releaseResources(); }
|
||||
bool AudioProcessorGraph::removeIllegalConnections (UpdateKind updateKind) { return pimpl->removeIllegalConnections (updateKind); }
|
||||
void AudioProcessorGraph::rebuild() { return pimpl->rebuild(); }
|
||||
void AudioProcessorGraph::reset() { return pimpl->reset(); }
|
||||
bool AudioProcessorGraph::canConnect (const Connection& c) const { return pimpl->canConnect (c); }
|
||||
bool AudioProcessorGraph::isConnected (const Connection& c) const noexcept { return pimpl->isConnected (c); }
|
||||
|
|
|
|||
|
|
@ -210,8 +210,11 @@ public:
|
|||
*/
|
||||
enum class UpdateKind
|
||||
{
|
||||
sync, ///< Indicates that the graph should be rebuilt immediately after modification.
|
||||
async ///< Indicates that the graph rebuild should be deferred.
|
||||
sync, ///< Graph should be rebuilt immediately after modification.
|
||||
async, ///< Graph rebuild should be delayed. If you make several changes to the graph
|
||||
///< inside the same call stack, these changes will be applied in one go.
|
||||
none ///< Graph should not be rebuilt automatically. Use rebuild() to trigger a graph
|
||||
///< rebuild.
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -312,6 +315,14 @@ public:
|
|||
*/
|
||||
bool removeIllegalConnections (UpdateKind = UpdateKind::sync);
|
||||
|
||||
/** Rebuilds the graph if necessary.
|
||||
|
||||
This function will only ever rebuild the graph on the main thread. If this function is
|
||||
called from another thread, the rebuild request will be dispatched asynchronously to the
|
||||
main thread.
|
||||
*/
|
||||
void rebuild();
|
||||
|
||||
//==============================================================================
|
||||
/** A special type of AudioProcessor that can live inside an AudioProcessorGraph
|
||||
in order to use the audio that comes into and out of the graph itself.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue