Add MIDI note strumming feature

This commit is contained in:
chousemp3 2025-09-12 19:02:07 +02:00 committed by Robin Gareus
parent 0581f29f5f
commit a9e7ce15db
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
3 changed files with 69 additions and 0 deletions

View file

@ -632,6 +632,9 @@ EditingContext::register_midi_actions (Bindings* midi_bindings, std::string cons
ActionManager::register_action (_midi_actions, X_("split-notes-less"), _("Split Selected Notes into less pieces"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::split_notes_less));
ActionManager::register_action (_midi_actions, X_("join-notes"), _("Join Selected Notes"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::join_notes));
ActionManager::register_action (_midi_actions, X_("strum-forward"), _("Strum notes forward"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::strum_notes_forward));
ActionManager::register_action (_midi_actions, X_("strum-backward"), _("Strum notes backward"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::strum_notes_backward));
ActionManager::register_action (_midi_actions, X_("edit-channels"), _("Edit Note Channels"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::channel_edit));
ActionManager::register_action (_midi_actions, X_("edit-velocities"), _("Edit Note Velocities"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::velocity_edit));
@ -1940,6 +1943,9 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve
items.back().set_sensitive (false);
}
items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs)));
items.push_back (SeparatorElem());
items.push_back(MenuElem(_("Strum forward"), sigc::mem_fun(mrv, &MidiView::strum_notes_forward)));
items.push_back(MenuElem(_("Strum backward"), sigc::mem_fun(mrv, &MidiView::strum_notes_backward)));
_note_context_menu.popup (event->button.button, event->button.time);
}

View file

@ -5367,3 +5367,62 @@ MidiView::set_visible_channel (int chn, bool clear_selection)
}
}
void
MidiView::strum_notes (bool forward, bool fine)
{
if (_selection.empty()) {
return;
}
start_note_diff_command (_("Strum"));
Notes notes;
selection_as_notelist (notes, false);
if (notes.size() < 2) {
abort_note_diff();
return;
}
Temporal::Beats total_offset;
Temporal::Beats offset;
if (fine) {
offset = Temporal::Beats::ticks (Temporal::ticks_per_beat / 128);
} else {
offset = Temporal::Beats::ticks (Temporal::ticks_per_beat / 32);
}
if (forward) {
for (auto const & n : notes) {
NoteBase* cne = find_canvas_note (n);
if (cne) {
change_note_time (cne, total_offset, true);
total_offset += offset;
}
}
} else { // backward
for (auto it = notes.rbegin(); it != notes.rend(); ++it) {
NoteBase* cne = find_canvas_note (*it);
if (cne) {
change_note_time (cne, total_offset, true);
total_offset += offset;
}
}
}
apply_note_diff ();
}
void
MidiView::strum_notes_forward ()
{
strum_notes (true, false);
}
void
MidiView::strum_notes_backward ()
{
strum_notes (false, false);
}

View file

@ -431,7 +431,11 @@ class MidiView : public virtual sigc::trackable, public LineMerger
void quantize_selected_notes ();
void strum_notes_forward ();
void strum_notes_backward ();
protected:
void strum_notes (bool forward, bool end);
friend class MidiRubberbandSelectDrag;
friend class MidiVerticalSelectDrag;
friend class NoteDrag;