mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 16:24:57 +01:00
make note joining code a bit cleaner and preserve note velocities
This commit is contained in:
parent
d6beba67dc
commit
253dcb312b
1 changed files with 35 additions and 18 deletions
|
|
@ -4894,17 +4894,26 @@ MidiRegionView::join_notes ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct NoteExtentInfo
|
||||||
|
{
|
||||||
|
Temporal::Beats start;
|
||||||
|
Temporal::Beats end;
|
||||||
|
float velocity;
|
||||||
|
float off_velocity;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
NoteExtentInfo()
|
||||||
|
: start (std::numeric_limits<Temporal::Beats>::max())
|
||||||
|
, end (Temporal::Beats())
|
||||||
|
, velocity (0.f)
|
||||||
|
, off_velocity (0.f)
|
||||||
|
, cnt (0) {}
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::join_notes_on_channel (int chn)
|
MidiRegionView::join_notes_on_channel (int chn)
|
||||||
{
|
{
|
||||||
typedef std::pair<Temporal::Beats,Temporal::Beats> StartAndEnd;
|
NoteExtentInfo ninfo[127];
|
||||||
StartAndEnd starts_and_ends[127];
|
|
||||||
uint32_t cnt[127];
|
|
||||||
|
|
||||||
for (size_t n = 0; n < 127; ++n) {
|
|
||||||
starts_and_ends[n].first = std::numeric_limits<Temporal::Beats>::max();
|
|
||||||
cnt[n] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto & s : _selection) {
|
for (auto & s : _selection) {
|
||||||
|
|
||||||
|
|
@ -4913,30 +4922,38 @@ MidiRegionView::join_notes_on_channel (int chn)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<NoteType> base (s->note());
|
std::shared_ptr<NoteType> base (s->note());
|
||||||
StartAndEnd& se (starts_and_ends[base->note()]);
|
NoteExtentInfo& ni (ninfo[base->note()]);
|
||||||
cnt[base->note()]++;
|
ni.cnt++;
|
||||||
|
|
||||||
if (base->time() < se.first) {
|
if (base->time() < ni.start) {
|
||||||
se.first = base->time();
|
ni.start = base->time();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base->end_time() > se.second) {
|
if (base->end_time() > ni.end) {
|
||||||
se.second = base->end_time();
|
ni.end = base->end_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ni.velocity += base->velocity();
|
||||||
|
ni.off_velocity += base->off_velocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
start_note_diff_command (_("join notes"));
|
start_note_diff_command (_("join notes"));
|
||||||
for (auto & s : _selection) {
|
for (auto & s : _selection) {
|
||||||
/* Only remove pitches that occur more than once */
|
/* Only remove pitches that occur more than once */
|
||||||
if (cnt[s->note()->note()] > 1 && s->note()->channel() == chn) {
|
if (ninfo[s->note()->note()].cnt > 1 && s->note()->channel() == chn) {
|
||||||
note_diff_remove_note (s);
|
note_diff_remove_note (s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t n = 0; n < 127; ++n) {
|
for (size_t n = 0; n < 127; ++n) {
|
||||||
if (cnt[n] > 1 && starts_and_ends[n].second != Temporal::Beats()) {
|
|
||||||
Temporal::Beats b = starts_and_ends[n].second - starts_and_ends[n].first;
|
NoteExtentInfo& ni (ninfo[n]);
|
||||||
std::shared_ptr<NoteType> new_note (new NoteType (chn, starts_and_ends[n].first, b, n, 64));
|
|
||||||
|
if (ni.cnt > 1 && ni.end != Temporal::Beats()) {
|
||||||
|
|
||||||
|
Temporal::Beats b = ni.end - ni.start;
|
||||||
|
std::shared_ptr<NoteType> new_note (new NoteType (chn, ni.start, b, n, ni.velocity / ni.cnt));
|
||||||
|
new_note->set_off_velocity (ni.off_velocity / ni.cnt);
|
||||||
note_diff_add_note (new_note, true, true);
|
note_diff_add_note (new_note, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue