MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RelationOperators.cpp
Go to the documentation of this file.
2
4
5#include <charconv>
6
8
9namespace {
10 std::shared_ptr<Kinesis::Stochastic::Weights> require_table(std::shared_ptr<Kinesis::Stochastic::Weights> table)
11 {
12 if (!table) {
13 error<std::invalid_argument>(
15 std::source_location::current(),
16 "CombineOperator: null weights table");
17 }
18 return table;
19 }
20}
21
22void StepOperator::process(float frames)
23{
24 const auto self = weak_from_this().lock();
25 if (self && m_body) {
26 m_body(self, slots(), static_cast<uint32_t>(frames));
27 }
28}
29
30void StepOperator::set_parameter(std::string_view param, double value)
31{
32 m_parameters.insert_or_assign(std::string(param), value);
33}
34
35std::optional<double> StepOperator::query_state(std::string_view query) const
36{
37 auto it = m_parameters.find(query);
38 if (it == m_parameters.end()) {
39 return std::nullopt;
40 }
41 return it->second;
42}
43
44double StepOperator::parameter(std::string_view name) const
45{
46 auto it = m_parameters.find(name);
47 return it == m_parameters.end() ? 0.0 : it->second;
48}
49
50void AdvanceOperator::process(float frames)
51{
52 const auto num_frames = static_cast<uint32_t>(frames);
53
54 for (auto& slot : slots()) {
55 const bool active = slot.active;
56 auto block = slot.prepare_block(num_frames);
57
58 if (slot.node) {
59 extract_node_samples(slot.node, m_scratch, m_scratch_pos, num_frames);
60 for (uint32_t i = 0; i < num_frames; ++i) {
61 block[i] = active ? m_scratch[i] : 0.0;
62 }
63 if (num_frames > 0) {
64 slot.level = m_scratch[num_frames - 1];
65 }
66 } else {
67 const double level = slot.level;
68 for (uint32_t i = 0; i < num_frames; ++i) {
69 block[i] = active ? level : 0.0;
70 }
71 }
72 }
73}
74
75DeriveOperator::DeriveOperator(size_t target, std::vector<size_t> inputs, Function function)
76 : m_target(target)
77 , m_inputs(std::move(inputs))
78 , m_values(m_inputs.size(), 0.0)
79 , m_kernel(function ? Kernel([function = std::move(function)](const std::vector<double>& values, std::span<double>) {
80 return function(values);
81 })
82 : Kernel {})
83{
84}
85
86DeriveOperator::DeriveOperator(size_t target, std::vector<size_t> inputs, CoefFunction function, std::vector<double> coefficients)
87 : m_target(target)
88 , m_inputs(std::move(inputs))
89 , m_values(m_inputs.size(), 0.0)
90 , m_coefficients(std::move(coefficients))
91 , m_kernel(function ? Kernel([function = std::move(function)](const std::vector<double>& values, std::span<double> coefs) {
92 return function(values, coefs);
93 })
94 : Kernel {})
95{
96}
97
98std::optional<size_t> DeriveOperator::coefficient_index(std::string_view param)
99{
100 if (param.size() < 2 || param.front() != 'c') {
101 return std::nullopt;
102 }
103
104 size_t index {};
105 const auto digits = param.substr(1);
106 const auto [end, error] = std::from_chars(digits.data(), digits.data() + digits.size(), index);
107 if (error != std::errc {} || end != digits.data() + digits.size()) {
108 return std::nullopt;
109 }
110 return index;
111}
112
113void DeriveOperator::set_parameter(std::string_view param, double value)
114{
115 const auto index = coefficient_index(param);
116 if (index && *index < m_coefficients.size()) {
118 }
119}
120
121std::optional<double> DeriveOperator::query_state(std::string_view query) const
122{
123 const auto index = coefficient_index(query);
124 if (index && *index < m_coefficients.size()) {
125 return m_coefficients[*index];
126 }
127 return std::nullopt;
128}
129
130void DeriveOperator::process(float frames)
131{
132 if (!m_kernel) {
133 return;
134 }
135
136 const auto num_frames = static_cast<uint32_t>(frames);
137 auto all = slots();
138 auto& target = all[m_target];
139 auto out = target.prepare_block(num_frames);
140
141 for (uint32_t frame = 0; frame < num_frames; ++frame) {
142 for (size_t i = 0; i < m_inputs.size(); ++i) {
143 const size_t input_index = m_inputs[i];
144 if (input_index == m_target) {
145 m_values[i] = frame == 0 ? target.level : out[frame - 1];
146 } else {
147 m_values[i] = all[input_index].block.size() > frame
148 ? all[input_index].block[frame]
149 : all[input_index].level;
150 }
151 }
153 if (m_gate) {
154 target.set_active(out[frame] > 0.5);
155 }
156 }
157
158 if (num_frames > 0) {
159 target.level = out[num_frames - 1];
160 }
161}
162
163CombineOperator::CombineOperator(size_t slot_count, size_t output_count)
164 : m_weights(std::make_shared<Kinesis::Stochastic::Weights>(slot_count, std::max<size_t>(1, output_count)))
165 , m_outputs(std::max<size_t>(1, output_count))
166 , m_values(slot_count, 0.0)
167{
168 for (size_t row = 0; row < slot_count; ++row) {
169 (*m_weights)(row, 0) = 1.0;
170 }
171}
172
173CombineOperator::CombineOperator(std::shared_ptr<Kinesis::Stochastic::Weights> table)
174 : m_weights(require_table(std::move(table)))
175 , m_outputs(std::max<size_t>(1, m_weights->cols()))
176 , m_values(m_weights->rows(), 0.0)
177{
178}
179
181{
182 if (slot >= m_weights->rows() || output >= m_weights->cols()) {
183 error<std::out_of_range>(
185 std::source_location::current(),
186 "CombineOperator::weight: ({}, {}) outside the weights table ({} x {})",
187 slot, output, m_weights->rows(), m_weights->cols());
188 }
189 return (*m_weights)(slot, output);
190}
191
192void CombineOperator::process(float frames)
193{
194 const auto num_frames = static_cast<uint32_t>(frames);
195 auto all = slots();
196
197 const size_t count = std::min(all.size(), m_weights->rows());
198 if (m_values.size() < count) {
199 m_values.resize(count, 0.0);
200 }
201 const std::span<const double> values(m_values.data(), count);
202
203 for (auto& output : m_outputs) {
204 output.m_block.assign(num_frames, 0.0);
205 }
206
207 for (uint32_t frame = 0; frame < num_frames; ++frame) {
208 for (size_t m = 0; m < count; ++m) {
209 m_values[m] = all[m].block.size() > frame ? all[m].block[frame] : all[m].level;
210 }
211
212 for (size_t o = 0; o < m_outputs.size(); ++o) {
213 auto& output = m_outputs[o];
214 if (output.has_combine()) {
216 continue;
217 }
218 double sum = 0.0;
219 for (size_t m = 0; m < count; ++m) {
220 sum += m_values[m] * m_weights->get(m, o);
221 }
222 output.m_block[frame] = sum;
223 }
224 }
225}
226
227std::span<const double> CombineOperator::get_output_block(size_t index) const
228{
229 return m_outputs[index].block();
230}
231
232} // namespace MayaFlux::Nodes::Network
bool size
uint32_t rows
glm::ivec3 max
std::vector< float > * out
glm::vec3 value
std::vector< std::byte > values
Definition VDBWriter.cpp:26
std::string name
Definition VKDevice.cpp:123
uint32_t index
Definition VKDevice.cpp:122
size_t count
Proxy for one cell with atomic load and store.
Definition Weights.hpp:44
void process(float frames) override
Process for one batch cycle.
std::span< const double > get_output_block(size_t index) const override
void process(float frames) override
Process for one batch cycle.
CombineOperator(size_t slot_count, size_t output_count=1)
std::shared_ptr< Kinesis::Stochastic::Weights > m_weights
Kinesis::Stochastic::Weights::Cell weight(size_t slot, size_t output)
One weight cell, readable and assignable from any thread.
static std::optional< size_t > coefficient_index(std::string_view param)
std::optional< double > query_state(std::string_view query) const override
DeriveOperator(size_t target, std::vector< size_t > inputs, Function function)
std::function< double(std::span< const double >, std::span< double >)> CoefFunction
std::function< double(std::span< const double >)> Function
void process(float frames) override
Process for one batch cycle.
void set_parameter(std::string_view param, double value) override
Set one coefficient.
std::function< double(const std::vector< double > &, std::span< double >)> Kernel
std::span< RelationSlot > slots() const noexcept
double parameter(std::string_view name) const
Value of a mapped or set parameter.
void process(float frames) override
Process for one batch cycle.
std::map< std::string, double, std::less<> > m_parameters
std::optional< double > query_state(std::string_view query) const override
Query operator internal state.
void set_parameter(std::string_view param, double value) override
Set operator parameter.
@ NodeProcessing
Node graph processing (Nodes::NodeGraphManager)
@ Init
Engine/subsystem initialization.
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
void extract_node_samples(const std::shared_ptr< Nodes::Node > &node, std::vector< double > &buffer, size_t &buffer_pos, size_t num_samples)
Extract num_samples from node into buffer using snapshot guard.