29 ossia::value_inlet pattern_select;
30 ossia::value_inlet switch_quantification;
31 ossia::value_inlet fill_in;
32 ossia::value_inlet density_in;
33 ossia::value_inlet velocity_in;
34 ossia::value_inlet swing_in;
35 ossia::value_inlet ratchet_in;
36 ossia::value_inlet pace_in;
37 ossia::value_inlet repeat_time_in;
38 ossia::midi_outlet out;
39 ossia::value_outlet accent_out;
40 ossia::value_outlet slide_out;
44 std::vector<Pattern> patterns;
49 int current_pattern{};
57 float velocity_scale{1.f};
74 double origin = std::numeric_limits<double>::quiet_NaN();
94 uint8_t in_flight_channel{1};
95 bool release_pending{};
98 static constexpr int max_lanes = Pattern::maxLanes;
109 double held_on{-std::numeric_limits<double>::infinity()};
128 std::array<decided, 2> decisions{};
130 std::array<lane_state, max_lanes> lanes{};
159 std::array<event, max_events> queue{};
161 uint32_t next_order{};
164 int immediate_size{};
175 static constexpr int max_points = 2048;
176 std::array<grid_point, max_points> points{};
178 std::minstd_rand rng{0x5eed};
182 int control_lane_count{};
189 std::atomic<int> pattern{-1};
190 std::atomic<int> pending{-1};
191 std::atomic<int> lane_count{0};
192 std::array<std::atomic<int64_t>, max_lanes> lanes;
198 for(
auto& l : shown.lanes)
199 l.store(-1,
std::memory_order_relaxed);
200 m_inlets.push_back(&pattern_select);
201 m_inlets.push_back(&switch_quantification);
202 m_inlets.push_back(&fill_in);
203 m_inlets.push_back(&density_in);
204 m_inlets.push_back(&velocity_in);
205 m_inlets.push_back(&swing_in);
206 m_inlets.push_back(&ratchet_in);
207 m_inlets.push_back(&pace_in);
208 m_inlets.push_back(&repeat_time_in);
209 m_outlets.push_back(&out);
210 m_outlets.push_back(&accent_out);
211 m_outlets.push_back(&slide_out);
214 std::string label() const noexcept
override {
return "pattern_node"; }
216 const Pattern& pattern() const noexcept {
return patterns[current_pattern]; }
223 idx = std::clamp(idx, 0,
int(patterns.size()) - 1);
227 void release_all(int64_t timestamp)
noexcept
229 auto& mess = out.target<ossia::midi_port>()->messages;
230 for(
int note = 0; note < 128; note++)
234 mess.push_back(libremidi::from_midi1::note_off(in_flight_channel, note, 0));
235 mess.back().timestamp = timestamp;
244 l.held_on = -std::numeric_limits<double>::infinity();
250 void reset_lanes() noexcept
262 if(ossia::valid_index(current_pattern, patterns)
263 && ossia::valid_index(current_pattern, list))
265 const Pattern& before = patterns[current_pattern];
266 const Pattern& after = list[current_pattern];
267 const int count_before = std::min(
int(before.lanes.size()), max_lanes);
268 const int count_after = std::min(
int(after.lanes.size()), max_lanes);
269 for(
int i = 0; i < count_after; i++)
271 || laneDivision(before, before.lanes[i]) != laneDivision(after, after.lanes[i]))
273 if(before.length != after.length || before.division != after.division)
276 std::swap(patterns, list);
279 void set_channel(uint8_t c)
noexcept
285 release_pending =
true;
291 static bool finite(
float v)
noexcept {
return std::isfinite(v); }
292 void set_switch_rate(
float v)
noexcept
297 void set_density(
float v)
noexcept
300 density = std::clamp(v, 0.f, 1.f);
302 void set_velocity_scale(
float v)
noexcept
305 velocity_scale = std::clamp(v, 0.f, 1.f);
307 void set_swing(
float v)
noexcept
310 swing = std::clamp(v, 0.f, 1.f);
312 void set_ratchet_scale(
float v)
noexcept
317 void set_pace_offset(
float v)
noexcept
322 void set_repeat_time(ossia::vec2f v)
noexcept
328 void read_controls() noexcept
330 if(
auto& d = pattern_select->get_data(); !d.empty())
332 if(
auto& d = switch_quantification->get_data(); !d.empty())
333 set_switch_rate(ossia::convert<float>(d.back().value));
334 if(
auto& d = fill_in->get_data(); !d.empty())
335 fill = ossia::convert<bool>(d.back().value);
336 if(
auto& d = density_in->get_data(); !d.empty())
337 set_density(ossia::convert<float>(d.back().value));
338 if(
auto& d = velocity_in->get_data(); !d.empty())
339 set_velocity_scale(ossia::convert<float>(d.back().value));
340 if(
auto& d = swing_in->get_data(); !d.empty())
341 set_swing(ossia::convert<float>(d.back().value));
342 if(
auto& d = ratchet_in->get_data(); !d.empty())
343 set_ratchet_scale(ossia::convert<float>(d.back().value));
344 if(
auto& d = pace_in->get_data(); !d.empty())
345 set_pace_offset(ossia::convert<float>(d.back().value));
346 if(
auto& d = repeat_time_in->get_data(); !d.empty())
347 set_repeat_time(ossia::convert<ossia::vec2f>(d.back().value));
353 void run(
const ossia::token_request& tk, ossia::exec_state_facade st)
noexcept override
355 using namespace ossia;
360 if(tk.tempo > 0. && std::isfinite(tk.tempo))
362 update_repeat_time();
364 const double samplesratio = st.modelToSamples();
369 const double speed = tk.speed != 0. ? std::abs(tk.speed) : 1.;
374 const int64_t tick_start
375 = tk.start_sample >= 0
376 ? int64_t(tk.start_sample)
377 : int64_t(
std::floor(tk.offset.impl * samplesratio / speed));
382 release_all(tick_start);
388 if(tk.model_read_duration() == 0_tv)
391 if(tk.end_discontinuous)
397 release_all(tick_start);
403 release_all(tick_start);
404 in_flight_channel = channel;
405 release_pending =
false;
411 current_pattern = std::clamp(current_pattern, 0,
int(patterns.size()) - 1);
416 const bool rewinding = tk.backward();
420 const bool timed = !rewinding
421 && tk.musical_end_position > tk.musical_start_position;
426 release_all(tick_start);
429 if(!std::isfinite(
origin) && std::isfinite(tk.musical_start_position))
430 origin = tk.musical_start_position;
434 constexpr auto never = std::numeric_limits<int64_t>::max();
435 int64_t switch_at = -1;
436 double switch_position{};
439 const auto points = tk.get_quantification_dates(
switch_rate);
444 switch_at = tk.physical_position(points.front().position, samplesratio);
445 switch_position = points.front().position;
452 tk, tick_start, samplesratio, rewinding, timed, 0,
453 switch_at < 0 ? never : switch_at);
458 emit_until(tk, tick_start, samplesratio, switch_position);
459 apply_switch(tick_start + switch_at);
461 play_steps(tk, tick_start, samplesratio, rewinding, timed, switch_at, never);
465 emit_until(tk, tick_start, samplesratio, tk.musical_end_position);
469 void publish() noexcept
472 = patterns.empty() ? 0 : std::min(
int(pattern().lanes.size()), max_lanes);
473 for(
int i = 0; i < count; i++)
474 shown.lanes[i].store(lanes[i].last, std::memory_order_relaxed);
475 shown.lane_count.store(count, std::memory_order_relaxed);
476 shown.pattern.store(patterns.empty() ? -1 : current_pattern,
std::memory_order_relaxed);
483 const ossia::token_request& tk, int64_t tick_start,
double samplesratio,
484 bool rewinding,
bool timed, int64_t from_offset, int64_t to_offset)
noexcept
486 const Pattern& pat = pattern();
491 if(current < 0 || current >= pat.length)
493 const int lane_count = std::min(
int(pat.lanes.size()), max_lanes);
494 control_lane_count = 0;
495 for(
int i = 0; i < lane_count; i++)
496 if(isControlLane(pat.lanes[i]))
506 const auto collect = [&](
int division,
bool main) {
507 tk.for_each_quantification_date(division, [&](
const auto& q) {
512 const int64_t offset = tk.physical_position(q.position, samplesratio);
513 if(offset >= from_offset && offset < to_offset && count < max_points)
514 points[count++] = {q.position, offset, division, main};
517 collect(pat.division,
true);
520 std::array<bool, Pattern::maxDivision + 1> walked{};
522 for(
int i = 0; i < lane_count; i++)
524 const int div = laneDivision(pat, pat.lanes[i]);
532 points.begin(), points.begin() + count,
534 if(a.position != b.position)
535 return a.position < b.position;
536 return a.main > b.main;
540 const bool solo = anySolo(pat);
541 for(
int k = 0; k < count; k++)
547 emit_until(tk, tick_start, samplesratio, q.position);
553 for(
int first = 1; first >= 0; first--)
554 for(
int i = 0; i < lane_count; i++)
555 if(isControlLane(pat.lanes[i]) ==
bool(first)
556 && laneDivision(pat, pat.lanes[i]) == q.division)
558 pat, i, q.position, 4. / q.division,
false,
true, solo,
559 tick_start + q.offset);
572 in_flight_channel = channel;
574 for(
int first = 1; first >= 0; first--)
575 for(
int i = 0; i < lane_count; i++)
577 if(isControlLane(pat.lanes[i]) !=
bool(first))
579 if(timed && laneDivision(pat, pat.lanes[i]) != pat.division)
582 pat, i, q.position, 4. / pat.division, rewinding, timed, solo,
583 tick_start + q.offset);
599 double from,
double to,
double bar_line,
double bar,
int division)
noexcept
601 if(!(bar > 0.) || division <= 0 || !(to > from))
603 const double unit = 4. / division;
604 const auto per_bar = int64_t(std::ceil(bar / unit - 1e-9));
605 const auto before = [&](
double x) {
606 const double rel = x - bar_line;
607 const double bars = std::floor(rel / bar + 1e-12);
608 const double within = std::max(0., rel - bars * bar);
609 return int64_t(bars) * per_bar
610 + std::min(per_bar, int64_t(std::ceil(within / unit - 1e-9)));
612 return before(to) - before(from);
621 const double at = tk.musical_start_position;
622 if(!std::isfinite(
origin) || !std::isfinite(at) || patterns.empty())
624 origin = std::numeric_limits<double>::quiet_NaN();
627 const auto& sig = tk.signature;
628 const double bar = (sig.upper > 0 && sig.lower > 0)
629 ? 4. * sig.upper / sig.lower
631 const Pattern& pat = pattern();
632 if(pat.length <= 0 || pat.division <= 0)
634 const double bar_line = tk.musical_start_last_bar;
637 current = int(steps % pat.length);
638 const int lane_count = std::min(
int(pat.lanes.size()), max_lanes);
639 for(
int i = 0; i < lane_count; i++)
647 void resync(
const ossia::token_request& tk)
noexcept
651 const Pattern& pat = pattern();
652 if(pat.length <= 0 || pat.division <= 0)
659 const auto& sig = tk.signature;
660 const double bar = (sig.upper > 0 && sig.lower > 0)
661 ? 4. * sig.upper / sig.lower
663 const int lane_count = std::min(
int(pat.lanes.size()), max_lanes);
664 for(
int i = 0; i < lane_count; i++)
669 const int div = laneDivision(pat, pat.lanes[i]);
671 ls.played = div == pat.division || !std::isfinite(
origin)
674 origin, tk.musical_start_position, tk.musical_start_last_bar,
678 for(
int i = lane_count; i < max_lanes; i++)
685 const int lane_count = std::min(
int(pattern().lanes.size()), max_lanes);
686 for(
int i = lane_count; i < max_lanes; i++)
690 emit({0., 0, event_kind::note_off, uint8_t(ls.held), 0, 0.f}, date);
698 const Pattern& pat,
int i,
double position,
double unit,
bool rewinding,
699 bool timed,
bool solo, int64_t date)
noexcept
701 const Lane& l = pat.lanes[i];
703 const int len = laneLength(pat, l);
708 ls.played = std::max<int64_t>(0, ls.played - 1);
709 const int64_t n = ls.played;
710 const int step = int(n % len);
712 ls.last_at = position;
718 play_step(pat, i, step, n / len, 0., 0., 0.,
false, solo, date);
725 const double shift = ls.shift_for == n ? ls.shift :
note_shift(l, step);
727 pat, i, step, n / len, position,
729 unit,
true, solo, date);
735 const int64_t next = n + 1;
736 const int next_step = int(next % len);
739 if(
const double t =
timing(l, next_step, ls.shift); t < 0.)
742 pat, i, next_step, next / len, position + unit,
743 position + (1. + t +
swing_delay(next_step)) * unit, unit,
true, solo, date);
753 if(r <= 0.f || (l.randomPerHit & Lane::TimingPerHit))
755 return std::uniform_real_distribution<double>{-r, r}(rng);
759 static double timing(
const Lane& l,
int step,
double shift)
noexcept
761 return std::clamp(stepParams(l, step).offset + shift, -0.5, 0.5);
764 void update_repeat_time() noexcept
785 template <
typename Gate>
787 const StepParams& p,
double unit,
bool scheduled, std::array<hit, max_ratchet>& out,
788 Gate&& gate_of)
const noexcept
790 const auto gate = [&](
int k) {
return std::clamp(gate_of(k), 0.05f, 1.f); };
791 if(!scheduled || unit <= 0.)
793 out[0] = {0., scheduled ? gate(0) : 1.};
797 double gap = 1. / (std::max<int>(1, p.ratchet) *
ratchet_scale);
800 const int n = std::clamp(
int(std::ceil(1. / gap - 1e-6)), 1,
max_ratchet);
802 const double pace = std::clamp(p.pace +
pace_offset, -1.f, 1.f);
803 const double exponent = std::exp2(-2. * pace);
804 const auto bend = [&](
double x) {
return std::pow(std::min(x, 1.), exponent); };
805 for(
int k = 0; k < n; k++)
807 const double on = bend(k * gap);
808 const double next = k + 1 < n ? bend((k + 1) * gap) : 1.;
809 out[k] = {on, on + gate(k) * (next - on)};
817 return (step % 2 == 1) ? swing * 0.5 : 0.;
820 bool condition_holds(
const StepParams& p, int64_t pass)
const noexcept
824 case Condition::Always:
826 case Condition::Fill:
828 case Condition::NotFill:
830 case Condition::First:
832 case Condition::NotFirst:
834 case Condition::Cycle:
835 return p.cycleB > 0 && (pass % p.cycleB) == (p.cycleA - 1);
845 for(
const auto& d : ls.decisions)
849 const Lane& l = pat.lanes[i];
850 const int len = laneLength(pat, l);
851 if(len <= 0 || n < 0)
853 const int step = int(n % len);
857 if(audibleNote(pat, l, step,
false) != Note::Rest && condition_holds(p, n / len))
859 const float chance = p.
chance * density;
860 if(chance >= 1.f || std::uniform_real_distribution<float>{0.f, 1.f}(rng) < chance)
862 if(l.
note == accentLane)
866 ? std::uniform_real_distribution<float>{
869 v = std::clamp(p.
velocity + spread, 0.f, 1.f) * std::clamp(l.
velocity, 0.f, 1.f);
873 v = std::clamp(p.
gate, 0.05f, 1.f);
877 auto& slot = ls.decisions[0].n < ls.decisions[1].n ? ls.decisions[0] : ls.decisions[1];
892 for(
int k = 0; k < control_lane_count; k++)
895 const Lane& l = pat.lanes[i];
896 const auto& ls = lanes[i];
900 if(scheduled && ls.last >= 0)
902 const double unit = 4. / laneDivision(pat, l);
903 n += int64_t(std::floor((grid - ls.last_at) / unit + 1e-6));
908 if(l.
note == accentLane)
909 c.accent = std::max(c.accent, v);
920 const Pattern& pat,
int i,
int step, int64_t pass,
double grid,
double at,
921 double unit,
bool scheduled,
bool solo, int64_t date)
noexcept
923 const Lane& l = pat.lanes[i];
927 const auto push = [&](
double position,
event_kind k,
int note,
int velocity,
930 {position, 0, k, uint8_t(note), uint8_t(velocity), value}, scheduled, date);
935 const auto kind = l.
note == accentLane ? event_kind::accent : event_kind::slide;
936 const float v =
control_value(pat, i, pass * laneLength(pat, l) + step);
937 push(at, kind, 0, 0, v);
939 if(kind == event_kind::accent && v > 0.f && scheduled && p.
gate < 1.f)
940 push(at + std::max(p.
gate, 0.05f) * unit, kind, 0, 0, 0.f);
946 Note kind = audibleNote(pat, l, step, solo);
947 if(kind != Note::Rest)
949 if(!condition_holds(p, pass))
951 else if(
const float chance = p.
chance * density; chance < 1.f)
952 if(std::uniform_real_distribution<float>{0.f, 1.f}(rng) >= chance)
955 const step_controls controls = control_lane_count > 0 && kind != Note::Rest
956 ? controls_at(pat, grid, scheduled)
961 const auto draw_pitch = [&] {
966 const auto draw_velocity = [&] {
968 ? std::uniform_real_distribution<float>{
972 const bool pitch_per_hit = l.randomPerHit & Lane::PitchPerHit;
973 const bool velocity_per_hit = l.randomPerHit & Lane::VelocityPerHit;
974 const int note_pitch = kind != Note::Rest && !pitch_per_hit ? draw_pitch() : 0;
975 const float note_velocity
976 = kind != Note::Rest && !velocity_per_hit ? draw_velocity() : 0.f;
977 const auto to_note = [&](
int pitch) {
978 return std::clamp(
int(l.
note) + p.
pitch + pitch, 0, 127);
981 const auto to_velocity = [&](
float spread) {
982 float v = std::clamp(p.
velocity + spread, 0.f, 1.f);
983 v += controls.accent * (1.f - v);
985 int(std::lround(v * l.
velocity * velocity_scale * 127.f)), 1, 127);
988 const auto strike = [&](
int k) {
989 return std::make_pair(
990 to_note(pitch_per_hit ? draw_pitch() : note_pitch),
991 to_velocity(velocity_per_hit ? draw_velocity() : note_velocity));
993 const int note = to_note(note_pitch);
995 const bool gate_per_hit = l.randomPerHit & Lane::GatePerHit;
996 const auto draw_gate = [&] {
997 return p.
gateRandom > 0.f ? std::uniform_real_distribution<float>{
1001 const float note_gate = kind != Note::Rest && !gate_per_hit ? draw_gate() : 0.f;
1003 = [&](int) {
return p.
gate + (gate_per_hit ? draw_gate() : note_gate); };
1007 const bool timing_per_hit
1008 = scheduled && p.
offsetRandom > 0.f && (l.randomPerHit & Lane::TimingPerHit);
1009 const auto hit_shift = [&](
const std::array<hit, max_ratchet>& h,
int k,
int n) {
1012 const double gap = (k + 1 < n ? h[k + 1].on : 1.) - h[k].on;
1014 const double d = std::uniform_real_distribution<double>{-r, r}(rng);
1015 return k == 0 ? std::max(0., d) : d;
1018 constexpr auto inf = std::numeric_limits<double>::infinity();
1021 const auto release_held = [&] {
1024 std::max(at, std::nextafter(ls.held_on, inf)), event_kind::note_off, ls.held,
1030 const bool slid = ls.slid && ls.held >= 0;
1032 const auto glide_to = [&](
double on,
int hit_note,
int hit_velocity) {
1033 if(ls.held != hit_note)
1035 push(on, event_kind::note_on, hit_note, hit_velocity);
1037 std::nextafter(std::max(on, ls.held_on), inf), event_kind::note_off, ls.held,
1050 case Note::Legato: {
1054 std::array<hit, max_ratchet> h;
1055 const int n = hits(p, unit, scheduled, h, gate_of);
1058 glide_to(at, note, strike(0).second);
1059 else if(ls.held < 0 || (ls.held != note && !pitch_per_hit))
1062 push(at, event_kind::note_on, note, strike(0).second);
1066 int sounding = ls.held;
1067 double off = at + h[0].off * unit;
1068 for(
int k = 1; k < n; k++)
1070 const double shift = hit_shift(h, k, n);
1071 const auto [hit_note, hit_velocity] = strike(k);
1072 push(off, event_kind::note_off, sounding, 0);
1073 push(at + (h[k].on + shift) * unit, event_kind::note_on, hit_note, hit_velocity);
1074 ls.held = sounding = hit_note;
1075 ls.held_on = at + (h[k].on + shift) * unit;
1076 off = at + (h[k].off + shift) * unit;
1079 if(h[n - 1].off < 1. && !controls.slide)
1081 push(off, event_kind::note_off, sounding, 0);
1091 std::array<hit, max_ratchet> h;
1092 const int n = hits(p, unit, scheduled, h, gate_of);
1093 for(
int k = 0; k < n; k++)
1095 const double shift = hit_shift(h, k, n);
1096 const auto [hit_note, hit_velocity] = strike(k);
1097 const double on = at + (h[k].on + shift) * unit;
1099 glide_to(on, hit_note, hit_velocity);
1101 push(on, event_kind::note_on, hit_note, hit_velocity);
1104 if(k + 1 == n && (h[k].off >= 1. || controls.slide))
1106 if(!(k == 0 && slid && ls.held_on < on))
1112 push(at + (h[k].off + shift) * unit, event_kind::note_off, hit_note, 0);
1120 ls.slid = controls.slide && ls.held >= 0;
1126 void push_event(
event e,
bool scheduled, int64_t date)
noexcept
1128 e.order = next_order++;
1131 if(immediate_size <
int(
immediate.size()))
1136 if(!std::isfinite(e.position))
1141 queue[queue_size++] = e;
1150 if(a.kind != b.kind)
1151 return a.kind < b.kind;
1152 return a.order < b.order;
1154 for(
int i = 0; i < immediate_size; i++)
1163 const ossia::token_request& tk, int64_t tick_start,
double samplesratio,
1164 double end)
noexcept
1166 const auto due_end = std::partition(
1167 queue.begin(), queue.begin() + queue_size,
1168 [end](
const event& e) { return e.position < end - 1e-9; });
1169 std::sort(queue.begin(), due_end, [](
const event& a,
const event& b) {
1170 if(a.position != b.position)
1171 return a.position < b.position;
1172 if(a.kind != b.kind)
1173 return a.kind < b.kind;
1174 return a.order < b.order;
1179 for(
auto it = queue.begin(); it != due_end; ++it)
1182 + tk.physical_position(
1183 std::max(it->position, tk.musical_start_position), samplesratio));
1185 const int remaining = int((queue.begin() + queue_size) - due_end);
1186 std::move(due_end, queue.begin() + queue_size, queue.begin());
1187 queue_size = remaining;
1190 void emit(
const event& e, int64_t date)
noexcept
1192 auto& mess = out.target<ossia::midi_port>()->messages;
1195 case event_kind::note_off:
1198 mess.push_back(libremidi::from_midi1::note_off(in_flight_channel, e.note, 0));
1199 mess.back().timestamp = date;
1202 case event_kind::note_on:
1208 mess.push_back(libremidi::from_midi1::note_off(in_flight_channel, e.note, 0));
1209 mess.back().timestamp = date;
1211 mess.push_back(libremidi::from_midi1::note_on(channel, e.note, e.velocity));
1212 mess.back().timestamp = date;
1215 in_flight_channel = channel;
1217 case event_kind::accent:
1218 accent_out->write_value(e.value, date);
1220 case event_kind::slide:
1221 slide_out->write_value(e.value, date);
1226 void apply_switch(int64_t date)
noexcept
1231 in_flight_channel = channel;
1241 void all_notes_off() noexcept
override { mustStop =
true; }