MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NodeNetwork.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::Nodes {
6
7/**
8 * @class NodeNetwork
9 * @brief Abstract base class for structured collections of nodes with defined
10 * relationships
11 *
12 * DESIGN PRINCIPLES:
13 * =================
14 *
15 * 1. OWNERSHIP: Networks own their nodes exclusively. Nodes within a network
16 * cannot be independently attached to NodeGraphManager channels.
17 *
18 * 2. PROCESSING: Networks are processed directly by NodeGraphManager, parallel
19 * to RootNodes. They are NOT summed through RootNode but manage their own
20 * internal processing pipeline.
21 *
22 * 3. OUTPUT ROUTING: Networks explicitly declare their output mode:
23 * - NONE: Pure internal computation (e.g., particle physics state)
24 * - AUDIO_SINK: Contributes to audio output (aggregated samples)
25 * - GRAPHICS_BIND: Data available for visualization (read-only)
26 * - CUSTOM: User-defined handling via callbacks
27 *
28 * 4. TOPOLOGY: Networks define relationships between nodes:
29 * - INDEPENDENT: No inter-node connections
30 * - CHAIN: Linear sequence (node[i] → node[i+1])
31 * - RING: Circular (last connects to first)
32 * - GRID_2D/3D: Spatial lattice with neighbor connections
33 * - SPATIAL: Dynamic proximity-based relationships
34 * - CUSTOM: Arbitrary user-defined topology
35 *
36 * 5. EXTENSIBILITY: Subclasses define:
37 * - Internal node data structure (spatial, physical, abstract)
38 * - Interaction behavior (forces, coupling, feedback)
39 * - Aggregation logic (how to combine node outputs)
40 * - Initialization patterns (how to populate the network)
41 *
42 * PHILOSOPHY:
43 * ===========
44 *
45 * NodeNetworks embody "structure IS content" - the relationships between
46 * nodes define emergent behavior. They bridge individual node computation
47 * with collective, coordinated behavior patterns (swarms, resonances,
48 * waveguides, recursive growth).
49 *
50 * Networks are NOT:
51 * - Buffers (no sequential data storage)
52 * - Processors (no transformation pipelines)
53 * - Simple node containers (relationships matter)
54 *
55 * Networks ARE:
56 * - Relational structures for coordinated node behavior
57 * - Generators of emergent complexity from simple rules
58 * - Cross-domain abstractions (audio, visual, control unified)
59 *
60 * USAGE PATTERN:
61 * ==============
62 *
63 * ```cpp
64 * // Create network via builder or subclass constructor
65 * auto particles = std::make_shared<ParticleNetwork>(1000);
66 * particles->set_output_mode(OutputMode::GRAPHICS_BIND);
67 * particles->initialize_random_positions();
68 *
69 * // Register with NodeGraphManager (NOT RootNode)
70 * node_graph_manager->add_network(particles, ProcessingToken::VISUAL_RATE);
71 *
72 * // NodeGraphManager calls process_batch() each frame
73 * // Graphics nodes can read network state for visualization
74 * auto geom = std::make_shared<NetworkGeometryNode>(particles);
75 * ```
76 */
77class MAYAFLUX_API NodeNetwork {
78public:
79 /**
80 * @enum Topology
81 * @brief Defines the structural relationships between nodes in the network
82 */
83 enum class Topology : uint8_t {
84 INDEPENDENT, ///< No connections, nodes process independently
85 CHAIN, ///< Linear sequence: node[i] → node[i+1]
86 RING, ///< Circular: last node connects to first
87 GRID_2D, ///< 2D lattice with 4-connectivity
88 GRID_3D, ///< 3D lattice with 6-connectivity
89 SPATIAL, ///< Dynamic proximity-based (nodes within radius interact)
90 CUSTOM ///< User-defined arbitrary topology
91 };
92
93 /**
94 * @enum OutputMode
95 * @brief Defines how the network's computational results are exposed
96 */
97 enum class OutputMode : uint8_t {
98 NONE, ///< Pure internal state, no external output
99 AUDIO_SINK, ///< Aggregated audio samples sent to output
100 GRAPHICS_BIND, ///< State available for visualization (read-only)
101 CUSTOM ///< User-defined output handling via callbacks
102 };
103
104 /**
105 * @enum MappingMode
106 * @brief Defines how nodes map to external entities (e.g., audio channels,
107 * graphics objects)
108 */
109 enum class MappingMode : uint8_t {
110 BROADCAST, ///< One node → all network nodes
111 ONE_TO_ONE ///< Node array/network → network nodes (must match count)
112 };
113
114 virtual ~NodeNetwork() = default;
115
116 //-------------------------------------------------------------------------
117 // Core Abstract Interface (MUST be implemented by subclasses)
118 //-------------------------------------------------------------------------
119
120 /**
121 * @brief Process the network for the given number of samples
122 * @param num_samples Number of samples/frames to process
123 *
124 * Subclasses implement their specific processing logic:
125 * 1. Update internal state (physics, relationships, etc.)
126 * 2. Process individual nodes
127 * 3. Apply inter-node interactions
128 * 4. Aggregate outputs if needed
129 *
130 * Called by NodeGraphManager during token processing.
131 */
132 virtual void process_batch(unsigned int num_samples) = 0;
133
134 /**
135 * @brief Get the number of nodes in the network
136 * @return Total node count
137 *
138 * Used for introspection, visualization, and validation.
139 */
140 [[nodiscard]] virtual size_t get_node_count() const = 0;
141
142 //-------------------------------------------------------------------------
143 // Output Interface (Default implementations provided)
144 //-------------------------------------------------------------------------
145
146 /**
147 * @brief Get cached audio buffer from last process_batch()
148 * @return Optional vector of samples
149 *
150 * Returns the buffer generated by the most recent process_batch() call.
151 * All channels requesting this network's output get the same buffer.
152 */
153 [[nodiscard]] virtual std::optional<std::vector<double>> get_audio_buffer() const;
154
155 //-------------------------------------------------------------------------
156 // Configuration (Non-virtual, base class managed)
157 //-------------------------------------------------------------------------
158
159 /**
160 * @brief Set the network's output routing mode
161 */
162 void set_output_mode(OutputMode mode) { m_output_mode = mode; }
163
164 /**
165 * @brief Get the current output routing mode
166 */
167 [[nodiscard]] OutputMode get_output_mode() const { return m_output_mode; }
168
169 /**
170 * @brief Set the network's topology
171 */
172 void set_topology(Topology topology) { m_topology = topology; }
173
174 /**
175 * @brief Get the current topology
176 */
177 [[nodiscard]] Topology get_topology() const { return m_topology; }
178
179 /**
180 * @brief Enable/disable the network
181 *
182 * Disabled networks skip processing but maintain state.
183 */
184 void set_enabled(bool enabled) { m_enabled = enabled; }
185
186 /**
187 * @brief Check if network is enabled
188 */
189 [[nodiscard]] bool is_enabled() const { return m_enabled; }
190
191 //-------------------------------------------------------------------------
192 // Introspection (Optional overrides for subclass-specific data)
193 //-------------------------------------------------------------------------
194
195 /**
196 * @brief Get network metadata for debugging/visualization
197 * @return Map of property names to string representations
198 *
199 * Subclasses can override to expose internal state:
200 * - Particle count, average velocity
201 * - Modal frequencies, decay times
202 * - Waveguide delay lengths
203 * etc.
204 */
205 [[nodiscard]] virtual std::unordered_map<std::string, std::string>
206 get_metadata() const;
207
208 /**
209 * @brief Get output of specific internal node (for ONE_TO_ONE mapping)
210 * @param index Index of node in network
211 * @return Output value, or nullopt if not applicable
212 */
213 [[nodiscard]] virtual std::optional<double> get_node_output(size_t index) const
214 {
215 return std::nullopt; // Default: not supported
216 }
217
218 //-------------------------------------------------------------------------
219 // Lifecycle Hooks (Optional overrides)
220 //-------------------------------------------------------------------------
221
222 /**
223 * @brief Called once before first process_batch()
224 *
225 * Use for expensive one-time initialization:
226 * - Building neighbor maps
227 * - Allocating buffers
228 * - Computing lookup tables
229 */
230 virtual void initialize() { }
231
232 /**
233 * @brief Reset network to initial state
234 *
235 * Override to implement network-specific reset logic:
236 * - Clear particle velocities
237 * - Reset modal phases
238 * - Rebuild topology
239 */
240 virtual void reset() { }
241
242 //-------------------------------------------------------------------------
243 // Mapping Hooks
244 //-------------------------------------------------------------------------
245
246 /**
247 * @brief Map external node output to network parameter
248 * @param param_name Parameter name (network-specific, e.g., "brightness",
249 * "frequency")
250 * @param source Single node for BROADCAST
251 * @param mode Mapping mode
252 * @note Default implementation stores mapping; subclasses handle in
253 * process_batch(). This methoud SHOULD BE OVERRIDDEN by child classes that
254 * need to handle parameter mappings.
255 */
256 virtual void map_parameter(const std::string& param_name,
257 const std::shared_ptr<Node>& source,
258 MappingMode mode = MappingMode::BROADCAST);
259 /**
260 * @brief Map external node network to network parameters (ONE_TO_ONE)
261 * @param param_name Parameter name
262 * @param source_network NodeNetwork with matching node count
263 * @note Default implementation stores mapping; subclasses handle in
264 * process_batch(). This methoud SHOULD BE OVERRIDDEN by child classes that
265 * need to handle parameter mappings.
266 */
267 virtual void
268 map_parameter(const std::string& param_name,
269 const std::shared_ptr<NodeNetwork>& source_network);
270 /**
271 * @brief Remove parameter mapping
272 */
273 virtual void unmap_parameter(const std::string& param_name);
274
275 //-------------------------------------------------------------------------
276 // Channel Registration (Mirrors Node interface)
277 //-------------------------------------------------------------------------
278
279 /**
280 * @brief Register network usage on a specific channel
281 * @param channel_id Channel index
282 *
283 * Networks can be registered to multiple channels like regular nodes.
284 * Channel registration determines where network output is routed.
285 */
286 void add_channel_usage(uint32_t channel_id);
287
288 /**
289 * @brief Unregister network from a specific channel
290 * @param channel_id Channel index
291 */
292 void remove_channel_usage(uint32_t channel_id);
293
294 /**
295 * @brief Check if network is registered on a channel
296 * @param channel_id Channel index
297 * @return true if registered on this channel
298 */
299 [[nodiscard]] bool is_registered_on_channel(uint32_t channel_id) const;
300
301 /**
302 * @brief Get all channels this network is registered on
303 * @return Vector of channel indices
304 */
305 [[nodiscard]] std::vector<uint32_t> get_registered_channels() const;
306
307 /**
308 * @brief Get channel mask (bitfield of registered channels)
309 */
310 [[nodiscard]] uint32_t get_channel_mask() const { return m_channel_mask; }
311
312 /**
313 * @brief Set channel mask directly
314 */
315 void set_channel_mask(uint32_t mask) { m_channel_mask = mask; }
316
317 /**
318 * @brief Check if network has been processed this cycle (lock-free)
319 * @return true if processed this cycle
320 */
321 [[nodiscard]] bool is_processed_this_cycle() const;
322
323 /**
324 * @brief Mark network as processing or not (lock-free)
325 */
326 void mark_processing(bool processing);
327
328 /**
329 * @brief Mark network as processed this cycle (lock-free)
330 */
331 void mark_processed(bool processed);
332
333 /**
334 * @brief Check if network is currently processing (lock-free)
335 * @return true if currently processing
336 */
337 [[nodiscard]] bool is_processing() const;
338
339protected:
340 //-------------------------------------------------------------------------
341 // Protected State (Accessible to subclasses)
342 //-------------------------------------------------------------------------
343
344 Topology m_topology = Topology::INDEPENDENT;
345 OutputMode m_output_mode = OutputMode::NONE;
346 bool m_enabled = true;
347 bool m_initialized = false;
348
349 /**
350 * @brief Ensure initialize() is called exactly once
351 */
352 void ensure_initialized();
353
354 //-------------------------------------------------------------------------
355 // Utility Functions (Helper methods for subclasses)
356 //-------------------------------------------------------------------------
357
358 /**
359 * @brief Build neighbor map for GRID_2D topology
360 * @param width Grid width
361 * @param height Grid height
362 * @return Map of node index to neighbor indices (4-connectivity)
363 */
364 static std::unordered_map<size_t, std::vector<size_t>>
365 build_grid_2d_neighbors(size_t width, size_t height);
366
367 /**
368 * @brief Build neighbor map for GRID_3D topology
369 * @param width Grid width
370 * @param height Grid height
371 * @param depth Grid depth
372 * @return Map of node index to neighbor indices (6-connectivity)
373 */
374 static std::unordered_map<size_t, std::vector<size_t>>
375 build_grid_3d_neighbors(size_t width, size_t height, size_t depth);
376
377 /**
378 * @brief Build neighbor map for RING topology
379 * @param count Total node count
380 * @return Map of node index to [prev, next] indices
381 */
382 static std::unordered_map<size_t, std::vector<size_t>>
383 build_ring_neighbors(size_t count);
384
385 /**
386 * @brief Build neighbor map for CHAIN topology
387 * @param count Total node count
388 * @return Map of node index to [next] or [prev] index
389 */
390 static std::unordered_map<size_t, std::vector<size_t>>
391 build_chain_neighbors(size_t count);
392
394 std::string param_name;
396
397 // Storage for mapped sources
398 std::shared_ptr<Node> broadcast_source; // For BROADCAST
399 std::shared_ptr<NodeNetwork> network_source; // For ONE_TO_ONE
400 };
401
402 std::vector<ParameterMapping> m_parameter_mappings;
403
404 //-------------------------------------------------------------------------
405 // Channel State (Same as Node)
406 //-------------------------------------------------------------------------
407
408 /// Bitfield of channels this network is registered on
409 std::atomic<uint32_t> m_channel_mask { 0 };
410
411 /// Per-channel processing state (lock-free atomic flags)
412 std::atomic<bool> m_processing_state { false };
413 std::atomic<bool> m_processed_this_cycle { false };
414
415 // Cached buffer from last process_batch() call
416 mutable std::vector<double> m_last_audio_buffer;
417
418private:
419 //-------------------------------------------------------------------------
420 // String Conversion (For metadata/debugging)
421 //-------------------------------------------------------------------------
422
423 static std::string topology_to_string(Topology topo);
424
425 static std::string output_mode_to_string(OutputMode mode);
426};
427
428} // namespace MayaFlux::Nodes
std::vector< ParameterMapping > m_parameter_mappings
void set_topology(Topology topology)
Set the network's topology.
MappingMode
Defines how nodes map to external entities (e.g., audio channels, graphics objects)
OutputMode get_output_mode() const
Get the current output routing mode.
virtual void process_batch(unsigned int num_samples)=0
Process the network for the given number of samples.
uint32_t get_channel_mask() const
Get channel mask (bitfield of registered channels)
Topology
Defines the structural relationships between nodes in the network.
std::vector< double > m_last_audio_buffer
virtual std::optional< double > get_node_output(size_t index) const
Get output of specific internal node (for ONE_TO_ONE mapping)
OutputMode
Defines how the network's computational results are exposed.
bool is_enabled() const
Check if network is enabled.
virtual ~NodeNetwork()=default
void set_channel_mask(uint32_t mask)
Set channel mask directly.
virtual size_t get_node_count() const =0
Get the number of nodes in the network.
void set_output_mode(OutputMode mode)
Set the network's output routing mode.
void set_enabled(bool enabled)
Enable/disable the network.
Topology get_topology() const
Get the current topology.
virtual void reset()
Reset network to initial state.
virtual void initialize()
Called once before first process_batch()
Abstract base class for structured collections of nodes with defined relationships.
Contains the node-based computational processing system components.
Definition Chronie.hpp:5
std::shared_ptr< NodeNetwork > network_source