@@ -599,6 +599,9 @@ void qtractorMidiToolsForm::loadPreset ( const QString& sPreset )
599
599
m_ui.ResizeValue2ComboBox ->setCurrentIndex (vlist[5 ].toInt ());
600
600
m_ui.ResizeValue2SpinBox ->setValue (vlist[6 ].toInt ());
601
601
}
602
+ // Resize legato mode tool...
603
+ if (vlist.count () > 7 )
604
+ m_ui.ResizeLegatoCheckBox ->setChecked (vlist[7 ].toBool ());
602
605
// Rescale tool...
603
606
vlist = settings.value (" /Rescale" ).toList ();
604
607
if (vlist.count () > 6 ) {
@@ -702,6 +705,7 @@ void qtractorMidiToolsForm::savePreset ( const QString& sPreset )
702
705
vlist.append ((unsigned int ) m_ui.ResizeDurationSpinBox ->value ());
703
706
vlist.append (m_ui.ResizeValue2ComboBox ->currentIndex ());
704
707
vlist.append (m_ui.ResizeValue2SpinBox ->value ());
708
+ vlist.append (m_ui.ResizeLegatoCheckBox ->isChecked ());
705
709
settings.setValue (" /Resize" , vlist);
706
710
// Rescale tool...
707
711
vlist.clear ();
@@ -863,9 +867,21 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
863
867
tools.append (tr (" temporamp" ));
864
868
pMidiEditCommand->setName (tools.join (" , " ));
865
869
866
- const qtractorMidiEditSelect::ItemList& items = pSelect->items ();
867
- qtractorMidiEditSelect::ItemList::ConstIterator iter = items.constBegin ();
868
- const qtractorMidiEditSelect::ItemList::ConstIterator& iter_end = items.constEnd ();
870
+ QList<qtractorMidiEvent *> items = pSelect->items ().keys ();
871
+
872
+ if (m_ui.ResizeCheckBox ->isChecked ()
873
+ && m_ui.ResizeDurationCheckBox ->isChecked ()
874
+ && m_ui.ResizeLegatoCheckBox ->isChecked ()) {
875
+ // Sort events in reverse event time...
876
+ struct ReverseEventTime {
877
+ bool operator () (qtractorMidiEvent *ev1, qtractorMidiEvent *ev2) const
878
+ { return (ev1->time () > ev2->time ()); }
879
+ };
880
+ std::sort (items.begin (), items.end (), ReverseEventTime ());
881
+ }
882
+
883
+ QList<qtractorMidiEvent *>::ConstIterator iter = items.constBegin ();
884
+ const QList<qtractorMidiEvent *>::ConstIterator& iter_end = items.constEnd ();
869
885
870
886
// Seed time range with a value from the list of selected events.
871
887
long iMinTime = iTimeOffset;
@@ -894,7 +910,7 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
894
910
m_ui.ResizeValue2ComboBox ->currentIndex () > 0 )) {
895
911
// Make it through one time...
896
912
for (int i = 0 ; iter != iter_end; ++i, ++iter) {
897
- qtractorMidiEvent *pEvent = iter. key () ;
913
+ qtractorMidiEvent *pEvent = * iter;
898
914
const long iTime = pEvent->time () + iTimeOffset;
899
915
const long iTime2 = iTime + pEvent->duration ();
900
916
if (iMinTime > iTime)
@@ -921,8 +937,11 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
921
937
// Go for the main pass...
922
938
qtractorTimeScale::Cursor cursor (m_pTimeScale);
923
939
940
+ // Resize duration: legato/gap filler helper...
941
+ QHash<unsigned char , qtractorMidiEvent *> notes;
942
+
924
943
for ( ; iter != iter_end; ++iter) {
925
- qtractorMidiEvent *pEvent = iter. key () ;
944
+ qtractorMidiEvent *pEvent = * iter;
926
945
int iNote = int (pEvent->note ());
927
946
long iTime = pEvent->time () + iTimeOffset;
928
947
long iDuration = long (pEvent->duration ());
@@ -1114,16 +1133,26 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
1114
1133
}
1115
1134
// Resize tool...
1116
1135
if (m_ui.ResizeCheckBox ->isChecked ()) {
1117
- if (m_ui.ResizeDurationCheckBox ->isChecked ()) {
1118
- const float T0 // @ iFrame == 0
1119
- = m_pTimeScale->nodes ().first ()->tempo ;
1120
- const float T1
1121
- = pNode->tempo ;
1122
- const unsigned long iFrames
1123
- = qtractorTimeScale::uroundf (
1124
- T0 * float (m_ui.ResizeDurationSpinBox ->value ()) / T1);
1125
- iDuration = pNode->tickFromFrame (
1126
- pNode->frameFromTick (iTime) + iFrames) - iTime;
1136
+ if (m_ui.ResizeDurationCheckBox ->isChecked ()
1137
+ && pEvent->type () == qtractorMidiEvent::NOTEON) {
1138
+ qtractorMidiEvent *pLastEvent = nullptr ;
1139
+ if (m_ui.ResizeLegatoCheckBox ->isChecked ()) {
1140
+ pLastEvent = notes.value (pEvent->note (), nullptr );
1141
+ notes.insert (pEvent->note (), pEvent);
1142
+ }
1143
+ if (pLastEvent) {
1144
+ iDuration = pLastEvent->time () - pEvent->time ();
1145
+ } else {
1146
+ const float T0 // @ iFrame == 0
1147
+ = m_pTimeScale->nodes ().first ()->tempo ;
1148
+ const float T1
1149
+ = pNode->tempo ;
1150
+ const unsigned long iFrames
1151
+ = qtractorTimeScale::uroundf (
1152
+ T0 * float (m_ui.ResizeDurationSpinBox ->value ()) / T1);
1153
+ iDuration = pNode->tickFromFrame (
1154
+ pNode->frameFromTick (iTime) + iFrames) - iTime;
1155
+ }
1127
1156
}
1128
1157
if (m_ui.ResizeValueCheckBox ->isChecked ()) {
1129
1158
const int p = (bPitchBend && iValue < 0 ? -1 : 1 ); // sign
@@ -1433,6 +1462,7 @@ void qtractorMidiToolsForm::stabilizeForm (void)
1433
1462
++iEnabled;
1434
1463
m_ui.ResizeDurationSpinBox ->setEnabled (bEnabled2);
1435
1464
m_ui.ResizeFormatComboBox ->setEnabled (bEnabled2);
1465
+ m_ui.ResizeLegatoCheckBox ->setEnabled (bEnabled2);
1436
1466
1437
1467
m_ui.ResizeValueCheckBox ->setEnabled (bEnabled);
1438
1468
bEnabled2 = bEnabled && m_ui.ResizeValueCheckBox ->isChecked ();
0 commit comments