MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Logic.cpp
Go to the documentation of this file.
1#include "Logic.hpp"
2
4
5//-------------------------------------------------------------------------
6// Constructors
7//-------------------------------------------------------------------------
8
10 : m_mode(LogicMode::DIRECT)
11 , m_operator(LogicOperator::THRESHOLD)
12 , m_history_size(1)
13 , m_input_count(1)
14 , m_threshold(threshold)
15 , m_low_threshold(threshold * 0.9)
16 , m_high_threshold(threshold)
17 , m_edge_type(EdgeType::BOTH)
18 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
19 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
20{
21 m_direct_function = [this](double input) {
22 return input > m_threshold;
23 };
24}
25
27 : m_mode(LogicMode::DIRECT)
28 , m_operator(op)
29 , m_history_size(1)
30 , m_input_count(1)
31 , m_threshold(threshold)
32 , m_low_threshold(threshold * 0.9)
33 , m_high_threshold(threshold)
34 , m_edge_type(EdgeType::BOTH)
35 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
36 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
37{
38 set_operator(op);
39}
40
42 : m_mode(LogicMode::DIRECT)
43 , m_operator(LogicOperator::CUSTOM)
44 , m_direct_function(std::move(function))
45 , m_history_size(1)
46 , m_input_count(1)
47 , m_threshold(0.5)
48 , m_low_threshold(0.45)
49 , m_high_threshold(0.5)
50 , m_edge_type(EdgeType::BOTH)
51 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
52 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
53{
54}
55
56Logic::Logic(MultiInputFunction function, size_t input_count)
57 : m_mode(LogicMode::MULTI_INPUT)
58 , m_operator(LogicOperator::CUSTOM)
59 , m_multi_input_function(std::move(function))
60 , m_history_size(1)
61 , m_input_count(input_count)
62 , m_threshold(0.5)
63 , m_low_threshold(0.45)
64 , m_high_threshold(0.5)
65 , m_edge_type(EdgeType::BOTH)
66 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
67 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
68{
69 m_input_buffer.resize(input_count, 0.0);
70}
71
72Logic::Logic(SequentialFunction function, size_t history_size)
73 : m_mode(LogicMode::SEQUENTIAL)
74 , m_operator(LogicOperator::CUSTOM)
75 , m_sequential_function(std::move(function))
76 , m_history_size(history_size)
77 , m_input_count(1)
78 , m_threshold(0.5)
79 , m_low_threshold(0.45)
80 , m_high_threshold(0.5)
81 , m_edge_type(EdgeType::BOTH)
82 , m_history_ring(history_size, false)
83 , m_history_linear(history_size, false)
84 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
85 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
86{
87}
88
90 : m_mode(LogicMode::TEMPORAL)
91 , m_operator(LogicOperator::CUSTOM)
92 , m_temporal_function(std::move(function))
93 , m_history_size(1)
94 , m_input_count(1)
95 , m_threshold(0.5)
96 , m_low_threshold(0.45)
97 , m_high_threshold(0.5)
98 , m_edge_type(EdgeType::BOTH)
99 , m_context(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer)
100 , m_context_gpu(0.0, m_mode, m_operator, {}, m_threshold, m_edge_detected, m_edge_type, m_input_buffer, get_gpu_data_buffer())
101{
102}
103
104Logic::Logic(CoefDirectFunction function, std::vector<double> coefficients)
106{
107 m_coefficients = std::move(coefficients);
108 set_direct_function(std::move(function));
109}
110
111Logic::Logic(CoefSequentialFunction function, size_t history_size, std::vector<double> coefficients)
112 : Logic(SequentialFunction {}, history_size)
113{
114 m_coefficients = std::move(coefficients);
115 set_sequential_function(std::move(function), history_size);
116}
117
118Logic::Logic(CoefTemporalFunction function, std::vector<double> coefficients)
120{
121 m_coefficients = std::move(coefficients);
122 set_temporal_function(std::move(function));
123}
124
125Logic::Logic(CoefMultiInputFunction function, size_t input_count, std::vector<double> coefficients)
126 : Logic(MultiInputFunction {}, input_count)
127{
128 m_coefficients = std::move(coefficients);
129 set_multi_input_function(std::move(function), input_count);
130}
131
132std::shared_ptr<Logic> Logic::clone() const
133{
134 std::shared_ptr<Logic> copy;
135
137 switch (m_mode) {
139 copy = std::make_shared<Logic>(m_coef_direct_function, m_coefficients);
140 break;
142 copy = std::make_shared<Logic>(m_coef_sequential_function, m_history_size, m_coefficients);
143 break;
145 copy = std::make_shared<Logic>(m_coef_temporal_function, m_coefficients);
146 break;
148 copy = std::make_shared<Logic>(m_coef_multi_function, m_input_count, m_coefficients);
149 break;
150 }
151 }
152
153 if (!copy) {
154 switch (m_mode) {
157 ? std::make_shared<Logic>(m_direct_function)
158 : std::make_shared<Logic>(m_operator, m_threshold);
159 break;
161 copy = std::make_shared<Logic>(m_sequential_function, m_history_size);
162 break;
164 copy = std::make_shared<Logic>(m_temporal_function);
165 break;
167 copy = std::make_shared<Logic>(m_multi_input_function, m_input_count);
169 copy->m_multi_input_function = copy->default_multi_input_function();
170 copy->m_default_multi_input = true;
171 }
172 break;
173 }
174 }
175
176 copy->m_coefficients = m_coefficients;
177 copy->m_threshold = m_threshold;
178 copy->m_low_threshold = m_low_threshold;
179 copy->m_high_threshold = m_high_threshold;
180 copy->m_edge_type = m_edge_type;
181 copy->m_input_node = m_input_node;
182 copy->m_input_nodes = m_input_nodes;
183 return copy;
184}
185
186void Logic::set_coefficients(const std::vector<double>& coefficients)
187{
188 m_coefficients = coefficients;
189}
190
191//-------------------------------------------------------------------------
192// Processing Methods
193//-------------------------------------------------------------------------
194
196{
197 bool result = false;
198 m_edge_detected = false;
199
200 if (m_input_node) {
201 atomic_inc_modulator_count(m_input_node->m_modulator_count, 1);
202 uint32_t state = m_input_node->m_state.load();
203 if (state & NodeState::PROCESSED) {
204 input += m_input_node->get_last_output();
205 } else {
206 input = m_input_node->process_sample(input);
208 }
209 }
210
211 const bool pulled = m_mode == LogicMode::MULTI_INPUT && !m_input_nodes.empty();
212 if (pulled) {
214 }
215
216 bool current_bool = input > m_threshold;
217 bool previous_bool = m_last_output > 0.5;
218
219 switch (m_mode) {
221 switch (m_operator) {
223 result = current_bool;
224 break;
225
227 if (input > m_high_threshold) {
228 m_hysteresis_state = true;
229 } else if (input < m_low_threshold) {
230 m_hysteresis_state = false;
231 }
232 result = m_hysteresis_state;
233 break;
234
235 case LogicOperator::EDGE: {
236 bool previous_bool_input = m_input > m_threshold;
237 if (current_bool != previous_bool_input) {
238 switch (m_edge_type) {
239 case EdgeType::RISING:
240 m_edge_detected = current_bool && !previous_bool_input;
241 break;
243 m_edge_detected = !current_bool && previous_bool_input;
244 break;
245 case EdgeType::BOTH:
246 m_edge_detected = true;
247 break;
248 }
249 }
250 result = m_edge_detected;
251 break;
252 }
253
255 result = current_bool && previous_bool;
256 break;
257
259 result = current_bool || previous_bool;
260 break;
261
263 result = current_bool != previous_bool;
264 break;
265
267 result = !current_bool;
268 break;
269
271 result = !(current_bool && previous_bool);
272 break;
273
275 result = !(current_bool || previous_bool);
276 break;
277
279 result = m_direct_function(input);
280 break;
281
282 default:
283 result = current_bool;
284 }
285 break;
286
288 bool current_bool = input > m_threshold;
289 history_push(current_bool);
290 auto view = history_linearized_view();
291 result = m_sequential_function(view);
292 break;
293 }
294
295 case LogicMode::TEMPORAL: {
298 break;
299 }
300
302 if (!pulled) {
303 add_input(input, 0);
304 } else if (m_input_count > m_input_nodes.size()) {
306 }
308 break;
309 }
310 }
311
312 m_input = input;
313 auto current = result ? 1.0 : 0.0;
314
316 && !m_networked_node) {
318 }
319
320 if (pulled) {
322 }
323
324 if (m_input_node) {
325 atomic_dec_modulator_count(m_input_node->m_modulator_count, 1);
327 }
328
330 return m_last_output;
331}
332
333std::vector<double> Logic::process_batch(unsigned int num_samples)
334{
335 std::vector<double> output(num_samples);
336
337 for (unsigned int i = 0; i < num_samples; ++i) {
338 // For batch processing, we use 0.0 as input
339 // This is mainly useful for temporal or sequential modes
340 output[i] = process_sample(0.0);
341 }
342
343 return output;
344}
345
346double Logic::process_multi_input(const std::vector<double>& inputs)
347{
351 m_coef_bound = false;
352
353 if (m_input_buffer.size() < inputs.size()) {
354 m_input_buffer.resize(inputs.size(), 0.0);
355 m_input_count = inputs.size();
356 }
357
361 }
362 }
363
364 // Copy inputs to our buffer
365 for (size_t i = 0; i < inputs.size() && i < m_input_buffer.size(); ++i) {
366 m_input_buffer[i] = inputs[i];
367 }
368
369 const double current = m_multi_input_function(m_input_buffer) ? 1.0 : 0.0;
370
372
374 return m_last_output;
375}
376
378{
379 return [this](const std::vector<double>& inputs) {
380 return std::ranges::all_of(inputs, [this](double input) { return input > m_threshold; });
381 };
382}
383
385{
386 if (m_input_buffer.size() < m_input_nodes.size()) {
387 m_input_buffer.resize(m_input_nodes.size(), 0.0);
388 }
389
390 for (size_t i = 0; i < m_input_nodes.size(); ++i) {
391 const auto& node = m_input_nodes[i];
392 atomic_inc_modulator_count(node->m_modulator_count, 1);
393
394 uint32_t state = node->m_state.load();
395 if (state & NodeState::PROCESSED) {
396 m_input_buffer[i] = node->get_last_output();
397 } else {
398 m_input_buffer[i] = node->process_sample(0.0);
400 }
401 }
402}
403
405{
406 for (const auto& node : m_input_nodes) {
407 atomic_dec_modulator_count(node->m_modulator_count, 1);
409 }
410}
411
412void Logic::add_input(double input, size_t index)
413{
414 if (index >= m_input_buffer.size()) {
415 m_input_buffer.resize(index + 1, 0.0);
416 }
418}
419
420//-------------------------------------------------------------------------
421// Configuration Methods
422//-------------------------------------------------------------------------
423
425{
426 std::ranges::fill(m_history_ring, false);
427 m_history_head = 0;
429 m_edge_detected = false;
430 m_last_output = 0.0;
431 m_hysteresis_state = false;
432 m_temporal_time = 0.0;
433 m_input_buffer.assign(m_input_count, 0.0);
434}
435
436void Logic::set_threshold(double threshold, bool create_default_direct_function)
437{
440 m_low_threshold = threshold * 0.9; // Default hysteresis
441
442 if (m_operator == LogicOperator::THRESHOLD && m_mode == LogicMode::DIRECT && create_default_direct_function) {
443 m_direct_function = [this](double input) {
444 return input > m_threshold;
445 };
446 }
447}
448
449void Logic::set_hysteresis(double low_threshold, double high_threshold, bool create_default_direct_function)
450{
451 m_low_threshold = low_threshold;
452 m_high_threshold = high_threshold;
453 m_threshold = high_threshold; // For compatibility with other methods
454
455 if (m_operator == LogicOperator::HYSTERESIS && m_mode == LogicMode::DIRECT && create_default_direct_function) {
456 m_direct_function = [this](double input) {
457 if (input > m_high_threshold) {
458 m_hysteresis_state = true;
459 } else if (input < m_low_threshold) {
460 m_hysteresis_state = false;
461 }
462 return m_hysteresis_state;
463 };
464 }
465}
466
473
474void Logic::set_operator(LogicOperator op, bool create_default_direct_function)
475{
476 m_operator = op;
477
478 if (create_default_direct_function) {
479 switch (op) {
481 m_direct_function = [this](double input) {
482 bool current = input > m_threshold;
483 bool previous = m_last_output > 0.5;
484 return current && previous;
485 };
486 break;
487
489 m_direct_function = [this](double input) {
490 bool current = input > m_threshold;
491 bool previous = m_last_output > 0.5;
492 return current || previous;
493 };
494 break;
495
497 m_direct_function = [this](double input) {
498 bool current = input > m_threshold;
499 bool previous = m_last_output > 0.5;
500 return current != previous;
501 };
502 break;
503
505 m_direct_function = [this](double input) {
506 return !(input > m_threshold);
507 };
508 break;
509
511 m_direct_function = [this](double input) {
512 bool current = input > m_threshold;
513 bool previous = m_last_output > 0.5;
514 return !(current && previous);
515 };
516 break;
517
519 m_direct_function = [this](double input) {
520 bool current = input > m_threshold;
521 bool previous = m_last_output > 0.5;
522 return !(current || previous);
523 };
524 break;
525
527 m_direct_function = [this](double input) {
528 return input > m_threshold;
529 };
530 break;
531
533 m_direct_function = [this](double input) {
534 if (input > m_high_threshold) {
535 m_hysteresis_state = true;
536 } else if (input < m_low_threshold) {
537 m_hysteresis_state = false;
538 }
539 return m_hysteresis_state;
540 };
541 break;
542
544 // Edge detection is handled in process_sample
546 // Custom function should be set directly
547 break;
548 }
549 }
550}
551
553{
554 m_direct_function = std::move(function);
557 m_coef_bound = false;
558}
559
561{
562 DirectFunction bound = [this](double input) {
563 return m_coef_direct_function(input, std::span<double>(m_coefficients));
564 };
565 set_direct_function(std::move(bound));
566 m_coef_direct_function = std::move(function);
567 m_coef_bound = true;
568}
569
570void Logic::set_multi_input_function(MultiInputFunction function, size_t input_count)
571{
572 m_coef_bound = false;
573 m_default_multi_input = false;
574 m_multi_input_function = std::move(function);
577 m_input_count = input_count;
578
579 // Resize input buffer if needed
580 if (m_input_buffer.size() != input_count) {
581 m_input_buffer.resize(input_count, 0.0);
582 }
583}
584
586{
587 MultiInputFunction bound = [this](const std::vector<double>& inputs) {
588 return m_coef_multi_function(inputs, std::span<double>(m_coefficients));
589 };
590 set_multi_input_function(std::move(bound), input_count);
591 m_coef_multi_function = std::move(function);
592 m_coef_bound = true;
593}
594
595void Logic::add_input_node(const std::shared_ptr<Node>& node)
596{
597 if (!node) {
598 return;
599 }
600
601 m_input_nodes.push_back(node);
602 if (m_input_count < m_input_nodes.size()) {
604 }
605 if (m_input_buffer.size() < m_input_count) {
606 m_input_buffer.resize(m_input_count, 0.0);
607 }
608}
609
610void Logic::set_input_nodes(std::vector<std::shared_ptr<Node>> nodes)
611{
612 std::erase(nodes, nullptr);
613 m_input_nodes = std::move(nodes);
614 if (m_input_count < m_input_nodes.size()) {
616 }
617 if (m_input_buffer.size() < m_input_count) {
618 m_input_buffer.resize(m_input_count, 0.0);
619 }
620}
621
622void Logic::set_sequential_function(SequentialFunction function, size_t history_size)
623{
624 m_sequential_function = std::move(function);
627 m_coef_bound = false;
628
629 if (history_size != m_history_size) {
630 m_history_size = history_size;
631 m_history_ring.resize(history_size, false);
632 m_history_linear.resize(history_size, false);
633 m_history_head = 0;
634 m_history_count = 0;
635 }
636}
637
639{
640 SequentialFunction bound = [this](std::span<bool> history) {
641 return m_coef_sequential_function(history, std::span<double>(m_coefficients));
642 };
643 set_sequential_function(std::move(bound), history_size);
644 m_coef_sequential_function = std::move(function);
645 m_coef_bound = true;
646}
647
656
658{
659 TemporalFunction bound = [this](double input, double time) {
660 return m_coef_temporal_function(input, time, std::span<double>(m_coefficients));
661 };
662 set_temporal_function(std::move(bound));
663 m_coef_temporal_function = std::move(function);
664 m_coef_bound = true;
665}
666
667void Logic::set_initial_conditions(const std::vector<bool>& initial_values)
668{
669 m_history_head = 0;
670 m_history_count = std::min(initial_values.size(), m_history_size);
671
672 for (size_t i = 0; i < m_history_count; ++i) {
673 m_history_ring[i] = initial_values[i];
674 }
675}
676
707
709{
711 bool state_changed = (value != m_last_output);
712
713 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast)
714 auto& ctx = static_cast<LogicContext&>(get_last_context());
715
716 m_callbacks.fire(ctx);
718
719 for (const auto& entry : m_all_callbacks.snapshot()) {
720 bool should_call = false;
721
722 switch (static_cast<LogicEventType>(entry.tag)) {
725 break;
726
728 should_call = static_cast<bool>(value);
729 break;
730
732 should_call = !value;
733 break;
734
736 should_call = state_changed;
737 break;
738
740 should_call = state_changed && static_cast<bool>(value);
741 break;
742
744 should_call = state_changed && !value;
745 break;
746 }
747
748 if (should_call) {
749 entry.hook(ctx);
750 }
751 }
752}
753
755{
756 if (m_gpu_compatible) {
757 return m_context_gpu;
758 }
759 return m_context;
760}
761
762std::span<bool> Logic::get_history()
763{
764 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
765}
766
771
776
781
786
791
796
798{
799 const auto& key = callback.target_type();
800 bool removed = m_callbacks.remove_by_key(key);
801 removed |= m_all_callbacks.remove_by_key(key);
802 return removed;
803}
804
809
811{
812 if (type == LogicEventType::TICK) {
814 } else if (type == LogicEventType::CONDITIONAL) {
816 } else {
817 m_all_callbacks.remove_by_tag(static_cast<uint8_t>(type));
818 }
819}
820
822{
823 if (m_history_size == 0)
824 return;
829}
830
832{
833 for (size_t i = 0; i < m_history_count; ++i) {
835 }
836 return { reinterpret_cast<bool*>(m_history_linear.data()), m_history_count };
837}
838
860
882
883std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>>
885{
886 std::vector<std::pair<ModulatorRole, std::shared_ptr<Node>>> modulators;
887 modulators.reserve(m_input_nodes.size() + 1);
888
889 if (m_input_node)
890 modulators.emplace_back(ModulatorRole::SignalMod, m_input_node);
891 for (const auto& node : m_input_nodes)
892 modulators.emplace_back(ModulatorRole::SignalMod, node);
893 return modulators;
894}
895
896}
Core::GlobalInputConfig input
Definition Config.cpp:42
glm::vec2 current
PickCallback callback
Definition Picker.cpp:22
glm::vec3 value
vk::PhysicalDeviceType type
Definition VKDevice.cpp:126
uint32_t index
Definition VKDevice.cpp:122
float threshold
std::span< bool > m_history
History of boolean states.
Definition Logic.hpp:121
LogicMode m_mode
Current computational model.
Definition Logic.hpp:119
LogicOperator m_operator
Current boolean operator.
Definition Logic.hpp:120
const std::vector< double > * m_coefficients
The node's coefficient array, set by the node each tick.
Definition Logic.hpp:127
EdgeType m_edge_type
Type of transition being monitored.
Definition Logic.hpp:124
bool m_edge_detected
Whether a state transition was detected.
Definition Logic.hpp:123
double m_threshold
Decision boundary for binary quantization.
Definition Logic.hpp:122
SequentialFunction m_sequential_function
Function for sequential mode.
Definition Logic.hpp:698
void set_direct_function(DirectFunction function)
Sets a custom combinational logic function.
Definition Logic.cpp:552
void set_initial_conditions(const std::vector< bool > &initial_values)
Preloads the state history buffer.
Definition Logic.cpp:667
void set_sequential_function(SequentialFunction function, size_t history_size)
Sets a custom state-based evaluation function.
Definition Logic.cpp:622
TemporalFunction m_temporal_function
Function for temporal mode.
Definition Logic.hpp:699
std::vector< uint8_t > m_saved_history_ring
Definition Logic.hpp:764
DirectFunction m_direct_function
Function for direct mode.
Definition Logic.hpp:696
CoefSequentialFunction m_coef_sequential_function
The function behind m_sequential_function while bound.
Definition Logic.hpp:721
void update_context(double value) override
Updates the context with the latest sample value.
Definition Logic.cpp:677
void reset()
Resets internal state to initial conditions.
Definition Logic.cpp:424
CoefDirectFunction m_coef_direct_function
The function behind m_direct_function while bound.
Definition Logic.hpp:720
std::vector< uint8_t > m_history_linear
Linear view of history for easy access.
Definition Logic.hpp:717
std::vector< std::shared_ptr< Node > > m_input_nodes
Nodes feeding the input slots in parallel input mode.
Definition Logic.hpp:714
void add_input_node(const std::shared_ptr< Node > &node)
Appends a node whose output feeds the next input slot.
Definition Logic.cpp:595
std::span< bool > get_history()
Gets the current state history.
Definition Logic.cpp:762
size_t m_history_size
Maximum size of the history buffer.
Definition Logic.hpp:702
EdgeType m_edge_type
Type of edge to detect.
Definition Logic.hpp:707
Logic(double threshold=0.5)
Constructs a Logic node with threshold quantization.
Definition Logic.cpp:9
std::function< bool(std::span< bool >, std::span< double >)> CoefSequentialFunction
Function type for state-based evaluation with access to the coefficient array.
Definition Logic.hpp:216
double process_sample(double input=0.) override
Processes a single input sample through the logic function.
Definition Logic.cpp:195
double m_threshold
Threshold for boolean conversion.
Definition Logic.hpp:704
HookId on_tick_if(const NodeCondition &condition, const TypedHook< LogicContext > &callback)
Registers a conditional callback for generated samples.
Definition Logic.cpp:772
void remove_hooks_of_type(LogicEventType type)
Definition Logic.cpp:810
std::function< bool(double, std::span< double >)> CoefDirectFunction
Function type for stateless evaluation with access to the coefficient array.
Definition Logic.hpp:209
std::function< bool(double)> DirectFunction
Function type for stateless boolean evaluation.
Definition Logic.hpp:185
double m_temporal_time
Time tracking for temporal mode.
Definition Logic.hpp:710
void set_temporal_function(TemporalFunction function)
Sets a custom time-dependent evaluation function.
Definition Logic.cpp:648
NodeContext & get_last_context() override
Retrieves the last created context object.
Definition Logic.cpp:754
double m_high_threshold
High threshold for hysteresis.
Definition Logic.hpp:706
CoefTemporalFunction m_coef_temporal_function
The function behind m_temporal_function while bound.
Definition Logic.hpp:722
HookList m_all_callbacks
Event-specific callbacks, tagged with their LogicEventType.
Definition Logic.hpp:762
HookId on_change_to(bool target_state, const TypedHook< LogicContext > &callback)
Registers a callback for when output changes to a specific state.
Definition Logic.cpp:792
double m_input
Current input value for multi-input mode.
Definition Logic.hpp:711
std::vector< double > m_input_buffer
Definition Logic.hpp:712
void set_edge_detection(EdgeType type, double threshold=0.5)
Configures digital transition detection.
Definition Logic.cpp:467
std::vector< double > m_coefficients
Coefficient array handed to coefficient-aware functions.
Definition Logic.hpp:718
bool m_coef_bound
True while the active mode runs a coefficient function.
Definition Logic.hpp:723
std::shared_ptr< Node > m_input_node
Input node for processing.
Definition Logic.hpp:713
LogicOperator m_operator
Current logic operator.
Definition Logic.hpp:695
std::function< bool(const std::vector< double > &)> MultiInputFunction
Function type for parallel input evaluation.
Definition Logic.hpp:190
bool m_default_multi_input
True while the parallel function is the built in all-above-threshold one.
Definition Logic.hpp:724
std::function< bool(const std::vector< double > &, std::span< double >)> CoefMultiInputFunction
Function type for parallel input evaluation with access to the coefficient array.
Definition Logic.hpp:230
std::shared_ptr< Logic > clone() const
An independent node with the same behaviour and fresh state.
Definition Logic.cpp:132
void set_operator(LogicOperator op, bool create_default_direct_function=false)
Sets the boolean operation to perform.
Definition Logic.cpp:474
double m_low_threshold
Low threshold for hysteresis.
Definition Logic.hpp:705
MultiInputFunction m_multi_input_function
Function for recursive/feedforward mode.
Definition Logic.hpp:697
bool m_edge_detected
Whether an edge was detected in the last processing.
Definition Logic.hpp:708
std::function< bool(std::span< bool >)> SequentialFunction
Function type for state-based evaluation.
Definition Logic.hpp:195
bool remove_conditional_hook(const NodeCondition &callback) override
Removes a previously registered conditional callback.
Definition Logic.cpp:805
void set_hysteresis(double low_threshold, double high_threshold, bool create_default_direct_function=false)
Configures noise-resistant binary quantization with memory.
Definition Logic.cpp:449
void set_multi_input_function(MultiInputFunction function, size_t input_count)
Sets a custom parallel input evaluation function.
Definition Logic.cpp:570
std::vector< double > process_batch(unsigned int num_samples) override
Processes multiple samples in batch mode.
Definition Logic.cpp:333
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
Definition Logic.cpp:839
std::vector< uint8_t > m_history_ring
Ring buffer for history storage.
Definition Logic.hpp:716
bool m_hysteresis_state
State for hysteresis operator.
Definition Logic.hpp:709
std::function< bool(double, double, std::span< double >)> CoefTemporalFunction
Function type for time-dependent evaluation with access to the coefficient array.
Definition Logic.hpp:223
bool remove_hook(const TypedHook< LogicContext > &callback)
Removes a previously registered callback.
Definition Logic.cpp:797
HookId while_false(const TypedHook< LogicContext > &callback)
Registers a callback that executes continuously while output is false.
Definition Logic.cpp:782
size_t m_history_count
Number of valid entries in the history buffer.
Definition Logic.hpp:701
MultiInputFunction default_multi_input_function()
Definition Logic.cpp:377
size_t m_history_head
Head index for the history ring buffer.
Definition Logic.hpp:700
double process_multi_input(const std::vector< double > &inputs)
Processes multiple parallel inputs.
Definition Logic.cpp:346
CoefMultiInputFunction m_coef_multi_function
The function behind m_multi_input_function while bound.
Definition Logic.hpp:715
LogicMode m_mode
Current processing mode.
Definition Logic.hpp:694
void set_coefficients(const std::vector< double > &coefficients)
Replaces the coefficient array.
Definition Logic.cpp:186
std::function< bool(double, double)> TemporalFunction
Function type for time-dependent evaluation.
Definition Logic.hpp:200
HookId on_change(const TypedHook< LogicContext > &callback)
Registers a callback for any state change (true↔false)
Definition Logic.cpp:787
std::span< bool > history_linearized_view()
Definition Logic.cpp:831
std::vector< double > m_saved_coefficients
Saved coefficient array, used when a coefficient function is bound.
Definition Logic.hpp:719
HookId on_tick(const TypedHook< LogicContext > &callback)
Registers a callback for every generated sample.
Definition Logic.cpp:767
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
Definition Logic.cpp:861
HookId add_callback(const TypedHook< LogicContext > &callback, LogicEventType type, const std::optional< NodeCondition > &condition=std::nullopt)
Adds a callback to the list of all callbacks.
Definition Logic.hpp:740
HookId while_true(const TypedHook< LogicContext > &callback)
Registers a callback that executes continuously while output is true.
Definition Logic.cpp:777
void notify_tick(double value) override
Notifies all registered callbacks about a new sample.
Definition Logic.cpp:708
size_t m_input_count
Expected number of inputs for multi-input mode.
Definition Logic.hpp:703
std::vector< std::pair< ModulatorRole, std::shared_ptr< Node > > > get_modulators() const override
Retrieves the current modulators connected to this node.
Definition Logic.cpp:884
void add_input(double input, size_t index)
Definition Logic.cpp:412
void set_threshold(double threshold, bool create_default_direct_function=false)
Sets the decision boundary for binary quantization.
Definition Logic.cpp:436
void set_input_nodes(std::vector< std::shared_ptr< Node > > nodes)
Replaces all input nodes.
Definition Logic.cpp:610
Digital signal processor implementing boolean logic operations.
Definition Logic.hpp:180
std::span< const float > m_gpu_data
Snapshot snapshot() const
The current entries, held stable for the lifetime of the returned object.
Definition NodeUtils.cpp:43
bool remove_by_tag(uint8_t tag)
Removes every entry carrying this tag.
bool remove_by_key(const std::type_info &key)
Removes every entry registered with this callable type.
void fire(NodeContext &ctx) const
Calls every entry whose condition, if any, holds.
Definition NodeUtils.cpp:68
bool remove_by_condition_key(const std::type_info &key)
Removes every entry whose condition has this callable type.
double value
Current sample value.
Definition Node.hpp:63
Base context class for node callbacks.
Definition Node.hpp:53
HookList m_conditional_callbacks
Hooks fired on a tick only while their condition holds.
Definition Node.hpp:485
bool m_state_saved
tracks if the node's state has been saved by a snapshot operation
Definition Node.hpp:498
bool m_networked_node
Flag indicating if the node is part of a NodeNetwork This flag is used to disable event firing when t...
Definition Node.hpp:493
uint32_t m_sample_rate
Sample rate for audio processing, used for normalization.
Definition Node.hpp:500
double m_last_output
The most recent sample value generated by this oscillator.
Definition Node.hpp:441
HookList m_callbacks
Hooks fired on every tick.
Definition Node.hpp:478
bool m_fire_events_during_snapshot
Internal flag controlling whether notify_tick fires during state snapshots Default: false (events don...
Definition Node.hpp:528
bool m_gpu_compatible
Flag indicating if the node supports GPU processing This flag is set by derived classes to indicate w...
Definition Node.hpp:450
EdgeType
Digital transition patterns to detect.
Definition Logic.hpp:40
@ FALLING
High-to-low transition (1→0)
@ RISING
Low-to-high transition (0→1)
LogicMode
Defines the computational model for digital signal evaluation.
Definition Logic.hpp:11
@ SEQUENTIAL
State-based evaluation using history of inputs (sequential logic)
@ DIRECT
Stateless evaluation of current input only (combinational logic)
@ TEMPORAL
Time-dependent evaluation with timing constraints.
@ MULTI_INPUT
Parallel evaluation of multiple input signals.
LogicEventType
Events that can trigger callbacks.
Definition Logic.hpp:50
LogicOperator
Digital operators for boolean computation.
Definition Logic.hpp:22
@ NOT
Logical NOT - inverts the input.
@ NOR
Logical NOR - inverted OR operation.
@ OR
Logical OR - true when any input is true.
@ NAND
Logical NAND - inverted AND operation.
@ THRESHOLD
Binary quantization - true when input exceeds threshold.
@ AND
Logical AND - true only when all inputs are true.
@ EDGE
Transition detector - identifies state changes.
@ HYSTERESIS
Threshold with memory - prevents rapid oscillation at boundary.
@ CUSTOM
User-defined boolean function.
@ XOR
Logical XOR - true when odd number of inputs are true.
@ PROCESSED
Node has been processed this cycle.
Definition NodeSpec.hpp:49
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.
uint64_t HookId
Identifies one registration inside a HookList.
Definition NodeUtils.hpp:60
void atomic_dec_modulator_count(std::atomic< uint32_t > &count, int amount)
Atomically decrements the modulator count by a specified amount.
std::function< void(ContextT &)> TypedHook
Callback function type for node processing events, parameterised on context type.
Definition NodeUtils.hpp:28
std::function< bool(NodeContext &)> NodeCondition
Predicate function type for conditional callbacks.
Definition NodeUtils.hpp:54
void atomic_add_flag(std::atomic< NodeState > &state, NodeState flag)
Atomically adds a flag to a node state.