Skip to content

Commit 93eeb72

Browse files
committed
- New MIDI Tool Resize Duration / Legato option added. (EXPERIMENTAL)
1 parent ba40b1f commit 93eeb72

12 files changed

+505
-411
lines changed

ChangeLog

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ Qtractor - An Audio/MIDI multi-track sequencer
44
ChangeLog
55

66

7+
GIT HEAD
8+
9+
- New MIDI Tool Resize Duration / Legato option added. (EXPERIMENTAL)
10+
11+
- MIDI Clip Editor (aka. piano-roll) thumb-view now taking tempo-map
12+
changes into account.
13+
14+
- Audio metronome is enabled only when both the bar and beat sample
15+
files are provided.
16+
17+
718
0.9.36 2023-11-10 An Autumn'23 Release.
819

920
- Multiple audio and/or MIDI files may now appear as arguments on

src/qtractorMidiToolsForm.cpp

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,9 @@ void qtractorMidiToolsForm::loadPreset ( const QString& sPreset )
599599
m_ui.ResizeValue2ComboBox->setCurrentIndex(vlist[5].toInt());
600600
m_ui.ResizeValue2SpinBox->setValue(vlist[6].toInt());
601601
}
602+
// Resize legato mode tool...
603+
if (vlist.count() > 7)
604+
m_ui.ResizeLegatoCheckBox->setChecked(vlist[7].toBool());
602605
// Rescale tool...
603606
vlist = settings.value("/Rescale").toList();
604607
if (vlist.count() > 6) {
@@ -702,6 +705,7 @@ void qtractorMidiToolsForm::savePreset ( const QString& sPreset )
702705
vlist.append((unsigned int) m_ui.ResizeDurationSpinBox->value());
703706
vlist.append(m_ui.ResizeValue2ComboBox->currentIndex());
704707
vlist.append(m_ui.ResizeValue2SpinBox->value());
708+
vlist.append(m_ui.ResizeLegatoCheckBox->isChecked());
705709
settings.setValue("/Resize", vlist);
706710
// Rescale tool...
707711
vlist.clear();
@@ -863,9 +867,21 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
863867
tools.append(tr("temporamp"));
864868
pMidiEditCommand->setName(tools.join(", "));
865869

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();
869885

870886
// Seed time range with a value from the list of selected events.
871887
long iMinTime = iTimeOffset;
@@ -894,7 +910,7 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
894910
m_ui.ResizeValue2ComboBox->currentIndex() > 0)) {
895911
// Make it through one time...
896912
for (int i = 0 ; iter != iter_end; ++i, ++iter) {
897-
qtractorMidiEvent *pEvent = iter.key();
913+
qtractorMidiEvent *pEvent = *iter;
898914
const long iTime = pEvent->time() + iTimeOffset;
899915
const long iTime2 = iTime + pEvent->duration();
900916
if (iMinTime > iTime)
@@ -921,8 +937,11 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
921937
// Go for the main pass...
922938
qtractorTimeScale::Cursor cursor(m_pTimeScale);
923939

940+
// Resize duration: legato/gap filler helper...
941+
QHash<unsigned char, qtractorMidiEvent *> notes;
942+
924943
for ( ; iter != iter_end; ++iter) {
925-
qtractorMidiEvent *pEvent = iter.key();
944+
qtractorMidiEvent *pEvent = *iter;
926945
int iNote = int(pEvent->note());
927946
long iTime = pEvent->time() + iTimeOffset;
928947
long iDuration = long(pEvent->duration());
@@ -1114,16 +1133,26 @@ qtractorMidiEditCommand *qtractorMidiToolsForm::midiEditCommand (
11141133
}
11151134
// Resize tool...
11161135
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+
}
11271156
}
11281157
if (m_ui.ResizeValueCheckBox->isChecked()) {
11291158
const int p = (bPitchBend && iValue < 0 ? -1 : 1); // sign
@@ -1433,6 +1462,7 @@ void qtractorMidiToolsForm::stabilizeForm (void)
14331462
++iEnabled;
14341463
m_ui.ResizeDurationSpinBox->setEnabled(bEnabled2);
14351464
m_ui.ResizeFormatComboBox->setEnabled(bEnabled2);
1465+
m_ui.ResizeLegatoCheckBox->setEnabled(bEnabled2);
14361466

14371467
m_ui.ResizeValueCheckBox->setEnabled(bEnabled);
14381468
bEnabled2 = bEnabled && m_ui.ResizeValueCheckBox->isChecked();

src/qtractorMidiToolsForm.ui

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,13 @@
10271027
</spacer>
10281028
</item>
10291029
<item row="3" column="1" colspan="5">
1030+
<widget class="QCheckBox" name="ResizeLegatoCheckBox">
1031+
<property name="text">
1032+
<string>&amp;Legato</string>
1033+
</property>
1034+
</widget>
1035+
</item>
1036+
<item row="4" column="1" colspan="5">
10301037
<spacer>
10311038
<property name="orientation">
10321039
<enum>Qt::Vertical</enum>
@@ -1590,6 +1597,7 @@ Edit head/tail (blue) markers define the shift range.</string>
15901597
<tabstop>ResizeValueSpinBox</tabstop>
15911598
<tabstop>ResizeValue2ComboBox</tabstop>
15921599
<tabstop>ResizeValue2SpinBox</tabstop>
1600+
<tabstop>ResizeLegatoCheckBox</tabstop>
15931601
<tabstop>RescaleCheckBox</tabstop>
15941602
<tabstop>RescaleTimeCheckBox</tabstop>
15951603
<tabstop>RescaleTimeSpinBox</tabstop>

0 commit comments

Comments
 (0)