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 //auto ratio = st.modelToSamples();
124 //auto parent_dur = tk.parent_duration * ratio;
125 //for(const ossia::timed_value& v : input.get_data())
126 //{
127 // int64_t new_time = tk.prev_date.impl * ratio + timestamp;
128 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
129 // self.last_value_time = new_time;
130
131 // FIXME
132 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
133 switch(v.get_type())
134 {
135 case ossia::val_type::NONE:
136 break;
137 case ossia::val_type::IMPULSE:
138 break;
139 case ossia::val_type::INT:
140 self.x = *v.target<int>();
141 break;
142 case ossia::val_type::FLOAT:
143 self.x = *v.target<float>();
144 break;
145 case ossia::val_type::BOOL:
146 self.x = *v.target<bool>() ? 1.f : 0.f;
147 break;
148 case ossia::val_type::STRING:
149 self.x = ossia::convert<float>(v);
150 break;
151 case ossia::val_type::VEC2F:
152 self.x = (*v.target<ossia::vec2f>())[0];
153 break;
154 case ossia::val_type::VEC3F:
155 self.x = (*v.target<ossia::vec3f>())[0];
156 break;
157 case ossia::val_type::VEC4F:
158 self.x = (*v.target<ossia::vec4f>())[0];
159 break;
160 case ossia::val_type::LIST: {
161 auto& arr = *v.target<std::vector<ossia::value>>();
162 if(!arr.empty())
163 self.x = ossia::convert<float>(arr[0]);
164 break;
165 }
166 case ossia::val_type::MAP: {
167 auto& arr = *v.target<ossia::value_map_type>();
168 if(!arr.empty())
169 self.x = ossia::convert<float>(arr.begin()->second);
170 break;
171 }
172 }
173
174 GenericMathMapping::exec_scalar(self, output);
175 }
176
177 static bool resize(const std::string& expr, State& self, int sz)
178 {
179 if(std::ssize(self.expressions) == sz && expr == self.last_expression)
180 return true;
181
182 self.expressions.resize(sz);
183 self.count = sz;
184 int i = 0;
185 for(auto& e : self.expressions)
186 {
187 e.init(self.cur_time, self.cur_deltatime, self.cur_pos, self.count);
188 e.instance = i++;
189 if(!e.expr.set_expression(expr))
190 return false;
191 e.expr.seed_random(
192 UINT64_C(0xda3e39cb94b95bdb), UINT64_C(0x853c49e6748fea9b) * (1 + i));
193 }
194 self.last_expression = expr;
195 return true;
196 }
197
198 static void run_polyphonic(
199 int size, value_output_callback& output, const std::string& expr,
200 const halp::tick_flicks& tk, State& self)
201 {
202 if(size <= 1
203 || (expr.find(":=") != std::string::npos && expr.find("po") != std::string::npos))
204 {
205 size = std::clamp(size, 0, 1024);
206 resize(expr, self, size);
207
208 setMathExpressionTiming(
209 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
210 self.last_value_time = tk.start_in_flicks;
211
212 GenericMathMapping::exec_polyphonic(self, output);
213
214 std::vector<ossia::value> res;
215 res.resize(self.expressions.size());
216 self.count = size;
217 for(int i = 0; i < self.expressions.size(); i++)
218 res[i] = (float)self.expressions[i].po;
219 // Combine
220 output(std::move(res));
221 }
222 else
223 {
224 resize(expr, self, 1);
225 setMathExpressionTiming(
226 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
227 self.last_value_time = tk.start_in_flicks;
228
229 std::vector<ossia::value> res;
230 res.resize(size);
231 self.count = size;
232 for(int i = 0; i < size; i++)
233 {
234 auto& e = self.expressions[0];
235 e.instance = i;
236 res[i] = e.expr.result();
237
238 // po isn't used either store_output(e, res);
239 }
240 output(std::move(res));
241 }
242 }
243
244 static void run_polyphonic(
245 const ossia::value& value, value_output_callback& output, const std::string& expr,
246 const halp::tick_flicks& tk, State& self)
247 {
248 setMathExpressionTiming(
249 self, tk.start_in_flicks, self.last_value_time, tk.relative_position);
250 self.last_value_time = tk.start_in_flicks;
251 //auto ratio = st.modelToSamples();
252 //auto parent_dur = tk.parent_duration.impl * ratio;
253 //for(const ossia::timed_value& v : input.get_data())
254 //{
255 // auto val = value.target<std::vector<ossia::value>>();
256 // if(!val)
257 // return;
258
259 // int64_t new_time = tk.prev_date.impl * ratio + timestamp;
260 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
261 // self.last_value_time = new_time;
262
263 switch(value.get_type())
264 {
265 case ossia::val_type::NONE:
266 break;
267 case ossia::val_type::IMPULSE:
268 break;
269 case ossia::val_type::INT:
270 if(!resize(expr, self, 1))
271 return;
272 self.expressions[0].x = *value.target<int>();
273 break;
274 case ossia::val_type::FLOAT:
275 if(!resize(expr, self, 1))
276 return;
277 self.expressions[0].x = *value.target<float>();
278 break;
279 case ossia::val_type::BOOL:
280 if(!resize(expr, self, 1))
281 return;
282 self.expressions[0].x = *value.target<bool>() ? 1.f : 0.f;
283 break;
284 case ossia::val_type::STRING:
285 if(!resize(expr, self, 1))
286 return;
287 self.expressions[0].x = ossia::convert<float>(value);
288 break;
289 case ossia::val_type::VEC2F:
290 if(!resize(expr, self, 2))
291 return;
292 self.expressions[0].x = (*value.target<ossia::vec2f>())[0];
293 self.expressions[1].x = (*value.target<ossia::vec2f>())[1];
294 break;
295 case ossia::val_type::VEC3F:
296 if(!resize(expr, self, 3))
297 return;
298 self.expressions[0].x = (*value.target<ossia::vec3f>())[0];
299 self.expressions[1].x = (*value.target<ossia::vec3f>())[1];
300 self.expressions[2].x = (*value.target<ossia::vec3f>())[2];
301 break;
302 case ossia::val_type::VEC4F:
303 if(!resize(expr, self, 4))
304 return;
305 self.expressions[0].x = (*value.target<ossia::vec4f>())[0];
306 self.expressions[1].x = (*value.target<ossia::vec4f>())[1];
307 self.expressions[2].x = (*value.target<ossia::vec4f>())[2];
308 self.expressions[3].x = (*value.target<ossia::vec4f>())[3];
309 break;
310 case ossia::val_type::LIST: {
311 auto& arr = *value.target<std::vector<ossia::value>>();
312 const auto N = std::clamp((int)std::ssize(arr), 0, 1024);
313 if(!resize(expr, self, N))
314 return;
315 for(int i = 0; i < N; i++)
316 self.expressions[i].x = ossia::convert<float>(arr[i]);
317 break;
318 }
319 case ossia::val_type::MAP: {
320 auto& arr = *value.target<ossia::value_map_type>();
321 const auto N = std::clamp((int)std::ssize(arr), 0, 1024);
322 if(!resize(expr, self, N))
323 return;
324 int i = 0;
325 for(auto& [k, v] : arr)
326 self.expressions[i++].x = ossia::convert<float>(v);
327 break;
328 }
329 }
330
331 GenericMathMapping::exec_polyphonic(self, output);
332
333 std::vector<ossia::value> res;
334 res.resize(self.expressions.size());
335 for(int i = 0; i < self.expressions.size(); i++)
336 res[i] = (float)self.expressions[i].po;
337
338 // Combine
339 output(std::move(res));
340 }
341
342 static void run_array(
343 const ossia::value& value, value_output_callback& output,
344 const halp::tick_flicks& tk, State& self)
345 {
346 //auto ratio = st.modelToSamples();
347 //auto parent_dur = tk.parent_duration.impl * ratio;
348 //for(const ossia::timed_value& v : input.get_data())
349 //{
350 // int64_t new_time = tk.prev_date.impl * ratio + timestamp;
351 // setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur);
352 // self.last_value_time = new_time;
353
354 auto array_run_scalar = [&](float in) {
355 auto old_size = self.xv.size();
356 self.xv.assign(1, in);
357 auto new_size = 1U;
358 GenericMathMapping::exec_array(self, output, old_size != new_size);
359 };
360
361 switch(value.get_type())
362 {
363 case ossia::val_type::NONE:
364 break;
365 case ossia::val_type::IMPULSE:
366 GenericMathMapping::exec_array(self, output, false);
367 break;
368 case ossia::val_type::INT:
369 array_run_scalar(*value.target<int>());
370 break;
371 case ossia::val_type::FLOAT:
372 array_run_scalar(*value.target<float>());
373 break;
374 case ossia::val_type::BOOL:
375 array_run_scalar(*value.target<bool>() ? 1.f : 0.f);
376 break;
377 case ossia::val_type::STRING:
378 array_run_scalar(ossia::convert<float>(value));
379 break;
380 case ossia::val_type::VEC2F: {
381 auto& arr = *value.target<ossia::vec2f>();
382 auto old_size = self.xv.size();
383 self.xv.assign(arr.begin(), arr.end());
384 auto new_size = 2U;
385 GenericMathMapping::exec_array(self, output, old_size != new_size);
386 break;
387 }
388 case ossia::val_type::VEC3F: {
389 auto& arr = *value.target<ossia::vec3f>();
390 auto old_size = self.xv.size();
391 self.xv.assign(arr.begin(), arr.end());
392 auto new_size = 3U;
393 GenericMathMapping::exec_array(self, output, old_size != new_size);
394 break;
395 }
396 case ossia::val_type::VEC4F: {
397 auto& arr = *value.target<ossia::vec4f>();
398 auto old_size = self.xv.size();
399 self.xv.assign(arr.begin(), arr.end());
400 auto new_size = 4U;
401 GenericMathMapping::exec_array(self, output, old_size != new_size);
402 break;
403 }
404 case ossia::val_type::LIST: {
405 auto& arr = *value.target<std::vector<ossia::value>>();
406 auto old_size = self.xv.size();
407 self.xv.resize(arr.size());
408 auto new_size = arr.size();
409 for(std::size_t i = 0; i < arr.size(); i++)
410 {
411 self.xv[i] = ossia::convert<float>(arr[i]);
412 }
413 GenericMathMapping::exec_array(self, output, old_size != new_size);
414 break;
415 }
416 case ossia::val_type::MAP: {
417 auto& arr = *value.target<ossia::value_map_type>();
418 auto old_size = self.xv.size();
419 self.xv.resize(arr.size());
420 auto new_size = arr.size();
421 int i = 0;
422 for(const auto& [k, v] : arr)
423 {
424 self.xv[i++] = ossia::convert<float>(v);
425 }
426 GenericMathMapping::exec_array(self, output, old_size != new_size);
427 break;
428 }
429 }
430 //}
431 }
432};
433}
Utilities for OSSIA data structures.
Definition DeviceInterface.hpp:33
Definition MathMapping_generic.hpp:12