From cbc43e5d683bf0b9eb0a27d4a35a183bf7ac428e Mon Sep 17 00:00:00 2001 From: Joelle Plow Date: Sun, 24 Sep 2023 22:49:59 +0100 Subject: [PATCH 1/4] NodeGraph nodes have parents --- src/signal/NodeGraph.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/signal/NodeGraph.h b/src/signal/NodeGraph.h index 0e1091e..e322c0d 100644 --- a/src/signal/NodeGraph.h +++ b/src/signal/NodeGraph.h @@ -16,17 +16,22 @@ class NodeGraph std::vector> inputs; + NodeGraph* parent = nullptr; + public: NodeGraph( std::string head ) : head( head ) { } - void addInput( std::shared_ptr input ) + std::shared_ptr addInput( std::shared_ptr input = std::make_shared() ) { inputs.push_back( input ); + input->parent = this; + return input; } + std::string toString() { std::string shorthand = toInlineString(); From 3429af36689f19d21f644dcc5503619f0a6f51bd Mon Sep 17 00:00:00 2001 From: Joelle Plow Date: Sun, 24 Sep 2023 22:50:20 +0100 Subject: [PATCH 2/4] remove defunct comments --- src/signal/SignalStructureAnalysis.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/signal/SignalStructureAnalysis.h b/src/signal/SignalStructureAnalysis.h index 61b90e5..35d319f 100644 --- a/src/signal/SignalStructureAnalysis.h +++ b/src/signal/SignalStructureAnalysis.h @@ -44,14 +44,10 @@ class SignalStructureAnalysis */ class NodeGraphExtracter { - /** - * These breadcrumb pointers are used to circuit break when analyising signals that contain feedback - */ + /// These breadcrumb pointers are used to circuit break when analyising + /// signals that contain feedback Breadcrumbs breadcrumbs; - // TODO: there could be a separate class `Breadcrumbs` to make this behaviour a bit more - // standard - public: std::shared_ptr startingPoint; NodeGraphExtracter( std::shared_ptr startingPoint ) From 5206ad7fcabb83064f9641083a807ecc4571a08d Mon Sep 17 00:00:00 2001 From: Joelle Plow Date: Mon, 25 Sep 2023 01:28:01 +0100 Subject: [PATCH 3/4] Show feedback using absolute paths --- src/signal/NodeGraph.h | 35 +++++++++++++++++-- src/signal/SignalStructureAnalysis.h | 38 +++++++++++++++------ src/signal/SignalStructureAnalysis.test.cpp | 2 +- 3 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/signal/NodeGraph.h b/src/signal/NodeGraph.h index e322c0d..293eb16 100644 --- a/src/signal/NodeGraph.h +++ b/src/signal/NodeGraph.h @@ -10,16 +10,17 @@ */ class NodeGraph { -protected: /** The name of the node */ - const std::string head; +public: + std::string head; +protected: std::vector> inputs; NodeGraph* parent = nullptr; public: - NodeGraph( std::string head ) + NodeGraph( std::string head = "unnamed node" ) : head( head ) { } @@ -82,5 +83,33 @@ class NodeGraph } +public: + std::vector backtrace() + { + std::vector trace; + NodeGraph* ptr = this; + while ( ptr ) + { + trace.push_back( ptr ); + ptr = ptr->parent; + } + return trace; + } + + std::string absolutePath() + { + std::stringstream str; + str << "~"; + auto bt = backtrace(); + for ( int i = bt.size() - 1; i > 0; --i ) + { + auto P = bt[i], C = bt[i - 1]; + int j = 0; + while ( j < P->inputs.size() && P->inputs[j].get() != C ) + ++j; + str << "/" << j; + } + return str.str(); + } // TODO: add parsing methods }; diff --git a/src/signal/SignalStructureAnalysis.h b/src/signal/SignalStructureAnalysis.h index 35d319f..2b40b60 100644 --- a/src/signal/SignalStructureAnalysis.h +++ b/src/signal/SignalStructureAnalysis.h @@ -4,6 +4,7 @@ #include "./Constructors.h" #include "NodeGraph.h" #include "Signal.h" +#include #include #include #include @@ -60,25 +61,42 @@ class SignalStructureAnalysis return extractNodeGraph( startingPoint ); } - std::shared_ptr extractNodeGraph( std::shared_ptr signal ) + std::map map; + + std::shared_ptr extractNodeGraph( + std::shared_ptr signal, + std::shared_ptr usingNode = std::make_shared() ) { // Check for for feedback if ( breadcrumbs.crumb( signal ) ) - return std::make_shared( "FEEDBACK" ); + { + auto other = map[signal.get()]; + usingNode->head = other->absolutePath(); + return usingNode; + } + else + { + map[signal.get()] = usingNode.get(); + } // Handle constants as a special case if ( isConstant( signal ) ) - return std::make_shared( stringifyConstant( signal ) ); - - // Default handling - auto node = std::make_shared( signalProcessName( signal ) ); - for ( auto input : signal->inputs ) { - auto subNode = extractNodeGraph( input->abstract_ptr() ); - node->addInput( subNode ); + usingNode->head = stringifyConstant( signal ); + return usingNode; + } + else + { + // Default handling + usingNode->head = signalProcessName( signal ); + for ( auto input : signal->inputs ) + { + auto childNode = usingNode->addInput(); + extractNodeGraph( input->abstract_ptr(), childNode ); + } + return usingNode; } - return node; } }; diff --git a/src/signal/SignalStructureAnalysis.test.cpp b/src/signal/SignalStructureAnalysis.test.cpp index 81db03d..75c8702 100644 --- a/src/signal/SignalStructureAnalysis.test.cpp +++ b/src/signal/SignalStructureAnalysis.test.cpp @@ -18,6 +18,6 @@ TEST_CASE( "Generating a structure string for a signal with feedback" ) auto osc = usaw( 30 ); osc->frequency = 150 + 100 * osc; auto signal = sineWavetable( osc ); - std::string graph = SignalStructureAnalysis::signalGraphStructureString( signal ); + std::string graph = SignalStructureAnalysis::signalGraphStructureString( signal + 2 ); std::cerr << "GRAPH:\n" << graph << "\n"; } From 7bb92198215e76519ab477a3cfeef3c99928d1e7 Mon Sep 17 00:00:00 2001 From: Joelle Plow Date: Mon, 25 Sep 2023 01:57:59 +0100 Subject: [PATCH 4/4] Relative paths, AT LAST! Its been a tought one today zzzzz --- src/signal/NodeGraph.h | 37 ++++++++++++++++++++++++++++ src/signal/SignalStructureAnalysis.h | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/signal/NodeGraph.h b/src/signal/NodeGraph.h index 293eb16..5ca0a53 100644 --- a/src/signal/NodeGraph.h +++ b/src/signal/NodeGraph.h @@ -83,6 +83,7 @@ class NodeGraph } + // TODO: Move all the path stuff into a separate class public: std::vector backtrace() { @@ -101,6 +102,13 @@ class NodeGraph std::stringstream str; str << "~"; auto bt = backtrace(); + str << pathifyBacktrace( bt ); + return str.str(); + } + + static std::string pathifyBacktrace( std::vector bt ) + { + std::stringstream str; for ( int i = bt.size() - 1; i > 0; --i ) { auto P = bt[i], C = bt[i - 1]; @@ -109,6 +117,35 @@ class NodeGraph ++j; str << "/" << j; } + + return str.str(); + } + + static std::string relativePath( NodeGraph* from, NodeGraph* to ) + { + std::vector fromBt = from->backtrace(), toBt = to->backtrace(); + + if ( fromBt[fromBt.size() - 1] != toBt[toBt.size() - 1] ) + // TODO: Use proper exceptions + throw 1; + + // Remove the shared root of the backtraces + while ( fromBt[fromBt.size() - 1] == toBt[toBt.size() - 1] ) + { + fromBt.pop_back(); + toBt.pop_back(); + } + + std::stringstream str; + for ( int i = 0; i < fromBt.size(); ++i ) + { + if ( i != 0 ) + str << "/"; + str << ".."; + } + + str << pathifyBacktrace( toBt ); + return str.str(); } // TODO: add parsing methods diff --git a/src/signal/SignalStructureAnalysis.h b/src/signal/SignalStructureAnalysis.h index 2b40b60..6b77e93 100644 --- a/src/signal/SignalStructureAnalysis.h +++ b/src/signal/SignalStructureAnalysis.h @@ -72,7 +72,7 @@ class SignalStructureAnalysis if ( breadcrumbs.crumb( signal ) ) { auto other = map[signal.get()]; - usingNode->head = other->absolutePath(); + usingNode->head = NodeGraph::relativePath( usingNode.get(), other ); return usingNode; } else