77 BinaryOpContextGpu(
double value,
double lhs_value,
double rhs_value, std::span<const float> gpu_data);
100 CompositeOpContextGpu(
double value, std::vector<double> input_values, std::span<const float> gpu_data);
118class MAYAFLUX_API
BinaryOpNode :
public Node,
public std::enable_shared_from_this<BinaryOpNode> {
154 const std::shared_ptr<Node>& lhs,
155 const std::shared_ptr<Node>& rhs,
178 double process_sample(
double input = 0.)
override;
188 std::vector<double> process_batch(
unsigned int num_samples)
override;
198 void reset_processed_state()
override;
200 void save_state()
override;
201 void restore_state()
override;
207 [[nodiscard]] std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> get_modulators()
const override;
218 void notify_tick(
double value)
override;
229 void update_context(
double value)
override;
278 double m_last_lhs_value {};
287 double m_last_rhs_value {};
298 bool m_is_initialized {};
300 bool m_state_saved {};
301 double m_saved_last_lhs_value {};
302 double m_saved_last_rhs_value {};
317 const std::vector<std::shared_ptr<Node>>& inputs,
320 const std::shared_ptr<Node>& self);
323 const std::vector<std::shared_ptr<Node>>& inputs,
343template <
size_t N = 0>
344class MAYAFLUX_API
CompositeOpNode :
public Node,
public std::enable_shared_from_this<CompositeOpNode<N>> {
346 using CombineFunc = std::function<double(std::span<const double>)>;
354 std::vector<std::shared_ptr<Node>> inputs,
356 : m_inputs(
std::move(inputs))
357 , m_func(
std::move(func))
358 , m_input_values(m_inputs.size(), 0.0)
359 , m_saved_input_values(m_inputs.size(), 0.0)
360 , m_context(0.0,
std::vector<double>(m_inputs.size(), 0.0))
361 , m_context_gpu(0.0,
std::vector<double>(m_inputs.size(), 0.0),
Node::get_gpu_data_buffer())
363 detail::composite_validate(m_inputs,
N);
374 std::vector<std::shared_ptr<Node>> inputs,
378 : m_inputs(
std::move(inputs))
379 , m_func(
std::move(func))
380 , m_manager(&manager)
382 , m_input_values(m_inputs.size(), 0.0)
383 , m_saved_input_values(m_inputs.size(), 0.0)
384 , m_context(0.0,
std::vector<double>(m_inputs.size(), 0.0))
385 , m_context_gpu(0.0,
std::vector<double>(m_inputs.size(), 0.0),
Node::get_gpu_data_buffer())
387 detail::composite_validate(m_inputs,
N);
401 template <
typename DerivedNode>
402 requires std::derived_from<DerivedNode, Node>
404 std::vector<std::shared_ptr<DerivedNode>> inputs,
409 std::vector<
std::shared_ptr<
Node>>(inputs.begin(), inputs.end()),
410 std::move(func), manager, token)
416 if (!m_is_initialized) {
418 detail::composite_initialize(m_inputs, *m_manager, m_token, this->shared_from_this());
419 m_is_initialized =
true;
422 detail::composite_apply_semantics(m_inputs, *m_manager, m_token);
430 for (
auto& node : m_inputs) {
434 for (
size_t i = 0; i < m_inputs.size(); ++i) {
435 uint32_t state = m_inputs[i]->m_state.load();
436 if (state & NodeState::PROCESSED) {
437 m_input_values[i] =
input + m_inputs[i]->get_last_output();
439 m_input_values[i] = m_inputs[i]->process_sample(
input);
444 m_last_output = m_func(std::span<const double>(m_input_values));
446 if (!m_state_saved || (m_state_saved && m_fire_events_during_snapshot))
447 notify_tick(m_last_output);
449 for (
auto& node : m_inputs) {
453 for (
auto& node : m_inputs) {
457 return m_last_output;
462 std::vector<double> output(num_samples);
463 for (
unsigned int i = 0; i < num_samples; ++i) {
464 output[i] = process_sample(0.0);
472 for (
auto& node : m_inputs) {
474 node->reset_processed_state();
480 m_saved_input_values = m_input_values;
481 for (
auto& node : m_inputs) {
485 m_state_saved =
true;
490 m_input_values = m_saved_input_values;
491 for (
auto& node : m_inputs) {
493 node->restore_state();
495 m_state_saved =
false;
498 [[nodiscard]]
size_t input_count()
const {
return m_inputs.size(); }
499 [[nodiscard]]
const std::vector<std::shared_ptr<Node>>&
inputs()
const {
return m_inputs; }
503 for (
auto& node : m_inputs) {
504 auto state = node->m_state.load();
505 if (state & NodeState::ACTIVE)
508 return m_is_initialized;
515 [[nodiscard]] std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>>
518 std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> result;
519 result.reserve(m_inputs.size());
520 for (
const auto& n : m_inputs)
521 result.emplace_back(ModulatorRole::SignalMod, n);
528 update_context(value);
529 auto& ctx = get_last_context();
531 for (
const auto& callback : m_callbacks) {
535 for (
const auto& [callback, condition] : m_conditional_callbacks) {
536 if (condition(ctx)) {
544 if (m_gpu_compatible) {
545 m_context_gpu.value = m_last_output;
546 m_context_gpu.input_values = m_input_values;
548 m_context.value = m_last_output;
549 m_context.input_values = m_input_values;
555 if (m_gpu_compatible)
556 return m_context_gpu;
567 bool m_is_initialized {};
568 bool m_state_saved {};
Core::GlobalInputConfig input
#define N(method_name, full_type_name)
GPU-compatible context for binary operation callbacks.
double rhs_value
The value from the right-hand side node.
double lhs_value
The value from the left-hand side node.
Specialized context for binary operation callbacks.
std::shared_ptr< Node > m_lhs
The left-hand side node.
std::function< double(double, double)> CombineFunc
Function type for combining two node outputs.
CombineFunc m_func
The function used to combine the outputs of both nodes.
BinaryOpContext m_context
std::shared_ptr< Node > m_rhs
The right-hand side node.
BinaryOpContextGpu m_context_gpu
Combines the outputs of two nodes using a binary operation.
GPU-compatible context for composite operation callbacks.
std::vector< double > input_values
Context for N-ary composite operation callbacks.
std::vector< double > m_input_values
CompositeOpNode(std::vector< std::shared_ptr< Node > > inputs, CombineFunc func)
Creates a composite operation node (unmanaged)
CompositeOpNode(std::vector< std::shared_ptr< DerivedNode > > inputs, CombineFunc func, NodeGraphManager &manager, ProcessingToken token=ProcessingToken::AUDIO_RATE)
Creates a composite operation node with derived node types (managed)
CompositeOpContextGpu m_context_gpu
void update_context(double) override
Updates the context object with the current node state.
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
std::vector< std::pair< ModulatorRole, std::shared_ptr< Node > > > get_modulators() const override
Retrieves the current modulators connected to this node.
void notify_tick(double value) override
Notifies all registered callbacks with the current context.
NodeContext & get_last_context() override
Retrieves the last created context object.
CompositeOpNode(std::vector< std::shared_ptr< Node > > inputs, CombineFunc func, NodeGraphManager &manager, ProcessingToken token=ProcessingToken::AUDIO_RATE)
Creates a composite operation node (managed)
const std::vector< std::shared_ptr< Node > > & inputs() const
double process_sample(double input=0.) override
Processes a single data sample.
std::vector< double > process_batch(unsigned int num_samples) override
Processes multiple samples at once.
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
bool is_initialized() const
std::vector< double > m_saved_input_values
std::vector< std::shared_ptr< Node > > m_inputs
std::function< double(std::span< const double >)> CombineFunc
CompositeOpContext m_context
void reset_processed_state() override
Resets the processed state of the node and any attached input nodes.
size_t input_count() const
Combines the outputs of N nodes using a composite operation.
GPU-uploadable 1D array data interface.
Base context class for node callbacks.
Central manager for the computational processing node graph.
Base interface for all computational processing nodes.
void composite_validate(const std::vector< std::shared_ptr< Node > > &inputs, size_t N)
void composite_initialize(const std::vector< std::shared_ptr< Node > > &inputs, NodeGraphManager &manager, ProcessingToken token, const std::shared_ptr< Node > &self)
void composite_apply_semantics(const std::vector< std::shared_ptr< Node > > &inputs, NodeGraphManager &manager, ProcessingToken token)
ProcessingToken
Enumerates the different processing domains for nodes.
void atomic_add_flag(std::atomic< NodeState > &state, NodeState flag)
Atomically adds a flag to a node state.
void try_reset_processed_state(std::shared_ptr< Node > node)
Attempts to reset the processed state of a node.
void atomic_inc_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically increments the modulator count by a specified amount.
void atomic_remove_flag(std::atomic< NodeState > &state, NodeState flag)
Atomically removes a flag from a node state.
void atomic_dec_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically decrements the modulator count by a specified amount.
Contains the node-based computational processing system components.
bool is_initialized()
Checks if the default engine has been initialized.