diff --git a/3rdparty/avendish b/3rdparty/avendish index 7763a02b87..7a40ef0cc5 160000 --- a/3rdparty/avendish +++ b/3rdparty/avendish @@ -1 +1 @@ -Subproject commit 7763a02b876e0990be3aa6a4fa06b66e2d878c00 +Subproject commit 7a40ef0cc55ee81f1bc14b0e837446af084458cc diff --git a/src/lib/score/tools/RecursiveWatch.hpp b/src/lib/score/tools/RecursiveWatch.hpp index cbd0237541..f343dd217e 100644 --- a/src/lib/score/tools/RecursiveWatch.hpp +++ b/src/lib/score/tools/RecursiveWatch.hpp @@ -46,4 +46,7 @@ class SCORE_LIB_BASE_EXPORT RecursiveWatch std::string m_root; ossia::string_map> m_watched; }; + +SCORE_LIB_BASE_EXPORT +void for_all_files(std::string_view root, std::function f); } diff --git a/src/plugins/score-plugin-avnd/CMakeLists.txt b/src/plugins/score-plugin-avnd/CMakeLists.txt index e7d6e596e4..57f99b5bdb 100644 --- a/src/plugins/score-plugin-avnd/CMakeLists.txt +++ b/src/plugins/score-plugin-avnd/CMakeLists.txt @@ -604,6 +604,14 @@ avnd_make_score( NAMESPACE examples::helpers ) +avnd_make_score( + SOURCES + "${AVND_FOLDER}/examples/Advanced/AudioParticles/AudioParticles.hpp" + "${AVND_FOLDER}/examples/Advanced/AudioParticles/AudioParticles.cpp" + TARGET avnd_audio_particles + MAIN_CLASS AudioParticles + NAMESPACE ao +) avnd_make_score( SOURCES "${AVND_FOLDER}/examples/Advanced/GeoZones/GeoZones.hpp" diff --git a/src/plugins/score-plugin-fx/Fx/MathMapping.hpp b/src/plugins/score-plugin-fx/Fx/MathMapping.hpp index 70e8a306b0..d813c5e749 100644 --- a/src/plugins/score-plugin-fx/Fx/MathMapping.hpp +++ b/src/plugins/score-plugin-fx/Fx/MathMapping.hpp @@ -6,7 +6,7 @@ namespace Nodes template struct GenericMathMapping { - static void store_output(State& self, const ossia::value& v) + static void store_output(auto& self, const ossia::value& v) { switch(v.get_type()) { @@ -16,27 +16,39 @@ struct GenericMathMapping self.po = *v.target(); break; case ossia::val_type::VEC2F: { - auto& vec = *v.target(); - self.pov.assign(vec.begin(), vec.end()); + if constexpr(requires { self.pov; }) + { + auto& vec = *v.target(); + self.pov.assign(vec.begin(), vec.end()); + } break; } case ossia::val_type::VEC3F: { - auto& vec = *v.target(); - self.pov.assign(vec.begin(), vec.end()); + if constexpr(requires { self.pov; }) + { + auto& vec = *v.target(); + self.pov.assign(vec.begin(), vec.end()); + } break; } case ossia::val_type::VEC4F: { - auto& vec = *v.target(); - self.pov.assign(vec.begin(), vec.end()); + if constexpr(requires { self.pov; }) + { + auto& vec = *v.target(); + self.pov.assign(vec.begin(), vec.end()); + } break; } case ossia::val_type::LIST: { - auto& arr = *v.target>(); - if(!arr.empty()) + if constexpr(requires { self.pov; }) { - self.pov.clear(); - for(auto& v : arr) - self.pov.push_back(ossia::convert(v)); + auto& arr = *v.target>(); + if(!arr.empty()) + { + self.pov.clear(); + for(auto& v : arr) + self.pov.push_back(ossia::convert(v)); + } } break; } @@ -56,6 +68,17 @@ struct GenericMathMapping output.write_value(res, timestamp); } + static void exec_polyphonic(int64_t timestamp, State& self, ossia::value_port& output) + { + for(auto& e : self.expressions) + { + auto res = e.expr.result(); + + e.px = e.x; + store_output(e, res); + } + } + static void exec_array( int64_t timestamp, State& self, ossia::value_port& output, bool vector_size_did_change) @@ -140,6 +163,105 @@ struct GenericMathMapping GenericMathMapping::exec_scalar(v.timestamp, self, output); } } + static void run_polyphonic( + const ossia::value_port& input, ossia::value_port& output, const std::string& expr, + const ossia::token_request& tk, ossia::exec_state_facade st, State& self) + { + if(input.get_data().empty()) + return; + + auto ratio = st.modelToSamples(); + auto parent_dur = tk.parent_duration.impl * ratio; + for(const ossia::timed_value& v : input.get_data()) + { + auto val = v.value.target>(); + if(!val) + return; + + auto resize = [&expr, &self](int sz) { + self.expressions.resize(sz); + for(auto& e : self.expressions) + { + e.init(self.cur_time, self.cur_deltatime, self.cur_pos); + if(!e.expr.set_expression(expr)) + return false; + } + return true; + }; + + int64_t new_time = tk.prev_date.impl * ratio + v.timestamp; + setMathExpressionTiming(self, new_time, self.last_value_time, parent_dur); + self.last_value_time = new_time; + + switch(v.value.get_type()) + { + case ossia::val_type::NONE: + break; + case ossia::val_type::IMPULSE: + break; + case ossia::val_type::INT: + if(!resize(1)) + return; + self.expressions[0].x = *v.value.target(); + break; + case ossia::val_type::FLOAT: + if(!resize(1)) + return; + self.expressions[0].x = *v.value.target(); + break; + case ossia::val_type::BOOL: + if(!resize(1)) + return; + self.expressions[0].x = *v.value.target() ? 1.f : 0.f; + break; + case ossia::val_type::STRING: + if(!resize(1)) + return; + self.expressions[0].x = ossia::convert(v.value); + break; + case ossia::val_type::VEC2F: + if(!resize(2)) + return; + self.expressions[0].x = (*v.value.target())[0]; + self.expressions[1].x = (*v.value.target())[1]; + break; + case ossia::val_type::VEC3F: + if(!resize(3)) + return; + self.expressions[0].x = (*v.value.target())[0]; + self.expressions[1].x = (*v.value.target())[1]; + self.expressions[2].x = (*v.value.target())[2]; + break; + case ossia::val_type::VEC4F: + if(!resize(4)) + return; + self.expressions[0].x = (*v.value.target())[0]; + self.expressions[1].x = (*v.value.target())[1]; + self.expressions[2].x = (*v.value.target())[2]; + self.expressions[3].x = (*v.value.target())[3]; + break; + case ossia::val_type::LIST: { + auto& arr = *v.value.target>(); + + if(!resize(arr.size())) + return; + for(int i = 0; i < arr.size(); i++) + self.expressions[i].x = ossia::convert(arr[i]); + break; + } + } + + GenericMathMapping::exec_polyphonic(v.timestamp, self, output); + + std::vector res; + res.resize(self.expressions.size()); + for(int i = 0; i < self.expressions.size(); i++) + res[i] = (float)self.expressions[i].po; + + // Combine + output.write_value(res, v.timestamp); + } + } static void run_array( const ossia::value_port& input, ossia::value_port& output, @@ -603,6 +725,80 @@ struct Node } }; } + +namespace ArrayMapping +{ +struct Node +{ + struct Metadata : Control::Meta_base + { + static const constexpr auto prettyName = "Arraymap"; + static const constexpr auto objectKey = "ArrayMapping"; + static const constexpr auto category = "Control/Mappings"; + static const constexpr auto author = "ossia score, ExprTK (Arash Partow)"; + static const constexpr auto kind = Process::ProcessCategory::Mapping; + static const constexpr auto description + = "Applies a math expression to each member of an input."; + static const constexpr auto tags = std::array{}; + static const uuid_constexpr auto uuid + = make_uuid("1fe9c806-b601-4ee0-9fbb-0ab817c4dd87"); + + static const constexpr value_in value_ins[]{value_in{"in", false}}; + static const constexpr value_out value_outs[]{"out"}; + + static const constexpr auto controls + = tuplet::make_tuple(Control::LineEdit("Expression", "x")); + }; + struct State + { + struct Expr + { + void init(double& cur_time, double& cur_deltatime, double& cur_pos) + { + expr.add_variable("x", x); + expr.add_variable("px", px); + expr.add_variable("po", po); + + expr.add_variable("t", cur_time); + expr.add_variable("dt", cur_deltatime); + expr.add_variable("pos", cur_pos); + expr.add_constants(); + + expr.register_symbol_table(); + } + double x; + double px; + double po; + + ossia::math_expression expr; + }; + + boost::container::static_vector expressions; + double cur_time{}; + double cur_deltatime{}; + double cur_pos{}; + + int64_t last_value_time{}; + + //bool ok = false; + }; + + using control_policy = ossia::safe_nodes::last_tick; + + static void + run(const ossia::value_port& input, const std::string& expr, ossia::value_port& output, + const ossia::token_request& tk, ossia::exec_state_facade st, State& self) + { + GenericMathMapping::run_polyphonic(input, output, expr, tk, st, self); + } + + template + static void item(Args&&... args) + { + Nodes::miniMathItem(Metadata::controls, std::forward(args)...); + } +}; +} } namespace Control @@ -624,6 +820,10 @@ struct HasCustomUI : std::true_type { }; template <> +struct HasCustomUI : std::true_type +{ +}; +template <> struct HasCustomUI : std::true_type { }; diff --git a/src/plugins/score-plugin-fx/score_plugin_fx.cpp b/src/plugins/score-plugin-fx/score_plugin_fx.cpp index 4eaf960dc5..eaa44664e6 100644 --- a/src/plugins/score-plugin-fx/score_plugin_fx.cpp +++ b/src/plugins/score-plugin-fx/score_plugin_fx.cpp @@ -60,7 +60,7 @@ std::vector score_plugin_fx::factories( Nodes::Gain::Node, Nodes::Metro::Node, Nodes::Envelope::Node, Nodes::Quantifier::Node, Nodes::MathGenerator::Node, Nodes::MathAudioGenerator::Node, Nodes::MathMapping::Node, - Nodes::MicroMapping::Node, Nodes::MathAudioFilter::Node, + Nodes::MicroMapping::Node, Nodes::ArrayMapping::Node, Nodes::MathAudioFilter::Node, Nodes::EmptyValueMapping::Node, Nodes::EmptyMidiMapping::Node, Nodes::EmptyAudioMapping::Node, Nodes::FactorOracle::Node, Nodes::FactorOracle2::Node, Nodes::FactorOracle2MIDI::Node,