2 #include <Fx/MathHelpers.hpp>
3 #include <Fx/Types.hpp>
5 #include <ossia/dataflow/value_port.hpp>
7 #include <halp/callback.hpp>
10 template <
typename State>
13 static void store_output(
auto&
self,
const ossia::value& v)
17 case ossia::val_type::NONE:
19 case ossia::val_type::FLOAT:
20 self.po = *v.target<
float>();
22 case ossia::val_type::VEC2F: {
23 if constexpr(requires {
self.pov; })
25 auto& vec = *v.target<ossia::vec2f>();
26 self.pov.assign(vec.begin(), vec.end());
30 case ossia::val_type::VEC3F: {
31 if constexpr(requires {
self.pov; })
33 auto& vec = *v.target<ossia::vec3f>();
34 self.pov.assign(vec.begin(), vec.end());
38 case ossia::val_type::VEC4F: {
39 if constexpr(requires {
self.pov; })
41 auto& vec = *v.target<ossia::vec4f>();
42 self.pov.assign(vec.begin(), vec.end());
46 case ossia::val_type::LIST: {
47 if constexpr(requires {
self.pov; })
49 auto& arr = *v.target<std::vector<ossia::value>>();
54 self.pov.push_back(ossia::convert<float>(v));
65 static void exec_scalar(
State&
self, value_output_callback& output)
67 auto res =
self.expr.result();
70 store_output(
self, res);
75 static void exec_polyphonic(
State&
self, value_output_callback& output)
77 for(
auto& e :
self.expressions)
79 auto res = e.expr.result();
81 if constexpr(requires { e.x; })
89 exec_array(
State&
self, value_output_callback& output,
bool vector_size_did_change)
94 if(vector_size_did_change)
96 self.expr.remove_vector(
"xv");
97 self.expr.add_vector(
"xv",
self.xv);
98 self.expr.recompile();
101 auto res =
self.expr.result();
102 store_output(
self, res);
106 bool old_prev =
self.pxv.size();
107 self.pxv.assign(
self.xv.begin(),
self.xv.end());
108 bool new_prev =
self.pxv.size();
110 if(old_prev != new_prev)
112 self.expr.remove_vector(
"pxv");
113 self.expr.add_vector(
"pxv",
self.pxv);
114 self.expr.recompile();
118 output(std::move(res));
121 static void run_scalar(
122 const ossia::value& v, value_output_callback& output,
const halp::tick_flicks& tk,
137 case ossia::val_type::NONE:
139 case ossia::val_type::IMPULSE:
141 case ossia::val_type::INT:
142 self.x = *v.target<
int>();
144 case ossia::val_type::FLOAT:
145 self.x = *v.target<
float>();
147 case ossia::val_type::BOOL:
148 self.x = *v.target<
bool>() ? 1.f : 0.f;
150 case ossia::val_type::STRING:
151 self.x = ossia::convert<float>(v);
153 case ossia::val_type::VEC2F:
154 self.x = (*v.target<ossia::vec2f>())[0];
156 case ossia::val_type::VEC3F:
157 self.x = (*v.target<ossia::vec3f>())[0];
159 case ossia::val_type::VEC4F:
160 self.x = (*v.target<ossia::vec4f>())[0];
162 case ossia::val_type::LIST: {
163 auto& arr = *v.target<std::vector<ossia::value>>();
165 self.x = ossia::convert<float>(arr[0]);
168 case ossia::val_type::MAP: {
169 auto& arr = *v.target<ossia::value_map_type>();
171 self.x = ossia::convert<float>(arr.begin()->second);
176 GenericMathMapping::exec_scalar(
self, output);
179 static bool resize(
const std::string& expr,
State&
self,
int sz)
181 if(std::ssize(
self.expressions) == sz && expr ==
self.last_expression)
184 self.expressions.resize(sz);
186 for(
auto& e :
self.expressions)
188 e.init(
self.cur_time,
self.cur_deltatime,
self.cur_pos);
190 if(!e.expr.set_expression(expr))
193 UINT64_C(0xda3e39cb94b95bdb), UINT64_C(0x853c49e6748fea9b) * (1 + i));
195 self.last_expression = expr;
199 static void run_polyphonic(
200 int size, value_output_callback& output,
const std::string& expr,
201 const halp::tick_flicks& tk,
State&
self)
204 || (expr.find(
":=") != std::string::npos && expr.find(
"po") != std::string::npos))
206 resize(expr,
self, size);
208 setMathExpressionTiming(
209 self, tk.start_in_flicks,
self.last_value_time, tk.relative_position);
210 self.last_value_time = tk.start_in_flicks;
212 GenericMathMapping::exec_polyphonic(
self, output);
214 std::vector<ossia::value> res;
215 res.resize(
self.expressions.size());
216 for(
int i = 0; i <
self.expressions.size(); i++)
217 res[i] = (
float)
self.expressions[i].po;
219 output(std::move(res));
223 resize(expr,
self, 1);
224 setMathExpressionTiming(
225 self, tk.start_in_flicks,
self.last_value_time, tk.relative_position);
226 self.last_value_time = tk.start_in_flicks;
228 std::vector<ossia::value> res;
230 for(
int i = 0; i < size; i++)
232 auto& e =
self.expressions[0];
234 res[i] = e.expr.result();
238 output(std::move(res));
242 static void run_polyphonic(
243 const ossia::value& value, value_output_callback& output,
const std::string& expr,
244 const halp::tick_flicks& tk,
State&
self)
246 setMathExpressionTiming(
247 self, tk.start_in_flicks,
self.last_value_time, tk.relative_position);
248 self.last_value_time = tk.start_in_flicks;
261 switch(value.get_type())
263 case ossia::val_type::NONE:
265 case ossia::val_type::IMPULSE:
267 case ossia::val_type::INT:
268 if(!resize(expr,
self, 1))
270 self.expressions[0].x = *value.target<
int>();
272 case ossia::val_type::FLOAT:
273 if(!resize(expr,
self, 1))
275 self.expressions[0].x = *value.target<
float>();
277 case ossia::val_type::BOOL:
278 if(!resize(expr,
self, 1))
280 self.expressions[0].x = *value.target<
bool>() ? 1.f : 0.f;
282 case ossia::val_type::STRING:
283 if(!resize(expr,
self, 1))
285 self.expressions[0].x = ossia::convert<float>(value);
287 case ossia::val_type::VEC2F:
288 if(!resize(expr,
self, 2))
290 self.expressions[0].x = (*value.target<ossia::vec2f>())[0];
291 self.expressions[1].x = (*value.target<ossia::vec2f>())[1];
293 case ossia::val_type::VEC3F:
294 if(!resize(expr,
self, 3))
296 self.expressions[0].x = (*value.target<ossia::vec3f>())[0];
297 self.expressions[1].x = (*value.target<ossia::vec3f>())[1];
298 self.expressions[2].x = (*value.target<ossia::vec3f>())[2];
300 case ossia::val_type::VEC4F:
301 if(!resize(expr,
self, 4))
303 self.expressions[0].x = (*value.target<ossia::vec4f>())[0];
304 self.expressions[1].x = (*value.target<ossia::vec4f>())[1];
305 self.expressions[2].x = (*value.target<ossia::vec4f>())[2];
306 self.expressions[3].x = (*value.target<ossia::vec4f>())[3];
308 case ossia::val_type::LIST: {
309 auto& arr = *value.target<std::vector<ossia::value>>();
310 const auto N = std::ssize(arr);
311 if(!resize(expr,
self, N))
313 for(
int i = 0; i < N; i++)
314 self.expressions[i].x = ossia::convert<float>(arr[i]);
317 case ossia::val_type::MAP: {
318 auto& arr = *value.target<ossia::value_map_type>();
319 const auto N = std::ssize(arr);
320 if(!resize(expr,
self, N))
323 for(
auto& [k, v] : arr)
324 self.expressions[i++].x = ossia::convert<float>(v);
329 GenericMathMapping::exec_polyphonic(
self, output);
331 std::vector<ossia::value> res;
332 res.resize(
self.expressions.size());
333 for(
int i = 0; i <
self.expressions.size(); i++)
334 res[i] = (
float)
self.expressions[i].po;
337 output(std::move(res));
340 static void run_array(
341 const ossia::value& value, value_output_callback& output,
342 const halp::tick_flicks& tk,
State&
self)
352 auto array_run_scalar = [&](
float in) {
353 auto old_size =
self.xv.size();
354 self.xv.assign(1, in);
356 GenericMathMapping::exec_array(
self, output, old_size != new_size);
359 switch(value.get_type())
361 case ossia::val_type::NONE:
363 case ossia::val_type::IMPULSE:
364 GenericMathMapping::exec_array(
self, output,
false);
366 case ossia::val_type::INT:
367 array_run_scalar(*value.target<
int>());
369 case ossia::val_type::FLOAT:
370 array_run_scalar(*value.target<
float>());
372 case ossia::val_type::BOOL:
373 array_run_scalar(*value.target<
bool>() ? 1.f : 0.f);
375 case ossia::val_type::STRING:
376 array_run_scalar(ossia::convert<float>(value));
378 case ossia::val_type::VEC2F: {
379 auto& arr = *value.target<ossia::vec2f>();
380 auto old_size =
self.xv.size();
381 self.xv.assign(arr.begin(), arr.end());
383 GenericMathMapping::exec_array(
self, output, old_size != new_size);
386 case ossia::val_type::VEC3F: {
387 auto& arr = *value.target<ossia::vec3f>();
388 auto old_size =
self.xv.size();
389 self.xv.assign(arr.begin(), arr.end());
391 GenericMathMapping::exec_array(
self, output, old_size != new_size);
394 case ossia::val_type::VEC4F: {
395 auto& arr = *value.target<ossia::vec4f>();
396 auto old_size =
self.xv.size();
397 self.xv.assign(arr.begin(), arr.end());
399 GenericMathMapping::exec_array(
self, output, old_size != new_size);
402 case ossia::val_type::LIST: {
403 auto& arr = *value.target<std::vector<ossia::value>>();
404 auto old_size =
self.xv.size();
405 self.xv.resize(arr.size());
406 auto new_size = arr.size();
407 for(std::size_t i = 0; i < arr.size(); i++)
409 self.xv[i] = ossia::convert<float>(arr[i]);
411 GenericMathMapping::exec_array(
self, output, old_size != new_size);
414 case ossia::val_type::MAP: {
415 auto& arr = *value.target<ossia::value_map_type>();
416 auto old_size =
self.xv.size();
417 self.xv.resize(arr.size());
418 auto new_size = arr.size();
420 for(
const auto& [k, v] : arr)
422 self.xv[i++] = ossia::convert<float>(v);
424 GenericMathMapping::exec_array(
self, output, old_size != new_size);
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: MathMapping_generic.hpp:12