Loading...
Searching...
No Matches
MathMapping_generic.hpp
1#pragma once
2#include <Fx/MathHelpers.hpp>
3#include <Fx/Types.hpp>
4
5#include <ossia/dataflow/value_port.hpp>
6
7#include <halp/callback.hpp>
8namespace Nodes
9{
10template <typename State>
12{
13 static void store_output(auto& self, const ossia::value& v)
14 {
15 switch(v.get_type())
16 {
17 case ossia::val_type::NONE:
18 break;
19 case ossia::val_type::FLOAT:
20 self.po = *v.target<float>();
21 break;
22 case ossia::val_type::VEC2F: {
23 if constexpr(requires { self.pov; })
24 {
25 auto& vec = *v.target<ossia::vec2f>();
26 self.pov.assign(vec.begin(), vec.end());
27 }
28 break;
29 }
30 case ossia::val_type::VEC3F: {
31 if constexpr(requires { self.pov; })
32 {
33 auto& vec = *v.target<ossia::vec3f>();
34 self.pov.assign(vec.begin(), vec.end());
35 }
36 break;
37 }
38 case ossia::val_type::VEC4F: {
39 if constexpr(requires { self.pov; })
40 {
41 auto& vec = *v.target<ossia::vec4f>();
42 self.pov.assign(vec.begin(), vec.end());
43 }
44 break;
45 }
46 case ossia::val_type::LIST: {
47 if constexpr(requires { self.pov; })
48 {
49 auto& arr = *v.target<std::vector<ossia::value>>();
50 if(!arr.empty())
51 {
52 self.pov.clear();
53 for(auto& v : arr)
54 self.pov.push_back(ossia::convert<float>(v));
55 }
56 }
57 break;
58 }
59 // Only these types are used now as per ossia::math_expression::result()
60 default:
61 break;
62 }
63 }
64
65 static void exec_scalar(State& self, value_output_callback& output)
66 {
67 auto res = self.expr.result();
68
69 self.px = self.x;
70 store_output(self, res);
71
72 output(res);
73 }
74
75 static void exec_polyphonic(State& self, value_output_callback& output)
76 {
77 for(auto& e : self.expressions)
78 {
79 auto res = e.expr.result();
80
81 if constexpr(requires { e.x; })
82 e.px = e.x;
83
84 store_output(e, res);
85 }
86 }
87
88 static void
89 exec_array(State& self, value_output_callback& output, bool vector_size_did_change)
90 {
91 if(self.xv.empty())
92 return;
93
94 if(vector_size_did_change)
95 {
96 self.expr.rebase_vector("xv", self.xv);
97 self.expr.recompile();
98 }
99
100 auto res = self.expr.result();
101 store_output(self, res);
102
103 // Save the previous input
104 {
105 bool old_prev = self.pxv.size();
106 self.pxv.assign(self.xv.begin(), self.xv.end());
107 bool new_prev = self.pxv.size();
108
109 if(old_prev != new_prev)
110 {
111 self.expr.rebase_vector("pxv", self.pxv);
112 self.expr.recompile();
113 }
114 }
115
116 output(std::move(res));
117 }
118
119 static void run_scalar(
120 const ossia::value& v, value_output_callback& output, const halp::tick_flicks& tk,
121 State& self)
122 {
123 setMathExpressionTiming(
124 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
125 self.last_value_time = tk.start_in_flicks;
126
127 switch(v.get_type())
128 {
129 case ossia::val_type::NONE:
130 break;
131 case ossia::val_type::IMPULSE:
132 break;
133 case ossia::val_type::INT:
134 self.x = *v.target<int>();
135 break;
136 case ossia::val_type::FLOAT:
137 self.x = *v.target<float>();
138 break;
139 case ossia::val_type::BOOL:
140 self.x = *v.target<bool>() ? 1.f : 0.f;
141 break;
142 case ossia::val_type::STRING:
143 self.x = ossia::convert<float>(v);
144 break;
145 case ossia::val_type::VEC2F:
146 self.x = (*v.target<ossia::vec2f>())[0];
147 break;
148 case ossia::val_type::VEC3F:
149 self.x = (*v.target<ossia::vec3f>())[0];
150 break;
151 case ossia::val_type::VEC4F:
152 self.x = (*v.target<ossia::vec4f>())[0];
153 break;
154 case ossia::val_type::LIST: {
155 auto& arr = *v.target<std::vector<ossia::value>>();
156 if(!arr.empty())
157 self.x = ossia::convert<float>(arr[0]);
158 break;
159 }
160 case ossia::val_type::MAP: {
161 auto& arr = *v.target<ossia::value_map_type>();
162 if(!arr.empty())
163 self.x = ossia::convert<float>(arr.begin()->second);
164 break;
165 }
166 }
167
168 GenericMathMapping::exec_scalar(self, output);
169 }
170
171 static bool resize(const std::string& expr, State& self, int sz)
172 {
173 if(std::ssize(self.expressions) == sz && expr == self.last_expression)
174 return true;
175
176 self.expressions.resize(sz);
177 self.count = sz;
178 int i = 0;
179 for(auto& e : self.expressions)
180 {
181 e.init(self.cur_time, self.cur_deltatime, self.cur_pos, self.count);
182 e.instance = i++;
183 if(!e.expr.set_expression(expr))
184 return false;
185 e.expr.seed_random(
186 UINT64_C(0xda3e39cb94b95bdb), UINT64_C(0x853c49e6748fea9b) * (1 + i));
187 }
188 self.last_expression = expr;
189 return true;
190 }
191
192 static void run_polyphonic(
193 int size, value_output_callback& output, const std::string& expr,
194 const halp::tick_flicks& tk, State& self)
195 {
196 if(size <= 1
197 || (expr.find(":=") != std::string::npos && expr.find("po") != std::string::npos))
198 {
199 size = std::clamp(size, 0, 1024);
200 resize(expr, self, size);
201
202 setMathExpressionTiming(
203 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
204 self.last_value_time = tk.start_in_flicks;
205
206 GenericMathMapping::exec_polyphonic(self, output);
207
208 std::vector<ossia::value> res;
209 res.resize(self.expressions.size());
210 self.count = size;
211 for(int i = 0; i < self.expressions.size(); i++)
212 res[i] = (float)self.expressions[i].po;
213 // Combine
214 output(std::move(res));
215 }
216 else
217 {
218 resize(expr, self, 1);
219 setMathExpressionTiming(
220 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
221 self.last_value_time = tk.start_in_flicks;
222
223 std::vector<ossia::value> res;
224 res.resize(size);
225 self.count = size;
226 for(int i = 0; i < size; i++)
227 {
228 auto& e = self.expressions[0];
229 e.instance = i;
230 res[i] = e.expr.result();
231
232 // po isn't used either store_output(e, res);
233 }
234 output(std::move(res));
235 }
236 }
237
238 static void run_polyphonic(
239 const ossia::value& value, value_output_callback& output, const std::string& expr,
240 const halp::tick_flicks& tk, State& self)
241 {
242 setMathExpressionTiming(
243 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
244 self.last_value_time = tk.start_in_flicks;
245 //auto ratio = st.modelToSamples();
246 //auto parent_dur = tk.parent_duration.impl * ratio;
247 //for(const ossia::timed_value& v : input.get_data())
248 //{
249 // auto val = value.target<std::vector<ossia::value>>();
250 // if(!val)
251 // return;
252
253 // int64_t new_time = tk.prev_date.impl * ratio + timestamp;
254 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
255 // self.last_value_time = new_time;
256
257 switch(value.get_type())
258 {
259 case ossia::val_type::NONE:
260 break;
261 case ossia::val_type::IMPULSE:
262 break;
263 case ossia::val_type::INT:
264 if(!resize(expr, self, 1))
265 return;
266 self.expressions[0].x = *value.target<int>();
267 break;
268 case ossia::val_type::FLOAT:
269 if(!resize(expr, self, 1))
270 return;
271 self.expressions[0].x = *value.target<float>();
272 break;
273 case ossia::val_type::BOOL:
274 if(!resize(expr, self, 1))
275 return;
276 self.expressions[0].x = *value.target<bool>() ? 1.f : 0.f;
277 break;
278 case ossia::val_type::STRING:
279 if(!resize(expr, self, 1))
280 return;
281 self.expressions[0].x = ossia::convert<float>(value);
282 break;
283 case ossia::val_type::VEC2F:
284 if(!resize(expr, self, 2))
285 return;
286 self.expressions[0].x = (*value.target<ossia::vec2f>())[0];
287 self.expressions[1].x = (*value.target<ossia::vec2f>())[1];
288 break;
289 case ossia::val_type::VEC3F:
290 if(!resize(expr, self, 3))
291 return;
292 self.expressions[0].x = (*value.target<ossia::vec3f>())[0];
293 self.expressions[1].x = (*value.target<ossia::vec3f>())[1];
294 self.expressions[2].x = (*value.target<ossia::vec3f>())[2];
295 break;
296 case ossia::val_type::VEC4F:
297 if(!resize(expr, self, 4))
298 return;
299 self.expressions[0].x = (*value.target<ossia::vec4f>())[0];
300 self.expressions[1].x = (*value.target<ossia::vec4f>())[1];
301 self.expressions[2].x = (*value.target<ossia::vec4f>())[2];
302 self.expressions[3].x = (*value.target<ossia::vec4f>())[3];
303 break;
304 case ossia::val_type::LIST: {
305 auto& arr = *value.target<std::vector<ossia::value>>();
306 const auto N = std::clamp((int)std::ssize(arr), 0, 1024);
307 if(!resize(expr, self, N))
308 return;
309 for(int i = 0; i < N; i++)
310 self.expressions[i].x = ossia::convert<float>(arr[i]);
311 break;
312 }
313 case ossia::val_type::MAP: {
314 auto& arr = *value.target<ossia::value_map_type>();
315 const auto N = std::clamp((int)std::ssize(arr), 0, 1024);
316 if(!resize(expr, self, N))
317 return;
318 int i = 0;
319 for(auto& [k, v] : arr)
320 self.expressions[i++].x = ossia::convert<float>(v);
321 break;
322 }
323 }
324
325 GenericMathMapping::exec_polyphonic(self, output);
326
327 std::vector<ossia::value> res;
328 res.resize(self.expressions.size());
329 for(int i = 0; i < self.expressions.size(); i++)
330 res[i] = (float)self.expressions[i].po;
331
332 // Combine
333 output(std::move(res));
334 }
335
336 static void run_array(
337 const ossia::value& value, value_output_callback& output,
338 const halp::tick_flicks& tk, State& self)
339 {
340 //auto ratio = st.modelToSamples();
341 //auto parent_dur = tk.parent_duration.impl * ratio;
342 //for(const ossia::timed_value& v : input.get_data())
343 //{
344 // int64_t new_time = tk.prev_date.impl * ratio + timestamp;
345 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
346 // self.last_value_time = new_time;
347
348 auto array_run_scalar = [&](float in) {
349 auto old_size = self.xv.size();
350 self.xv.assign(1, in);
351 auto new_size = 1U;
352 GenericMathMapping::exec_array(self, output, old_size != new_size);
353 };
354
355 switch(value.get_type())
356 {
357 case ossia::val_type::NONE:
358 break;
359 case ossia::val_type::IMPULSE:
360 GenericMathMapping::exec_array(self, output, false);
361 break;
362 case ossia::val_type::INT:
363 array_run_scalar(*value.target<int>());
364 break;
365 case ossia::val_type::FLOAT:
366 array_run_scalar(*value.target<float>());
367 break;
368 case ossia::val_type::BOOL:
369 array_run_scalar(*value.target<bool>() ? 1.f : 0.f);
370 break;
371 case ossia::val_type::STRING:
372 array_run_scalar(ossia::convert<float>(value));
373 break;
374 case ossia::val_type::VEC2F: {
375 auto& arr = *value.target<ossia::vec2f>();
376 auto old_size = self.xv.size();
377 self.xv.assign(arr.begin(), arr.end());
378 auto new_size = 2U;
379 GenericMathMapping::exec_array(self, output, old_size != new_size);
380 break;
381 }
382 case ossia::val_type::VEC3F: {
383 auto& arr = *value.target<ossia::vec3f>();
384 auto old_size = self.xv.size();
385 self.xv.assign(arr.begin(), arr.end());
386 auto new_size = 3U;
387 GenericMathMapping::exec_array(self, output, old_size != new_size);
388 break;
389 }
390 case ossia::val_type::VEC4F: {
391 auto& arr = *value.target<ossia::vec4f>();
392 auto old_size = self.xv.size();
393 self.xv.assign(arr.begin(), arr.end());
394 auto new_size = 4U;
395 GenericMathMapping::exec_array(self, output, old_size != new_size);
396 break;
397 }
398 case ossia::val_type::LIST: {
399 auto& arr = *value.target<std::vector<ossia::value>>();
400 auto old_size = self.xv.size();
401 self.xv.resize(arr.size());
402 auto new_size = arr.size();
403 for(std::size_t i = 0; i < arr.size(); i++)
404 {
405 self.xv[i] = ossia::convert<float>(arr[i]);
406 }
407 GenericMathMapping::exec_array(self, output, old_size != new_size);
408 break;
409 }
410 case ossia::val_type::MAP: {
411 auto& arr = *value.target<ossia::value_map_type>();
412 auto old_size = self.xv.size();
413 self.xv.resize(arr.size());
414 auto new_size = arr.size();
415 int i = 0;
416 for(const auto& [k, v] : arr)
417 {
418 self.xv[i++] = ossia::convert<float>(v);
419 }
420 GenericMathMapping::exec_array(self, output, old_size != new_size);
421 break;
422 }
423 }
424 //}
425 }
426};
427}
Utilities for OSSIA data structures.
Definition DeviceInterface.hpp:33
Definition MathMapping_generic.hpp:12