2 #include <Engine/Node/SimpleApi.hpp>
15 static const constexpr
auto prettyName =
"Midi quantify";
16 static const constexpr
auto objectKey =
"Quantifier";
17 static const constexpr
auto category =
"Midi";
18 static const constexpr
auto author =
"ossia score";
19 static const constexpr
auto kind = Process::ProcessCategory::MidiEffect;
20 static const constexpr
auto description =
"Quantifies a MIDI input";
21 static const constexpr
auto tags = std::array<const char*, 0>{};
22 static const uuid_constexpr
auto uuid
23 = make_uuid(
"b8e2e5ad-17e4-43de-8d79-660a29d5c4f4");
25 static const constexpr midi_in midi_ins[]{
"in"};
26 static const constexpr midi_out midi_outs[]{
"out"};
27 static const constexpr
auto controls = tuplet::make_tuple(
28 Control::Widgets::QuantificationChooser(),
30 Control::Widgets::DurationChooser(), Control::Widgets::TempoChooser());
36 ossia::time_value date{};
40 std::vector<NoteIn> to_start;
41 std::vector<NoteIn> running_notes;
44 using control_policy = ossia::safe_nodes::default_tick_controls;
47 run(
const ossia::midi_port& p1,
const ossia::timed_vec<float>& startq,
48 const ossia::timed_vec<float>& tightness,
const ossia::timed_vec<float>& dur,
49 const ossia::timed_vec<float>& tempo_vec, ossia::midi_port& p2,
50 ossia::token_request tk, ossia::exec_state_facade st,
State&
self)
52 auto start = startq.rbegin()->second;
53 double precision = tightness.rbegin()->second;
54 auto duration = dur.rbegin()->second;
55 auto tempo = tempo_vec.rbegin()->second;
58 const auto whole_dur = 240.f / tempo;
59 const auto whole_samples = whole_dur * st.sampleRate();
61 for(
const libremidi::message& in : p1.messages)
63 if(!in.is_note_on_or_off())
65 p2.messages.push_back(in);
69 Note note{in[1], in[2], (uint8_t)in.get_channel()};
71 if(in.get_message_type() == libremidi::message_type::NOTE_ON && note.vel != 0)
75 auto no = libremidi::channel_events::note_on(note.chan, note.pitch, note.vel);
76 no.timestamp = in.timestamp;
78 p2.messages.push_back(no);
82 = tk.date + (int64_t)no.timestamp + (int64_t)(whole_samples * duration);
83 self.running_notes.push_back({note, end});
85 else if(duration == 0.f)
89 = libremidi::channel_events::note_off(note.chan, note.pitch, note.vel);
90 noff.timestamp = no.timestamp;
91 p2.messages.push_back(noff);
98 const auto start_q = whole_samples * start;
99 auto perf_date = int64_t(
100 start_q * int64_t(1 + tk.date.impl * st.modelToSamples() / start_q));
101 int64_t actual_date = (1. - precision) * tk.date.impl * st.modelToSamples()
102 + precision * perf_date;
103 ossia::time_value next_date{actual_date};
104 self.to_start.push_back({note, next_date});
110 auto noff = libremidi::channel_events::note_off(note.chan, note.pitch, note.vel);
111 noff.timestamp = in.timestamp;
112 p2.messages.push_back(noff);
118 for(
auto it =
self.to_start.begin(); it !=
self.to_start.end();)
121 if(note.date > tk.prev_date && note.date.impl < tk.date.impl)
123 auto no = libremidi::channel_events::note_on(
124 note.note.chan, note.note.pitch, note.note.vel);
125 no.timestamp = tk.to_physical_time_in_tick(note.date, st.modelToSamples());
126 p2.messages.push_back(no);
130 auto end = note.date + (int64_t)(whole_samples * duration);
131 self.running_notes.push_back({note.note, end});
133 else if(duration == 0.f)
136 auto noff = libremidi::channel_events::note_off(
137 note.note.chan, note.note.pitch, note.note.vel);
138 noff.timestamp = no.timestamp;
139 p2.messages.push_back(noff);
142 it =
self.to_start.erase(it);
150 for(
auto it =
self.running_notes.begin(); it !=
self.running_notes.end();)
153 if(note.date > tk.prev_date && note.date.impl < tk.date.impl)
155 auto noff = libremidi::channel_events::note_off(
156 note.note.chan, note.note.pitch, note.note.vel);
157 noff.timestamp = tk.to_physical_time_in_tick(note.date, st.modelToSamples());
158 p2.messages.push_back(noff);
159 it =
self.running_notes.erase(it);
Utilities for OSSIA data structures.
Definition: DeviceInterface.hpp:33
Definition: score-lib-process/Control/Widgets.hpp:77
Definition: SimpleApi.hpp:81
Definition: Quantifier.hpp:34
Definition: Quantifier.hpp:12