MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NodeGraphManager.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "NodeSpec.hpp"
4#include "RootNode.hpp"
5
6namespace MayaFlux::Nodes {
7
8using TokenChannelProcessor = std::function<std::vector<double>(RootNode*, uint32_t)>;
9using TokenSampleProcessor = std::function<double(RootNode*, uint32_t)>;
10
11namespace Network {
12 class NodeNetwork;
13} // namespace Network
14
15/**
16 * @class NodeGraphManager
17 * @brief Central manager for the computational processing node graph
18 *
19 * The NodeGraphManager is the primary interface for creating, connecting, and managing
20 * processing nodes in the MayaFlux engine. It serves as a registry for all nodes
21 * and maintains the root nodes for each processing channel and processing domain (token).
22 *
23 * Features:
24 * - Multi-modal (token-based) processing: Supports multiple independent processing domains
25 * (e.g., AUDIO_RATE, VISUAL_RATE, CUSTOM_RATE), each with its own set of channels and root nodes.
26 * - Per-channel root nodes: Each processing domain can have multiple channels, each with its own RootNode.
27 * - Node registry: Nodes are registered by string identifier for easy lookup and connection.
28 * - Flexible connection: Nodes can be connected by reference or by identifier, supporting both direct and named graph construction.
29 * - Subsystem token processors: Allows registration of custom processing functions for each token, enabling efficient backend-specific processing.
30 *
31 * This class provides methods to:
32 * - Create nodes of any type with automatic registration
33 * - Connect nodes to form processing chains
34 * - Add nodes to channel root nodes for output
35 * - Look up nodes by their string identifiers
36 *
37 * The NodeGraphManager maintains separate root nodes for each processing channel.
38 * Channels are local to a specific processing domain.
39 * This allows for independent transformation chains per channel while sharing nodes
40 * between channels when needed.
41 */
42class MAYAFLUX_API NodeGraphManager {
43public:
44 /**
45 * @brief Creates a new NodeGraphManager
46 * @param sample_rate Sample rate for audio processing (default: 48000 Hz)
47 * @param block_size Block size for audio processing (default: 512 samples)
48 * @param frame_rate Frame rate for visual processing (default: 60 FPS)
49 *
50 * Initializes the manager with a root node for channel 0 (the default channel)
51 * in the AUDIO_RATE domain. Additional root nodes for other tokens and channels
52 * are created on demand when accessed.
53 */
54 NodeGraphManager(uint32_t sample_rate = 48000, uint32_t block_size = 512, uint32_t frame_rate = 60);
55
56 /**
57 * @brief Destroys the NodeGraphManager
58 *
59 * Cleans up all registered nodes and networks.
60 */
62
63 // NodeGraphManager is non-copyable and non-moveable due to internal atomic state
68
69 /**
70 * @brief Add node to specific processing token and channel
71 * @param node Node to add
72 * @param token Processing domain (AUDIO_RATE, VISUAL_RATE, etc.)
73 * @param channel Channel within that domain
74 *
75 * Registers the node with the specified processing domain and channel.
76 * The node's output will contribute to that token/channel's output.
77 * If the node is not already globally registered, it will be registered automatically.
78 */
79 void add_to_root(const std::shared_ptr<Node>& node, ProcessingToken token, unsigned int channel = 0);
80
81 /**
82 * @brief Remove node from a specific processing token and channel
83 * @param node Node to remove
84 * @param token Processing domain (AUDIO_RATE, VISUAL_RATE, etc.)
85 * @param channel Channel within that domain
86 *
87 * Removes the specified node from the root node of the given processing domain and channel.
88 * If the node is not found in that root, no action is taken.
89 */
90 void remove_from_root(const std::shared_ptr<Node>& node, ProcessingToken token, unsigned int channel = 0);
91
92 /**
93 * @brief Adds a node to a channel's root node by its identifier
94 * @param node_id Identifier of the node to add
95 @ param token Processing domain to add the node to (default is AUDIO_RATE)
96 * @param channel Channel index to add the node to (AUDIO_RATE domain)
97 *
98 * Looks up the node by its identifier and adds it to the specified
99 * channel's root node in the specified processing domain (default is AUDIO_RATE).
100 * Throws an exception if the node identifier is not found.
101 */
102 inline void add_to_root(const std::string& node_id, ProcessingToken token = ProcessingToken::AUDIO_RATE, unsigned int channel = 0)
103 {
104 auto node = get_node(node_id);
105 if (node) {
106 add_to_root(node, token, channel);
107 }
108 }
109
110 /**
111 * @brief Register subsystem processor for a specific token
112 * @param token Processing domain to handle (e.g., AUDIO_RATE, VISUAL_RATE)
113 * @param processor Function that receives a span of root nodes for that token
114 *
115 * Registers a custom processing function for a given processing domain (token).
116 * When process_token() is called for that token, the registered processor will
117 * be invoked with a span of all root nodes for that domain, enabling efficient
118 * backend-specific or multi-channel processing.
119 */
120 void register_token_processor(ProcessingToken token,
121 std::function<void(std::span<RootNode*>)> processor);
122
123 /**
124 * @brief Gets all channel root nodes for the AUDIO_RATE domain
125 * @param token Processing domain to get the root nodes for (default is AUDIO_RATE)
126 * @return Constant reference to the map of channel indices to root nodes
127 *
128 * This provides access to all channel root nodes of the specified domain that have been created.
129 * Useful for processing all channels or inspecting the node graph structure.
130 * For multi-modal access, use get_token_roots().
131 */
132 const std::unordered_map<unsigned int, std::shared_ptr<RootNode>>& get_all_channel_root_nodes(ProcessingToken token = ProcessingToken::AUDIO_RATE) const;
133
134 /**
135 * @brief Creates and registers a new node of the specified type
136 * @tparam NodeType The type of node to create (must derive from Node)
137 * @tparam Args Parameter types for the node's constructor
138 * @param id String identifier for the node
139 * @param args Constructor arguments for the node
140 * @return Shared pointer to the created node
141 *
142 * This template method creates a node of any type that derives from Node,
143 * passing the provided arguments to its constructor. The created node is
144 * automatically registered with the given string identifier for later lookup.
145 *
146 * Example:
147 * ```cpp
148 * auto sine = manager.create_node<Generators::Sine>("my_sine", 440.0, 0.5);
149 * auto filter = manager.create_node<Filters::LowPass>("my_filter", sine, 1000.0);
150 * ```
151 */
152 template <typename NodeType, typename... Args>
153 inline std::shared_ptr<NodeType> create_node(const std::string& id, Args&&... args)
154 {
155 auto node = std::make_shared<NodeType>(std::forward<Args>(args)...);
156 m_Node_registry[id] = node;
157 return node;
158 }
159
160 /**
161 * @brief Looks up a node by its string identifier
162 * @param id The string identifier of the node
163 * @return Shared pointer to the node, or nullptr if not found
164 *
165 * Retrieves a previously registered node using its string identifier.
166 * This allows for connecting nodes by name rather than requiring direct
167 * references to node objects.
168 */
169 std::shared_ptr<Node> get_node(const std::string& id);
170
171 /**
172 * @brief Connects two nodes by their string identifiers
173 * @param source_id Identifier of the source node
174 * @param target_id Identifier of the target node
175 *
176 * Looks up both nodes by their identifiers and establishes a connection
177 * where the output of the source node becomes an input to the target node.
178 *
179 * Equivalent to:
180 * ```cpp
181 * connect(get_node(source_id), get_node(target_id));
182 * ```
183 *
184 * Throws an exception if either node identifier is not found.
185 */
186 void connect(const std::string& source_id, const std::string& target_id);
187
188 /**
189 * @brief Checks if a node is registered with this manager
190 * @param node Node to check
191 * @return true if the node is registered, false otherwise
192 *
193 * A node is considered registered if it exists in the node registry
194 * with any identifier.
195 */
196 bool is_node_registered(const std::shared_ptr<Node>& node);
197
198 /**
199 * @brief Process all nodes in a specific token domain
200 * Calls registered processor if available, otherwise calls process() on each root
201 * @param token Processing domain to process
202 * @param num_samples Number of samples/frames to process
203 *
204 * Processes all root nodes for the specified processing domain (token).
205 * If a custom processor is registered for the token, it is called with all root nodes.
206 * Otherwise, process() is called on each root node individually.
207 */
208 void process_token(ProcessingToken token, unsigned int num_samples = 1);
209
210 /**
211 * @brief Register per-channel processor for a specific token
212 * @param token Processing domain to handle (e.g., AUDIO_RATE, VISUAL_RATE)
213 * @param processor Function that receives a single root node and returns processed data
214 *
215 * Registers a per-channel processing function that processes one root node at a time
216 * and returns the processed data. This enables coordination with buffer management
217 * on a per-channel basis.
218 */
219 void register_token_channel_processor(ProcessingToken token,
220 TokenChannelProcessor processor);
221
222 /**
223 * @brief Register per-sample processor for a specific token
224 * @param token Processing domain to handle (e.g., AUDIO_RATE, VISUAL_RATE)
225 * @param processor Function that processes a single sample and returns the processed value
226 *
227 * Registers a per-sample processing function that processes one sample at a time
228 * and returns the processed value. This is useful for low-level sample manipulation.
229 */
230 void register_token_sample_processor(ProcessingToken token,
231 TokenSampleProcessor processor);
232
233 /**
234 * @brief Process a specific channel within a token domain
235 * @param token Processing domain
236 * @param channel Channel index within that domain
237 * @param num_samples Number of samples/frames to process
238 * @return Processed data from the channel's root node
239 *
240 * Processes a single channel's root node and returns the processed data.
241 * If a custom per-channel processor is registered, it is used; otherwise,
242 * the default root node processing is performed.
243 */
244 std::vector<double> process_channel(ProcessingToken token, unsigned int channel, unsigned int num_samples);
245
246 /**
247 * @brief Process a single sample for a specific channel
248 * @param token Processing domain
249 * @param channel Channel index within that domain
250 * @return Processed sample value from the channel's root node
251 *
252 * Processes a single sample for the specified channel and returns the processed value.
253 * If a custom per-sample processor is registered, it is used; otherwise, the default
254 * root node processing is performed.
255 * As node graph manager feeds into hardware audio output, the value returned is normalized
256 */
257 double process_sample(ProcessingToken token, uint32_t channel);
258
259 /**
260 * @brief Process all channels for a token and return channel-separated data
261 * @param token Processing domain
262 * @param num_samples Number of samples/frames to process
263 * @return Map of channel index to processed data
264 *
265 * Processes all channels for a token and returns a map where each channel
266 * index maps to its processed data. This enables bulk processing while
267 * maintaining per-channel data separation.
268 */
269 std::unordered_map<unsigned int, std::vector<double>> process_token_with_channel_data(
270 ProcessingToken token, unsigned int num_samples);
271
272 /**
273 * @brief Get the number of active channels for a specific token
274 * @param token Processing domain
275 * @return Number of channels that have active root nodes
276 */
277 unsigned int get_channel_count(ProcessingToken token) const;
278
279 /**
280 * @brief Get spans of root nodes for a token (for custom processing)
281 * @param token Processing domain
282 * @return Vector of RootNode pointers for that domain
283 *
284 * Returns a vector of pointers to all root nodes for the specified processing domain.
285 * Useful for custom processing, introspection, or multi-channel operations.
286 */
287 std::vector<RootNode*> get_all_root_nodes(ProcessingToken token);
288
289 /**
290 * @brief Gets or creates the root node for a specific token and channel
291 * @param token Processing domain
292 * @param channel Channel index
293 * @return Reference to the root node for the given token and channel
294 *
295 * If the root node does not exist, it is created and registered.
296 */
297 RootNode& get_root_node(ProcessingToken token, unsigned int channel);
298
299 /**
300 * @brief Process all active tokens sequentially
301 * @param num_samples Number of samples/frames to process
302 *
303 * Iterates over all processing domains (tokens) that have active root nodes,
304 * and processes each one in turn. This enables multi-modal, multi-channel
305 * processing in a single call.
306 */
307 void process_all_tokens(unsigned int num_samples = 1);
308
309 /**
310 * @brief Gets all currently active processing tokens (domains)
311 * @return Vector of active ProcessingToken values
312 *
313 * Returns a list of all processing domains that have at least one root node.
314 * Useful for introspection and for iterating over all active domains.
315 */
316 std::vector<ProcessingToken> get_active_tokens() const;
317
318 /**
319 * @brief Gets all channel indices for a given processing token
320 * @param token Processing domain
321 * @return Vector of channel indices that have root nodes for this token
322 */
323 std::vector<unsigned int> get_all_channels(ProcessingToken token) const;
324
325 /**
326 * @brief Gets the total number of nodes registered under a given token
327 * @param token Processing domain
328 * @return Total number of nodes across all channels for this token
329 */
330 size_t get_node_count(ProcessingToken token) const;
331
332 /**
333 * @brief Prints a summary of all tokens, channels, and node counts
334 *
335 * Outputs a human-readable summary of the current node graph structure,
336 * including the number of tokens, channels, and nodes per domain.
337 * Useful for debugging and introspection.
338 */
339 void print_summary() const;
340
341 //-------------------------------------------------------------------------
342 // NodeNetwork Management
343 //-------------------------------------------------------------------------
344
345 /**
346 * @brief Add a network to a processing token
347 * @param network Network to add
348 * @param token Processing domain (AUDIO_RATE, VISUAL_RATE, etc.)
349 *
350 * Networks are processed parallel to RootNodes, managing their own
351 * internal node coordination and processing.
352 */
353 void add_network(const std::shared_ptr<Network::NodeNetwork>& network, ProcessingToken token);
354
355 /**
356 * @brief Remove a network from a processing token
357 * @param network Network to remove
358 * @param token Processing domain
359 * @param channel Channel index within that domain, optional
360 */
361 void remove_network(const std::shared_ptr<Network::NodeNetwork>& network, ProcessingToken token);
362
363 /**
364 * @brief Get all networks for a specific token
365 * @param token Processing domain
366 * @return Vector of networks registered to this token
367 */
368 [[nodiscard]] std::vector<std::shared_ptr<Network::NodeNetwork>> get_networks(ProcessingToken token, uint32_t channel = 0) const;
369
370 /**
371 * @brief Get all networks for a specific token across all channels
372 * @param token Processing domain
373 * @return Vector of networks registered to this token
374 */
375 [[nodiscard]] std::vector<std::shared_ptr<Network::NodeNetwork>> get_all_networks(ProcessingToken token) const;
376
377 /**
378 * @brief Get count of networks for a token
379 */
380 [[nodiscard]] size_t get_network_count(ProcessingToken token) const;
381
382 /**
383 * @brief Clear all networks from a token
384 */
385 void clear_networks(ProcessingToken token);
386
387 /**
388 * @brief Register network globally (like nodes)
389 */
390 void register_network_global(const std::shared_ptr<Network::NodeNetwork>& network);
391
392 /**
393 * @brief Unregister network globally
394 */
395 void unregister_network_global(const std::shared_ptr<Network::NodeNetwork>& network);
396
397 /**
398 * @brief Process audio networks for a specific channel
399 * @param token Processing domain (should be AUDIO_RATE)
400 * @param num_samples Number of samples/frames to process
401 * @param channel Channel index within that domain
402 * @return Vector of processed audio data from all networks for that channel
403 *
404 * Processes all audio-sink networks registered to the specified channel
405 * and returns their combined output data.
406 */
407 std::vector<std::vector<double>> process_audio_networks(ProcessingToken token, uint32_t num_samples, uint32_t channel = 0);
408
409 /**
410 * @brief Terminates all active processing across all tokens and channels
411 *
412 * This method stops all active processing contexts in all root nodes
413 * and networks, ensuring a clean shutdown of processing activities.
414 */
415 void terminate_active_processing();
416
417 /**
418 * @brief Routes a node's output to specific channels within a token domain
419 * @param node Node to route
420 * @param target_channels Vector of channel indices to route the node's output to
421 * @param fade_cycles Number of cycles to fade in the routing (optional)
422 * @param token Processing domain to route within
423 *
424 * This method adds the specified node to the root nodes of the target channels
425 * within the given processing domain. If fade_cycles is greater than 0, the routing
426 * will be smoothly faded in over that many processing cycles.
427 */
428 void route_node_to_channels(
429 const std::shared_ptr<Node>& node,
430 const std::vector<uint32_t>& target_channels,
431 uint32_t fade_cycles,
432 ProcessingToken token);
433
434 /**
435 * @brief Routes a network's output to specific channels within a token domain
436 * @param network Network to route (must be an audio sink)
437 * @param target_channels Vector of channel indices to route the network's output to
438 * @param fade_cycles Number of cycles to fade in the routing (optional)
439 * @param token Processing domain to route within
440 *
441 * This method registers the network and adds it to the specified channels' root nodes
442 * within the given processing domain. If fade_cycles is greater than 0, the routing
443 * will be smoothly faded in over that many processing cycles.
444 */
445 void route_network_to_channels(
446 const std::shared_ptr<Network::NodeNetwork>& network,
447 const std::vector<uint32_t>& target_channels,
448 uint32_t fade_cycles,
449 ProcessingToken token);
450
451 /**
452 * @brief Updates routing states for all nodes and networks for a given token
453 * @param token Processing domain to update routing states for
454 *
455 * This method should be called at the end of each processing cycle to update the
456 * routing states of all nodes and networks that are currently undergoing routing changes.
457 * It handles the fade-in/out logic and transitions routing states as needed.
458 */
459 void update_routing_states_for_cycle(ProcessingToken token);
460
461 /**
462 * @brief Cleans up completed routing transitions for a given token
463 * @param token Processing domain to clean up routing for
464 *
465 * This method should be called after routing states have been updated to remove any nodes
466 * or networks that have completed their fade-out transitions and are no longer contributing
467 * to the output of their previous channels.
468 */
469 void cleanup_completed_routing(ProcessingToken token);
470
471 /**
472 * @brief Sets the node configuration for this manager
473 * @param config The NodeConfig to set
474 */
475 void set_node_config(const NodeConfig& config) { m_node_config = config; }
476
477 /**
478 * @brief Gets the current node configuration
479 * @return Reference to the current NodeConfig
480 */
481 NodeConfig& get_node_config() { return m_node_config; }
482 const NodeConfig& get_node_config() const { return m_node_config; }
483
484private:
485 /**
486 * @brief Map of channel indices to their root nodes (AUDIO_RATE domain)
487 *
488 * Each audio channel has its own root node that collects all nodes
489 * that should output to that channel. For multi-modal support,
490 * see m_token_roots.
491 */
492 std::unordered_map<unsigned int, std::shared_ptr<RootNode>> m_channel_root_nodes;
493
494 /**
495 * @brief Registry of all nodes by their string identifiers
496 *
497 * This registry allows nodes to be looked up by their string identifiers
498 * for operations like connecting nodes by name.
499 */
500 std::unordered_map<std::string, std::shared_ptr<Node>> m_Node_registry;
501
502 /**
503 * @brief Multi-modal map of processing tokens to their channel root nodes
504 *
505 * Each processing domain (token) can have multiple channels, each with its own RootNode.
506 * Enables support for audio, visual, and custom processing domains.
507 */
508 std::unordered_map<ProcessingToken,
509 std::unordered_map<unsigned int, std::shared_ptr<RootNode>>>
511
512 /**
513 * @brief Registered custom processors for each processing token
514 *
515 * Maps each processing domain (token) to a custom processing function that
516 * receives a span of all root nodes for that domain. Enables efficient
517 * backend-specific or multi-channel processing.
518 */
519 std::unordered_map<ProcessingToken,
520 std::function<void(std::span<RootNode*>)>>
522
523 /**
524 * @brief Per-channel processors for each processing token
525 *
526 * Maps each processing domain to a per-channel processing function that
527 * processes a single root node and returns processed data. This enables
528 * fine-grained processing with data extraction capabilities.
529 */
530 std::unordered_map<ProcessingToken, TokenChannelProcessor> m_token_channel_processors;
531
532 /**
533 * @brief Per-sample processors for each processing token
534 *
535 * Maps each processing domain to a per-sample processing function that
536 * processes a single sample and returns the processed value. This is useful
537 * for low-level sample manipulation and custom processing.
538 */
539 std::unordered_map<ProcessingToken, TokenSampleProcessor> m_token_sample_processors;
540
541 /**
542 * @brief Global network registry (like m_Node_registry)
543 *
544 * Maps generated IDs to networks for lifecycle management
545 */
546 std::unordered_map<std::string, std::shared_ptr<Network::NodeNetwork>> m_network_registry;
547
548 /**
549 * @brief Audio-sink networks
550 * Only populated for networks with OutputMode::AUDIO_SINK
551 */
552 std::unordered_map<ProcessingToken,
553 std::vector<std::shared_ptr<Network::NodeNetwork>>>
555
556 /**
557 * @brief Non-audio networks (token-level processing)
558 * For NONE, GRAPHICS_BIND, CUSTOM output modes
559 */
560 std::unordered_map<ProcessingToken, std::vector<std::shared_ptr<Network::NodeNetwork>>>
562
563 /**
564 * @brief Processing flags for each token's networks
565 *
566 * Used to prevent re-entrant processing of networks within the same cycle.
567 */
568 std::unordered_map<ProcessingToken, std::unique_ptr<std::atomic<bool>>> m_token_network_processing;
569
570 std::atomic<bool> m_terminate_requested { false }; ///< Global termination flag
571
572 uint32_t m_registered_sample_rate { 48000 }; ///< Sample rate for audio processing, used for normalization
573
574 uint32_t m_registered_frame_rate { 60 }; ///< Frame rate for visual processing, used for timing and normalization
575
576 uint32_t m_registered_block_size { 512 }; ///< Block size for audio processing, used for normalizationbuffer
577
578 NodeConfig m_node_config; ///< Configuration for node creation and management
579
580 /**
581 * @brief Ensures a root node exists for the given token and channel
582 * @param token Processing domain
583 * @param channel Channel index
584 *
585 * Creates and registers a new root node if one does not already exist.
586 */
587 void ensure_root_exists(ProcessingToken token, unsigned int channel);
588
589 /**
590 * @brief Ensures that a processing token entry exists
591 * @param token Processing domain
592 * @param num_channels Number of channels to initialize (default: 1)
593 *
594 * Creates the necessary data structures for the given processing token
595 * if they do not already exist.
596 */
597 void ensure_token_exists(ProcessingToken token, uint32_t num_channels = 1);
598
599 /**
600 * @brief Registers a node globally if not already registered
601 * @param node Node to register
602 *
603 * Assigns a generated identifier if needed and adds the node to the registry.
604 */
605 void register_global(const std::shared_ptr<Node>& node);
606
607 /**
608 * @brief Adds the specified channel mask to a node's global registration
609 * @param node Node to modify
610 * @param channel_id Channel mask to set
611 */
612 void set_channel_mask(const std::shared_ptr<Node>& node, uint32_t channel_id);
613
614 /**
615 * @brief Unsets the specified channel mask from a node's global registration
616 * @param node Node to modify
617 * @param channel_id Channel mask to unset
618 *
619 * Removes the specified channel mask from the node's global registration.
620 */
621 void unset_channel_mask(const std::shared_ptr<Node>& node, uint32_t channel_id);
622
623 /**
624 * @brief Unregisters a node globally
625 * @param node Node to unregister
626 *
627 * Removes the node from the global registry and cleans up any references.
628 */
629 void unregister_global(const std::shared_ptr<Node>& node);
630
631 /**
632 * @brief Normalizes a sample to the range [-1, 1] based on the number of nodes
633 * @param sample Reference to the sample value to normalize
634 * @param num_nodes Number of nodes in the processing chain
635 *
636 * Ensures that the sample value is within the valid range for audio processing.
637 */
638 void normalize_sample(double& sample, uint32_t num_nodes);
639
640 /**
641 * @brief Check if network is registered globally
642 */
643 bool is_network_registered(const std::shared_ptr<Network::NodeNetwork>& network);
644
645 /**
646 * @brief Resets the processing state of audio networks for a token and channel
647 * @param token Processing domain
648 * @param channel Channel index
649 */
650 void reset_audio_network_state(ProcessingToken token, uint32_t channel = 0);
651
652 /**
653 * @brief Preprocess networks for a specific token
654 * @param token Processing domain
655 * @return true if preprocessing succeeded, false otherwise
656 */
657 bool preprocess_networks(ProcessingToken token);
658
659 /**
660 * @brief Postprocess networks for a specific token and channel
661 * @param token Processing domain
662 * @param channel Channel index
663 */
664 void postprocess_networks(ProcessingToken token, std::optional<uint32_t> channel);
665};
666
667}
uint32_t id
uint32_t channel
void set_node_config(const NodeConfig &config)
Sets the node configuration for this manager.
NodeGraphManager(NodeGraphManager &&)=delete
std::unordered_map< unsigned int, std::shared_ptr< RootNode > > m_channel_root_nodes
Map of channel indices to their root nodes (AUDIO_RATE domain)
std::unordered_map< ProcessingToken, std::vector< std::shared_ptr< Network::NodeNetwork > > > m_token_networks
Non-audio networks (token-level processing) For NONE, GRAPHICS_BIND, CUSTOM output modes.
void add_to_root(const std::string &node_id, ProcessingToken token=ProcessingToken::AUDIO_RATE, unsigned int channel=0)
Adds a node to a channel's root node by its identifier.
std::unordered_map< ProcessingToken, std::function< void(std::span< RootNode * >)> > m_token_processors
Registered custom processors for each processing token.
std::unordered_map< std::string, std::shared_ptr< Network::NodeNetwork > > m_network_registry
Global network registry (like m_Node_registry)
const NodeConfig & get_node_config() const
NodeGraphManager & operator=(const NodeGraphManager &)=delete
std::shared_ptr< NodeType > create_node(const std::string &id, Args &&... args)
Creates and registers a new node of the specified type.
std::unordered_map< ProcessingToken, TokenSampleProcessor > m_token_sample_processors
Per-sample processors for each processing token.
std::unordered_map< std::string, std::shared_ptr< Node > > m_Node_registry
Registry of all nodes by their string identifiers.
NodeGraphManager(const NodeGraphManager &)=delete
std::unordered_map< ProcessingToken, std::unordered_map< unsigned int, std::shared_ptr< RootNode > > > m_token_roots
Multi-modal map of processing tokens to their channel root nodes.
std::unordered_map< ProcessingToken, std::vector< std::shared_ptr< Network::NodeNetwork > > > m_audio_networks
Audio-sink networks Only populated for networks with OutputMode::AUDIO_SINK.
NodeGraphManager & operator=(NodeGraphManager &&)=delete
NodeConfig m_node_config
Configuration for node creation and management.
std::unordered_map< ProcessingToken, TokenChannelProcessor > m_token_channel_processors
Per-channel processors for each processing token.
std::unordered_map< ProcessingToken, std::unique_ptr< std::atomic< bool > > > m_token_network_processing
Processing flags for each token's networks.
NodeConfig & get_node_config()
Gets the current node configuration.
Central manager for the computational processing node graph.
Container for top-level nodes in a processing channel with multi-modal support.
Definition RootNode.hpp:29
ProcessingToken
Enumerates the different processing domains for nodes.
std::function< double(RootNode *, uint32_t)> TokenSampleProcessor
std::function< std::vector< double >(RootNode *, uint32_t)> TokenChannelProcessor
Contains the node-based computational processing system components.
Definition Chronie.hpp:13
Configuration settings for individual audio nodes.
Definition NodeSpec.hpp:29