62 using byte =
unsigned char;
63 using chord = ossia::small_vector<std::pair<byte, byte>, 5>;
65 ossia::flat_map<byte, byte> notes;
66 ossia::small_vector<chord, 10> arpeggio;
67 std::array<int8_t, 128> in_flight{};
69 int previous_octave{};
70 int previous_octave_mode{};
71 int previous_repeat{};
72 int previous_arpeggio{};
75 std::random_device d{};
86 arpeggio.reserve(1024);
92 switch(previous_arpeggio)
99 std::reverse(arpeggio.begin(), arpeggio.end());
103 duplicate_vector(arpeggio);
104 std::reverse(arpeggio.begin() + notes.size(), arpeggio.end());
108 duplicate_vector(arpeggio);
109 std::reverse(arpeggio.begin(), arpeggio.begin() + notes.size());
115 for(std::pair note : notes)
117 arpeggio[0].push_back(note);
119 for(
int i = 1; i < previous_octave; i++)
122 if(previous_octave_mode != 2)
124 int up = note.first + 12 * i;
126 arpeggio[0].push_back({
static_cast<byte>(up), note.second});
128 if(previous_octave_mode != 1)
130 int down = note.first - 12 * i;
132 arpeggio[0].push_back({
static_cast<byte>(down), note.second});
144 if(previous_repeat > 1)
146 const std::size_t n = arpeggio.size();
147 const std::size_t rep = previous_repeat;
148 arpeggio.resize(n * rep);
149 for(std::size_t i = n; i-- > 0;)
150 for(std::size_t r = rep; r-- > 0;)
151 arpeggio[i * rep + r] = arpeggio[i];
154 const std::size_t orig_size = arpeggio.size();
158 if(previous_octave_mode != 2)
160 for(
int i = 1; i < previous_octave; i++)
161 octavize(orig_size, i);
163 if(previous_octave_mode != 1)
165 for(
int i = 1; i < previous_octave; i++)
166 octavize(orig_size, -i);
170 void arpeggiate(
int size_mult)
173 arpeggio.reserve(notes.size() * size_mult);
174 for(std::pair note : notes)
176 arpeggio.push_back(chord{note});
180 void octavize(std::size_t orig_size,
int i)
182 for(std::size_t j = 0; j < orig_size; j++)
184 auto copy = arpeggio[j];
185 for(
auto it = copy.begin(); it != copy.end();)
188 int res = note.first + 12 * i;
189 if(res >= 0 && res <= 127)
200 arpeggio.push_back(std::move(copy));
204 template <
typename Out>
205 void all_off(Out& out,
int date)
207 for(
int k = 0; k < 128; k++)
209 while(in_flight[k] > 0)
211 out.note_off(1, k, 0).timestamp = date;
218 template <
typename In,
typename Out>
220 const In& msgs, Out& out,
int octave,
int octave_mode,
int repeat,
221 int arpeggio_mode,
const halp::tick_musical& tk,
double rate)
224 for(
auto& note : msgs)
226 const auto type = note.get_message_type();
227 if(type == libremidi::message_type::NOTE_ON && note.bytes[2] != 0)
228 notes.insert({note.bytes[1], note.bytes[2]});
230 type == libremidi::message_type::NOTE_OFF
231 || type == libremidi::message_type::NOTE_ON)
232 notes.erase(note.bytes[1]);
236 const bool mustUpdateArpeggio = msgs.size() > 0 || octave != previous_octave
237 || octave_mode != previous_octave_mode
238 || repeat != previous_repeat
239 || arpeggio_mode != previous_arpeggio;
240 previous_octave = octave;
241 previous_octave_mode = octave_mode;
242 previous_repeat = repeat;
243 previous_arpeggio = arpeggio_mode;
245 if(mustUpdateArpeggio)
254 if(index >= arpeggio.size())
258 for(
auto [date, q] : tk.get_quantification_date_with_bars(rate))
260 if(date >= tk.frames)
267 std::size_t play_index;
268 if(arpeggio_mode == 5)
270 std::uniform_int_distribution<std::size_t> dist(0, arpeggio.size() - 1);
271 play_index = dist(rng);
276 index = (index + 1) % arpeggio.size();
280 for(
auto& note : arpeggio[play_index])
282 in_flight[note.first]++;
283 out.note_on(1, note.first, note.second).timestamp = date;
291 halp_meta(name,
"Arpeggiator (old)")
292 halp_meta(c_name,
"Arpeggiator")
293 halp_meta(category,
"Midi")
294 halp_meta(author,
"ossia score")
297 "https://ossia.io/score-docs/processes/midi-utilities.html#arpeggiator")
298 halp_meta(description,
"Arpeggiator")
299 halp_flag(deprecated);
300 halp_meta(uuid,
"0b98c7cd-f831-468f-81e3-706d6a97d705")
305 halp::midi_bus<
"in", libremidi::message> midi;
307 halp::hslider_i32<
"Octave", halp::irange{1, 7, 1}> octave;
309 halp::hslider_i32<
"Repeat", halp::irange{1, 8, 1}> repeat;
310 halp::hslider_i32<
"Quantification", halp::irange{1, 32, 8}> quantification;
314 halp::midi_out_bus<
"out", libremidi::message> midi;
319 using tick = halp::tick_musical;
320 void operator()(
const halp::tick_musical& tk)
323 inputs.midi, outputs.midi, inputs.octave, inputs.octave_mode.value,
324 inputs.repeat, inputs.arpeggios.value, tk, inputs.quantification.value);
void process(const In &msgs, Out &out, int octave, int octave_mode, int repeat, int arpeggio_mode, const halp::tick_musical &tk, double rate)
rate is the grid's: 1 a whole note, 4 a quarter...
Definition Arpeggiator.hpp:219