diff --git a/src/plugins/score-plugin-fx/Fx/Arraymap.hpp b/src/plugins/score-plugin-fx/Fx/Arraymap.hpp index 23c144e7e9..40334601f8 100644 --- a/src/plugins/score-plugin-fx/Fx/Arraymap.hpp +++ b/src/plugins/score-plugin-fx/Fx/Arraymap.hpp @@ -27,6 +27,7 @@ struct Node { // Messages to this port trigger a new computation cycle with updated timestamps halp_flag(active_port); + void update(Node& self) { self.trigger = true; } } port; halp::lineedit<"Expression", "x"> expr; } inputs; @@ -74,11 +75,14 @@ struct Node int64_t last_value_time{}; std::string last_expression; } state; + bool trigger{false}; using tick = halp::tick_flicks; void operator()(const tick& tk) { + if(!std::exchange(trigger, false)) + return; GenericMathMapping::run_polyphonic( inputs.port.value, outputs.port.call, inputs.expr.value, tk, state); } diff --git a/src/plugins/score-plugin-fx/Fx/MathValueFilter.hpp b/src/plugins/score-plugin-fx/Fx/MathValueFilter.hpp index 0bc69d3829..2885d31272 100644 --- a/src/plugins/score-plugin-fx/Fx/MathValueFilter.hpp +++ b/src/plugins/score-plugin-fx/Fx/MathValueFilter.hpp @@ -30,6 +30,7 @@ struct Node { // Messages to this port trigger a new computation cycle with updated timestamps halp_flag(active_port); + void update(Node& self) { self.trigger = true; } } port; halp::lineedit<"Expression (ExprTK)", "cos(t) + log(pos * (1+abs(x)) / dt)"> expr; halp::hslider_f32<"Param (a)", halp::range{0., 1., 0.5}> a; @@ -102,10 +103,13 @@ struct Node } state; halp::setup setup; + bool trigger{false}; void prepare(halp::setup s) { setup = s; } void operator()(const tick& tk) { + if(!std::exchange(trigger, false)) + return; auto& self = this->state; if(!self.expr.set_expression(this->inputs.expr)) return; diff --git a/src/plugins/score-plugin-fx/Fx/MicroMapping.hpp b/src/plugins/score-plugin-fx/Fx/MicroMapping.hpp index de5a42960f..98c303f4ad 100644 --- a/src/plugins/score-plugin-fx/Fx/MicroMapping.hpp +++ b/src/plugins/score-plugin-fx/Fx/MicroMapping.hpp @@ -24,7 +24,9 @@ struct Node struct : halp::val_port<"in", ossia::value> { // Messages to this port trigger a new computation cycle with updated timestamps + // FIXME not implemented yet halp_flag(active_port); + void update(Node& self) { self.trigger = true; } } port; halp::lineedit<"Expression", "x / 127"> expr; } inputs; @@ -76,12 +78,15 @@ struct Node } state; halp::setup setup; + bool trigger{false}; void prepare(halp::setup s) { setup = s; } using tick = halp::tick_flicks; void operator()(const tick& tk) { + if(!std::exchange(trigger, false)) + return; auto& self = this->state; if(!self.expr.set_expression(this->inputs.expr)) return; diff --git a/src/plugins/score-plugin-fx/Fx/Smooth.hpp b/src/plugins/score-plugin-fx/Fx/Smooth.hpp index 4ae87970f4..aa5aaeac11 100644 --- a/src/plugins/score-plugin-fx/Fx/Smooth.hpp +++ b/src/plugins/score-plugin-fx/Fx/Smooth.hpp @@ -32,6 +32,7 @@ struct Node : NoiseState { // Messages to this port trigger a new computation cycle with updated timestamps halp_flag(active_port); + void update(Node& self) { self.trigger = true; } } port; halp::enum_t type; halp::knob_f32<"Amount", halp::range{0., 1., 0.1}> amount; @@ -43,9 +44,12 @@ struct Node : NoiseState { value_out port{}; } outputs; + bool trigger{false}; void operator()() { + if(!std::exchange(trigger, false)) + return; auto& v = this->inputs.port.value; auto filtered = this->filter( diff --git a/src/plugins/score-plugin-fx/Fx/VelToNote.hpp b/src/plugins/score-plugin-fx/Fx/VelToNote.hpp index 0b68dc7203..7e93b8ed3e 100644 --- a/src/plugins/score-plugin-fx/Fx/VelToNote.hpp +++ b/src/plugins/score-plugin-fx/Fx/VelToNote.hpp @@ -74,6 +74,7 @@ struct Node { Note note{}; int64_t date{}; + bool fresh{}; }; std::vector to_start; std::vector running_notes; @@ -166,21 +167,25 @@ struct Node auto note = in.value.apply(val_visitor{*this, base_note, base_vel}); if(rand_note != 0) - note.pitch += rnd::rand(-rand_note, rand_note); + note.pitch = std::clamp( + (int)note.pitch + (int)rnd::rand(-rand_note, rand_note), 0, 127); + if(rand_vel != 0) - note.vel += rnd::rand(-rand_vel, rand_vel); + note.vel + = std::clamp((int)note.vel + (int)rnd::rand(-rand_vel, rand_vel), 0, 127); note.pitch = ossia::clamp((int)note.pitch + shiftnote, 0, 127); note.vel = ossia::clamp((int)note.vel, 0, 127); - if(note.vel != 0) + if(note.vel != 0.) { if(start == 0.f) // No quantification, start directly { outputs.midi.note_on(chan, note.pitch, note.vel).timestamp = in.timestamp; if(end > 0.f) { - this->running_notes.push_back({note, tk.position_in_frames + in.timestamp}); + this->running_notes.push_back( + {note, tk.position_in_frames + in.timestamp, true}); } else if(end == 0.f) { @@ -189,7 +194,10 @@ struct Node outputs.midi.note_off(chan, note.pitch, note.vel).timestamp = in.timestamp; #endif } - // else do nothing and just wait for a note off + else + { + // else do nothing and just wait for a note off + } } else { @@ -270,11 +278,21 @@ struct Node void stop_notes(ossia::physical_time date_phys, int chan) { - for(auto& note : this->running_notes) + for(auto it = this->running_notes.begin(); it != this->running_notes.end();) { - outputs.midi.note_off(chan, note.note.pitch, note.note.vel).timestamp = date_phys; + auto& note = *it; + if(!note.fresh) + { + it = this->running_notes.erase(it); + outputs.midi.note_off(chan, note.note.pitch, note.note.vel).timestamp + = date_phys; + } + else + { + note.fresh = false; + ++it; + } } - this->running_notes.clear(); /* for(auto it = this->running_notes.begin(); it != this->running_notes.end();) {