2 #include <Engine/Node/SimpleApi.hpp>
4 #include <ossia/math/math_expression.hpp>
10 template <
typename State>
11 static void setMathExpressionTiming(
12 State&
self, int64_t input_time, int64_t prev_time, int64_t parent_dur)
14 self.cur_time = input_time;
15 self.cur_deltatime = (input_time - prev_time);
16 self.cur_pos = parent_dur > 0 ? double(input_time) / parent_dur : 0;
19 template <
typename State>
20 static void setMathExpressionTiming(
21 State&
self, ossia::time_value input_time, ossia::time_value prev_time,
22 ossia::time_value parent_dur,
double modelToSamples)
24 setMathExpressionTiming(
25 self, input_time.impl * modelToSamples, prev_time.impl * modelToSamples,
26 parent_dur.impl * modelToSamples);
29 template <
typename State>
30 static void setMathExpressionTiming(
31 State&
self,
const ossia::token_request& tk, ossia::exec_state_facade st)
33 setMathExpressionTiming(
34 self, tk.date, tk.prev_date, tk.parent_duration, st.modelToSamples());
37 static void miniMathItem(
38 const tuplet::tuple<Control::LineEdit>& controls, Process::LineEdit& edit,
44 using namespace tuplet;
49 = makeControlNoText(get<0>(controls), edit, parent, context, doc, portFactory);
50 edit_item.control.setTextWidth(100);
51 edit_item.control.setPos(15, 0);
56 &edit_item.control, &Process::LineEditItem::sizeChanged, obj,
57 &score::ResizeableItem::childrenSizeChanged);
65 Process::LineEdit& edit, Process::FloatSlider& a, Process::FloatSlider& b,
71 using namespace tuplet;
78 c0_bg->setRect({0., 0., 300., 200.});
81 = makeControl(get<0>(controls), edit, parent, context, doc, portFactory);
82 edit_item.control.setTextWidth(280);
83 edit_item.root.setPos(c0, 40);
91 auto a_item = makeControl(get<1>(controls), a, parent, context, doc, portFactory);
92 a_item.root.setPos(c0, 5);
93 auto b_item = makeControl(get<2>(controls), b, parent, context, doc, portFactory);
94 b_item.root.setPos(c0 + 70, 5);
95 auto c_item = makeControl(get<3>(controls), c, parent, context, doc, portFactory);
96 c_item.root.setPos(c0 + 140, 5);
99 namespace MathGenerator
105 static const constexpr
auto prettyName =
"Expression Value Generator";
106 static const constexpr
auto objectKey =
"MathGenerator";
107 static const constexpr
auto category =
"Control/Generators";
108 static const constexpr
auto author =
"ossia score, ExprTK (Arash Partow)";
109 static const constexpr
auto tags = std::array<const char*, 0>{};
110 static const constexpr
auto kind = Process::ProcessCategory::Generator;
111 static const constexpr
auto description
112 =
"Generate a signal from a math expression.\n"
113 "Available variables: a,b,c, t (samples), dt (delta), pos (position "
115 "See the documentation at http://www.partow.net/programming/exprtk";
116 static const uuid_constexpr
auto uuid
117 = make_uuid(
"d757bd0d-c0a1-4aec-bf72-945b722ab85b");
119 static const constexpr value_out value_outs[]{
"out"};
121 static const constexpr
auto controls = tuplet::make_tuple(
131 expr.add_variable(
"t", cur_time);
132 expr.add_variable(
"dt", cur_deltatime);
133 expr.add_variable(
"pos", cur_pos);
134 expr.add_variable(
"a", p1);
135 expr.add_variable(
"b", p2);
136 expr.add_variable(
"c", p3);
137 expr.add_variable(
"m1", m1);
138 expr.add_variable(
"m2", m2);
139 expr.add_variable(
"m3", m3);
140 expr.add_constants();
141 expr.register_symbol_table();
144 double cur_deltatime{};
146 double p1{}, p2{}, p3{};
147 double m1{}, m2{}, m3{};
148 ossia::math_expression expr;
152 using control_policy = ossia::safe_nodes::last_tick;
154 run(
const std::string& expr,
float a,
float b,
float c, ossia::value_port& output,
155 ossia::token_request tk, ossia::exec_state_facade st,
State&
self)
157 if(!
self.expr.set_expression(expr))
160 setMathExpressionTiming(
self, tk, st);
165 auto res =
self.expr.result();
166 const auto [tick_start, d] = st.timings(tk);
167 output.write_value(res, tick_start);
170 template <
typename... Args>
171 static void item(Args&&... args)
173 Nodes::mathItem(Metadata::controls, std::forward<Args>(args)...);
178 namespace MathAudioGenerator
184 static const constexpr
auto prettyName =
"Expression Audio Generator";
185 static const constexpr
auto objectKey =
"MathAudioGenerator";
186 static const constexpr
auto category =
"Audio/Utilities";
187 static const constexpr
auto author =
"ossia score, ExprTK (Arash Partow)";
188 static const constexpr
auto tags = std::array<const char*, 0>{};
189 static const constexpr
auto kind = Process::ProcessCategory::Generator;
190 static const constexpr
auto description
191 =
"Generate an audio signal from a math expression.\n"
192 "Available variables: a,b,c, t (samples), fs (sampling frequency)\n"
193 "See the documentation at http://www.partow.net/programming/exprtk";
194 static const uuid_constexpr
auto uuid
195 = make_uuid(
"eae294b3-afeb-4fba-bbe4-337998d3748a");
197 static const constexpr audio_out audio_outs[]{
"out"};
199 static const constexpr
auto controls = tuplet::make_tuple(
201 "Expression (ExprTK)",
202 "var phi := 2 * pi * (20 + a * 500) / fs;\n"
205 "out[0] := b * cos(m1[0]);\n"
206 "out[1] := b * cos(m1[0]);\n"),
225 expr.add_vector(
"out", cur_out);
226 expr.add_variable(
"t", cur_time);
227 expr.add_variable(
"a", p1);
228 expr.add_variable(
"b", p2);
229 expr.add_variable(
"c", p3);
230 expr.add_vector(
"m1", m1);
231 expr.add_vector(
"m2", m2);
232 expr.add_vector(
"m3", m3);
233 expr.add_variable(
"fs", fs);
235 expr.add_constants();
236 expr.register_symbol_table();
239 void reset_symbols(std::size_t N)
242 if(N == cur_out.size())
245 expr.remove_vector(
"out");
246 expr.remove_vector(
"m1");
247 expr.remove_vector(
"m2");
248 expr.remove_vector(
"m3");
255 expr.add_vector(
"out", cur_out);
256 expr.add_vector(
"m1", m1);
257 expr.add_vector(
"m2", m2);
258 expr.add_vector(
"m3", m3);
260 expr.update_symbol_table();
262 std::vector<double> cur_out{};
264 double p1{}, p2{}, p3{};
265 std::vector<double> m1, m2, m3;
267 ossia::math_expression expr;
271 using control_policy = ossia::safe_nodes::last_tick;
273 run(
const std::string& expr,
float a,
float b,
float c, ossia::audio_port& output,
274 ossia::token_request tk, ossia::exec_state_facade st,
State&
self)
278 self.fs = st.sampleRate();
279 if(!
self.expr.set_expression(expr))
282 const auto samplesRatio = st.modelToSamples();
283 const auto [tick_start, count] = st.timings(tk);
286 self.reset_symbols(chans);
287 output.set_channels(chans);
288 for(
int j = 0; j < chans; j++)
290 auto& out = output.channel(j);
291 out.resize(st.bufferSize(), boost::container::default_init);
297 const auto start_sample = (tk.prev_date * samplesRatio).impl;
298 for(int64_t i = 0; i < count; i++)
300 self.cur_time = start_sample + i;
306 for(
int j = 0; j < chans; j++)
308 output.channel(j)[tick_start + i] =
self.cur_out[j];
314 template <
typename... Args>
315 static void item(Args&&... args)
317 Nodes::mathItem(Metadata::controls, std::forward<Args>(args)...);
Definition: PortFactory.hpp:65
The Process class.
Definition: score-lib-process/Process/Process.hpp:61
Definition: RectItem.hpp:96
Definition: RectItem.hpp:12
Base classes and tools to implement processes and layers.
Definition: JSONVisitor.hpp:1324
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: score-lib-process/Control/Widgets.hpp:77
Definition: score-lib-process/Control/Widgets.hpp:417
Definition: MathGenerator.hpp:181
Definition: MathGenerator.hpp:102
Definition: ProcessContext.hpp:12
const T & interfaces() const
Access to a specific interface list.
Definition: ApplicationContext.hpp:67