MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RootNode.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#define MAX_PENDING_NODES 2048
6
7namespace MayaFlux::Nodes {
8
9class Node;
10
11/**
12 * @class RootNode
13 * @brief Container for top-level nodes in a processing channel with multi-modal support
14 *
15 * The RootNode serves as a collection point for multiple independent nodes
16 * that contribute to a single channel's output. Unlike regular nodes,
17 * a RootNode doesn't process data itself but rather manages and combines
18 * the outputs of its registered nodes.
19 *
20 * With multi-modal support, the RootNode can handle different processing rates
21 * (e.g., audio rate, visual rate, custom rates) in a single channel. This enables
22 * advanced scenarios where nodes with different processing requirements coexist.
23 *
24 * Each processing channel has its own RootNode, which collects and
25 * processes all nodes that should output to that channel. The RootNode
26 * processes all registered nodes and aggregates their outputs based on their
27 * assigned processing rates.
28 */
29class MAYAFLUX_API RootNode {
30public:
31 /**
32 * @brief Constructs a RootNode for a specific processing token and channel
33 * @param token The processing domain (e.g., AUDIO_RATE)
34 * @param channel The channel index (default: 0)
35 *
36 * Initializes the root node for the given processing domain and channel.
37 * Each channel and processing domain combination should have its own RootNode.
38 */
39 RootNode(ProcessingToken token = ProcessingToken::AUDIO_RATE, uint32_t channel = 0);
40
41 /**
42 * @brief Adds a node to this root node
43 * @param node The node to register
44 *
45 * Registered nodes will be processed when the root node's process()
46 * method is called, and their outputs will be combined together.
47 * If called during processing, the operation is deferred until safe.
48 */
49 void register_node(const std::shared_ptr<Node>& node);
50
51 /**
52 * @brief Removes a node from this root node
53 * @param node The node to unregister
54 *
55 * After unregistering, the node will no longer contribute to
56 * the root node's output. If called during processing, the operation
57 * is deferred until safe.
58 */
59 void unregister_node(const std::shared_ptr<Node>& node);
60
61 /** @brief Checks if the root node can process pending operations
62 * @return True if successful
63 *
64 * This method can be used to determine if the root node is in the middle
65 * of a processing cycle. If true, queued pending operations will be executed
66 */
67 bool preprocess();
68
69 /** @brief Performs post-processing after all nodes have been processed
70 *
71 * This method unregisters channel usage on the node, cleans up state
72 * and resets processing flags.
73 */
74 void postprocess();
75
76 /**
77 * @brief Processes a single sample from all registered nodes
78 * @return Combined output sample from all nodes
79 *
80 * This method processes each registered node and combines their outputs
81 * into a single sample. It is typically called in a loop to process
82 * multiple samples, but can also be used for single-sample processing.
83 */
84 double process_sample();
85
86 /**
87 * @brief Processes a single frame from all registered nodes
88 *
89 * This method processes each registered node for a single frame.
90 * It is useful in scenarios where frame-based processing is required,
91 * such as visual or animation data processing.
92 */
93 void process_frame();
94
95 /**
96 * @brief Processes all registered nodes and combines their outputs
97 * @param num_samples Number of samples to process
98 * @return Vector containing the combined output samples
99 *
100 * This method calls process_batch() on each registered node and
101 * aggregates their outputs together. The result is the combined output
102 * of all nodes registered with this root node.
103 * If nodes are added or removed during processing, those operations are
104 * deferred until after processing completes.
105 */
106 std::vector<double> process_batch(uint32_t num_samples);
107
108 /**
109 * @brief Processes multiple frames from all registered nodes
110 * @param num_frames Number of frames to process
111 *
112 * This method calls process_batch_frame() on each registered node
113 * for the specified number of frames. It is useful for scenarios
114 * requiring batch frame processing.
115 */
116 void process_batch_frame(uint32_t num_frames);
117
118 /**
119 * @brief Gets the number of nodes registered with this root node
120 * @return Number of registered nodes
121 */
122 inline unsigned int get_node_size() { return m_Nodes.size(); }
123
124 /**
125 * @brief Removes all nodes from this root node
126 *
127 * After calling this method, the root node will have no registered
128 * nodes and will output zero values.
129 */
130 inline void clear_all_nodes() { m_Nodes.clear(); }
131
132 /**
133 * @brief Gets the channel index associated with this root node
134 * @return The channel index
135 */
136 inline uint32_t get_channel() { return m_channel; }
137
138 /**
139 * @brief Gets the processing token associated with this root node
140 * @return The processing token (domain)
141 */
142 inline ProcessingToken get_token() { return m_token; }
143
144private:
145 /**
146 * @brief Collection of nodes registered with this root node
147 *
148 * All nodes in this collection will be processed when the root
149 * node's process() method is called.
150 */
151 std::vector<std::shared_ptr<Node>> m_Nodes;
152
153 /**
154 * @brief Flag indicating if the root node is currently processing nodes
155 *
156 * This atomic flag prevents concurrent modifications to the node collection
157 * during processing cycles. When set to true, any attempts to register or
158 * unregister nodes will be queued as pending operations rather than being
159 * executed immediately, ensuring thread safety and preventing data corruption
160 * during audio processing.
161 */
162 std::atomic<bool> m_is_processing;
163
164 /**
165 * @brief Structure for storing pending node registration/unregistration operations
166 *
167 * When nodes need to be added or removed while the root node is processing,
168 * these operations are stored in this structure and executed later when it's
169 * safe to modify the node collection. This prevents race conditions and ensures
170 * consistent audio processing without interruptions.
171 */
172 struct PendingOp {
173 /**
174 * @brief Flag indicating if this pending operation slot is in use
175 */
176 std::atomic<bool> active;
177
178 /**
179 * @brief The node to be registered or unregistered
180 */
181 std::shared_ptr<Node> node;
182 } m_pending_ops[MAX_PENDING_NODES];
183
184 /**
185 * @brief Counter tracking the number of pending operations
186 *
187 * This counter helps efficiently manage the pending operations array,
188 * allowing the system to quickly determine if there are operations
189 * waiting to be processed without scanning the entire array.
190 */
191 std::atomic<uint32_t> m_pending_count;
192
193 /**
194 * @brief Processes any pending node registration/unregistration operations
195 *
196 * This method is called after the processing cycle completes to handle any
197 * node registration or unregistration requests that came in during processing.
198 * It ensures that node collection modifications happen safely between
199 * processing cycles, maintaining audio continuity while allowing dynamic
200 * changes to the node graph.
201 */
202 void process_pending_operations();
203
204 /**
205 * @brief The processing channel index for this root node
206 *
207 * Each root node is associated with a specific processing channel,
208 * allowing multiple channels to coexist with their own independent
209 * node collections and processing logic.
210 */
211 uint32_t m_channel;
212
213 /**
214 * @brief Flag indicating whether to skip preprocessing and post processing
215 *
216 * This flag can be set to true to skip the pre and post processing steps,
217 * which is useful in scenarios where the root node is not expected
218 * to sync processing state with other channels or is used outside of the
219 * Engine context.
220 */
222
223 /**
224 * @brief The processing token indicating the domain of this root node
225 *
226 * This token specifies the type of processing this root node is responsible for,
227 * such as audio rate, visual rate, or custom processing rates.
228 */
230};
231
232}
#define MAX_PENDING_NODES
Definition RootNode.hpp:5
static MayaFlux::Nodes::ProcessingToken token
Definition Timers.cpp:8
std::vector< std::shared_ptr< Node > > m_Nodes
Collection of nodes registered with this root node.
Definition RootNode.hpp:151
uint32_t m_channel
The processing channel index for this root node.
Definition RootNode.hpp:211
uint32_t get_channel()
Gets the channel index associated with this root node.
Definition RootNode.hpp:136
void clear_all_nodes()
Removes all nodes from this root node.
Definition RootNode.hpp:130
std::atomic< bool > m_is_processing
Flag indicating if the root node is currently processing nodes.
Definition RootNode.hpp:162
bool m_skip_state_management
Flag indicating whether to skip preprocessing and post processing.
Definition RootNode.hpp:221
std::atomic< uint32_t > m_pending_count
Counter tracking the number of pending operations.
Definition RootNode.hpp:191
unsigned int get_node_size()
Gets the number of nodes registered with this root node.
Definition RootNode.hpp:122
ProcessingToken m_token
The processing token indicating the domain of this root node.
Definition RootNode.hpp:229
ProcessingToken get_token()
Gets the processing token associated with this root node.
Definition RootNode.hpp:142
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.
Contains the node-based computational processing system components.
Definition Chronie.hpp:5
void register_node(const std::shared_ptr< Nodes::Node > &node, const Nodes::ProcessingToken &token, uint32_t channel)
Definition Graph.cpp:72
void unregister_node(const std::shared_ptr< Nodes::Node > &node, const Nodes::ProcessingToken &token, uint32_t channel)
Removes a node from the root node of specified channels.
Definition Graph.cpp:57
std::shared_ptr< Node > node
The node to be registered or unregistered.
Definition RootNode.hpp:181
std::atomic< bool > active
Flag indicating if this pending operation slot is in use.
Definition RootNode.hpp:176
Structure for storing pending node registration/unregistration operations.
Definition RootNode.hpp:172