22 root.register_node(node);
32 root.unregister_node(node);
36 std::function<
void(std::span<RootNode*>)> processor)
43 static std::unordered_map<unsigned int, std::shared_ptr<RootNode>> audio_roots;
48 for (
const auto& [channel, root] : it->second) {
49 audio_roots[channel] = root;
59 bool expected =
false;
60 return processing_flag.compare_exchange_strong(
62 std::memory_order_acquire,
63 std::memory_order_relaxed);
71 it->second(std::span<RootNode*>(roots.data(), roots.size()));
81 for (
auto& network : it->second) {
82 if (!network || !network->is_enabled()) {
86 if (!network->is_processed_this_cycle()) {
87 network->mark_processing(
true);
88 network->process_batch(num_samples);
89 network->mark_processing(
false);
90 network->mark_processed(
true);
98 for (
auto* root : roots) {
99 root->process_batch(num_samples);
102 for (
auto* root : roots) {
103 root->process_batch_frame(num_samples);
114 std::vector<std::vector<double>> all_network_outputs;
118 auto channel_it = audio_it->second.find(channel);
119 if (channel_it != audio_it->second.end()) {
120 for (
auto& network : channel_it->second) {
121 if (!network || !network->is_enabled()) {
125 if (!network->is_processed_this_cycle()) {
126 network->mark_processing(
true);
127 network->process_batch(num_samples);
128 network->mark_processing(
false);
129 network->mark_processed(
true);
132 const auto& net_buffer = network->get_audio_buffer();
134 all_network_outputs.push_back(*net_buffer);
141 return all_network_outputs;
147 auto ch = channel.value_or(0U);
150 for (
auto& network : it->second) {
151 if (network && network->is_enabled()) {
152 network->mark_processed(
false);
164 auto channel_it = audio_it->second.find(channel);
165 if (channel_it != audio_it->second.end()) {
166 for (
auto& network : channel_it->second) {
168 network->mark_processed(
false);
188 unsigned int channel,
unsigned int num_samples)
197 return it->second(&root, num_samples);
200 std::vector<double> samples = root.process_batch(num_samples);
202 uint32_t normalize_coef = root.get_node_size();
203 for (
double& sample : samples) {
214 return it->second(&root, channel);
217 double sample = root.process_sample();
227 sample /= std::sqrt(
static_cast<double>(num_nodes));
229 const double threshold = 0.95;
230 const double knee = 0.1;
231 const double abs_sample = std::abs(sample);
233 if (abs_sample > threshold) {
234 const double excess = abs_sample - threshold;
235 const double compressed_excess = std::tanh(excess / knee) * knee;
236 const double limited_abs = threshold + compressed_excess;
237 sample = std::copysign(limited_abs, sample);
244 std::unordered_map<unsigned int, std::vector<double>> channel_data;
248 for (
unsigned int channel : channels) {
258 return static_cast<unsigned int>(channels.size());
263 std::vector<RootNode*> roots;
267 for (
auto& [channel, root] : it->second) {
268 roots.push_back(root.get());
297 for (uint32_t ch = 0; ch < num_channels; ++ch) {
305 std::stringstream ss;
306 ss <<
"node_" << node.get();
307 std::string generated_id = ss.str();
315 node->register_channel_usage(channel_id);
321 if (pair.second == node) {
331 node->unregister_channel_usage(channel_id);
336 std::vector<ProcessingToken> tokens;
338 if (!channels.empty()) {
339 tokens.push_back(
token);
347 std::vector<unsigned int> channels;
350 for (
const auto& [channel, root] : it->second) {
351 channels.push_back(channel);
362 for (
const auto& [channel, root] : it->second) {
363 count += root->get_node_size();
373 "=== NodeGraphManager Summary ===");
381 "Token {}: {} nodes across {} channels",
382 static_cast<int>(
token), total_nodes, channels.size());
384 for (
auto channel : channels) {
390 " Channel {}: {} nodes, {} networks",
391 channel, root.get_node_size(), networks.size());
393 for (
const auto& network : networks) {
397 " Network: {} internal nodes, mode={}, enabled={}",
398 network->get_node_count(),
399 static_cast<int>(network->get_output_mode()),
400 network->is_enabled());
420 [&node](
const auto& pair) {
return pair.second == node; });
428 if (source && target) {
446 network->set_enabled(
true);
449 uint32_t channel_mask = network->get_channel_mask();
451 if (channel_mask == 0) {
453 network->add_channel_usage(0);
456 auto channels = network->get_registered_channels();
457 for (
auto ch : channels) {
463 "Added audio network to token {} channel {}: {} nodes",
464 static_cast<int>(
token), ch, network->get_node_count());
472 "Added network to token {}: {} nodes, mode={}",
473 static_cast<int>(
token),
474 network->get_node_count(),
475 static_cast<int>(network->get_output_mode()));
489 for (
auto& [channel, networks] : token_it->second) {
491 std::remove(networks.begin(), networks.end(), network),
498 auto& networks = it->second;
500 std::remove(networks.begin(), networks.end(), network),
508std::vector<std::shared_ptr<NodeNetwork>>
513 auto channel_it = token_it->second.find(channel);
514 if (channel_it != token_it->second.end()) {
515 return channel_it->second;
521std::vector<std::shared_ptr<NodeNetwork>>
524 std::vector<std::shared_ptr<NodeNetwork>> all_networks;
528 for (
const auto& [channel, networks] : audio_it->second) {
529 all_networks.insert(all_networks.end(), networks.begin(), networks.end());
535 all_networks.insert(all_networks.end(),
536 token_it->second.begin(),
537 token_it->second.end());
549 for (
const auto& [channel, networks] : audio_it->second) {
550 count += networks.size();
556 count += token_it->second.size();
571 std::stringstream ss;
572 ss <<
"network_" << network.get();
573 std::string generated_id = ss.str();
581 if (pair.second == network) {
591 [&network](
const auto& pair) {
return pair.second == network; });
#define MF_INFO(comp, ctx,...)
#define MF_PRINT(comp, ctx,...)
static MayaFlux::Nodes::ProcessingToken token
void register_token_processor(ProcessingToken token, std::function< void(std::span< RootNode * >)> processor)
Register subsystem processor for a specific token.
std::unordered_map< ProcessingToken, std::unordered_map< unsigned int, std::vector< std::shared_ptr< NodeNetwork > > > > m_audio_networks
Audio-sink networks (channel-routed) Only populated for networks with OutputMode::AUDIO_SINK.
void register_token_sample_processor(ProcessingToken token, TokenSampleProcessor processor)
Register per-sample processor for a specific token.
void add_network(const std::shared_ptr< NodeNetwork > &network, ProcessingToken token)
Add a network to a processing token.
void clear_networks(ProcessingToken token)
Clear all networks from a token.
void print_summary() const
Prints a summary of all tokens, channels, and node counts.
std::vector< std::shared_ptr< NodeNetwork > > get_all_networks(ProcessingToken token) const
Get all networks for a specific token across all channels.
const std::unordered_map< unsigned int, std::shared_ptr< RootNode > > & get_all_channel_root_nodes(ProcessingToken token=ProcessingToken::AUDIO_RATE) const
Gets all channel root nodes for the AUDIO_RATE domain.
std::vector< std::vector< double > > process_audio_networks(ProcessingToken token, uint32_t num_samples, uint32_t channel=0)
Process audio networks for a specific channel.
std::unordered_map< ProcessingToken, std::function< void(std::span< RootNode * >)> > m_token_processors
Registered custom processors for each processing token.
void unregister_network_global(const std::shared_ptr< NodeNetwork > &network)
Unregister network globally.
size_t get_network_count(ProcessingToken token) const
Get count of networks for a token.
bool preprocess_networks(ProcessingToken token)
Preprocess networks for a specific token.
void normalize_sample(double &sample, uint32_t num_nodes)
Normalizes a sample to the range [-1, 1] based on the number of nodes.
size_t get_node_count(ProcessingToken token) const
Gets the total number of nodes registered under a given token.
void unregister_global(const std::shared_ptr< Node > &node)
Unregisters a node globally.
unsigned int get_channel_count(ProcessingToken token) const
Get the number of active channels for a specific token.
void unset_channel_mask(const std::shared_ptr< Node > &node, uint32_t channel_id)
Unsets the specified channel mask from a node's global registration.
void reset_audio_network_state(ProcessingToken token, uint32_t channel=0)
Resets the processing state of audio networks for a token and channel.
void process_all_tokens(unsigned int num_samples=1)
Process all active tokens sequentially.
void register_global(const std::shared_ptr< Node > &node)
Registers a node globally if not already registered.
void remove_network(const std::shared_ptr< NodeNetwork > &network, ProcessingToken token)
Remove a network from a processing token.
std::unordered_map< ProcessingToken, TokenSampleProcessor > m_token_sample_processors
Per-sample processors for each processing token.
std::vector< std::shared_ptr< NodeNetwork > > get_networks(ProcessingToken token, uint32_t channel=0) const
Get all networks for a specific token.
std::unordered_map< std::string, std::shared_ptr< Node > > m_Node_registry
Registry of all nodes by their string identifiers.
std::vector< double > process_channel(ProcessingToken token, unsigned int channel, unsigned int num_samples)
Process a specific channel within a token domain.
void postprocess_networks(ProcessingToken token, std::optional< uint32_t > channel)
Postprocess networks for a specific token and channel.
void ensure_root_exists(ProcessingToken token, unsigned int channel)
Ensures a root node exists for the given token and channel.
double process_sample(ProcessingToken token, uint32_t channel)
Process a single sample for a specific channel.
std::unordered_map< std::string, std::shared_ptr< NodeNetwork > > m_network_registry
Global network registry (like m_Node_registry)
void connect(const std::string &source_id, const std::string &target_id)
Connects two nodes by their string identifiers.
void set_channel_mask(const std::shared_ptr< Node > &node, uint32_t channel_id)
Adds the specified channel mask to a node's global registration.
void add_to_root(const std::shared_ptr< Node > &node, ProcessingToken token, unsigned int channel=0)
Add node to specific processing token and channel.
RootNode & get_root_node(ProcessingToken token, unsigned int channel)
Gets or creates the root node for a specific token and channel.
NodeGraphManager()
Creates a new NodeGraphManager.
bool is_node_registered(const std::shared_ptr< Node > &node)
Checks if a node is registered with this manager.
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.
void remove_from_root(const std::shared_ptr< Node > &node, ProcessingToken token, unsigned int channel=0)
Remove node from a specific processing token and channel.
std::unordered_map< unsigned int, std::vector< double > > process_token_with_channel_data(ProcessingToken token, unsigned int num_samples)
Process all channels for a token and return channel-separated data.
std::shared_ptr< Node > get_node(const std::string &id)
Looks up a node by its string identifier.
bool is_network_registered(const std::shared_ptr< NodeNetwork > &network)
Check if network is registered globally.
std::vector< ProcessingToken > get_active_tokens() const
Gets all currently active processing tokens (domains)
std::unordered_map< ProcessingToken, TokenChannelProcessor > m_token_channel_processors
Per-channel processors for each processing token.
void ensure_token_exists(ProcessingToken token, uint32_t num_channels=1)
Ensures that a processing token entry exists.
std::unordered_map< ProcessingToken, std::atomic< bool > > m_token_network_processing
Processing flags for each token's networks.
std::vector< RootNode * > get_all_root_nodes(ProcessingToken token)
Get spans of root nodes for a token (for custom processing)
std::vector< unsigned int > get_all_channels(ProcessingToken token) const
Gets all channel indices for a given processing token.
std::unordered_map< ProcessingToken, std::vector< std::shared_ptr< NodeNetwork > > > m_token_networks
Non-audio networks (token-level processing) For NONE, GRAPHICS_BIND, CUSTOM output modes.
void register_network_global(const std::shared_ptr< NodeNetwork > &network)
Register network globally (like nodes)
void process_token(ProcessingToken token, unsigned int num_samples=1)
Process all nodes in a specific token domain Calls registered processor if available,...
void register_token_channel_processor(ProcessingToken token, TokenChannelProcessor processor)
Register per-channel processor for a specific token.
Central manager for the computational processing node graph.
@ AUDIO_SINK
Aggregated audio samples sent to output.
Container for top-level nodes in a processing channel with multi-modal support.
@ NodeProcessing
Node graph processing (Nodes::NodeGraphManager)
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
ProcessingToken
Enumerates the different processing domains for nodes.
@ AUDIO_RATE
Nodes that process at the audio sample rate.
@ VISUAL_RATE
Nodes that process at the visual frame rate.
std::function< double(RootNode *, uint32_t)> TokenSampleProcessor
std::function< std::vector< double >(RootNode *, uint32_t)> TokenChannelProcessor
Contains the node-based computational processing system components.