From 1f5f28fd8ab21d1de6a04918c4eede08a70cc62a Mon Sep 17 00:00:00 2001 From: Levin Oehlmann Date: Tue, 9 Apr 2024 01:17:26 +0200 Subject: [PATCH] Don't auto-quantize notes when recording MIDI input (#6714) * Don't auto-quantize notes when recording MIDI input. * Add midi:autoquantize to config file and a widget to set it in the MIDI settings. * Quantize notes during recording if midi:autoquantize is enabled. * Apply suggestions from code review: Formatting Style formatting Co-authored-by: saker * Cache the auto quantization setting in a PianoRoll member variable, and update it on ConfigManager::valueChanged() * Apply suggestions from code review: Formatting & temp variable One formatting change, and reusing an existing variable instead of introducting a new local one. Co-authored-by: saker Co-authored-by: IanCaio * Update src/gui/modals/SetupDialog.cpp Good catch. Co-authored-by: IanCaio * Fix logic bug in PianoRoll's midi/autoquantize value observer. * Use '!' instead of 'not' to please MSVC. * autoquantize: Add an explicit check for consistency with the rest of the PR, and give the setting a default value in SetupDialog constructor. * Integrate MIDI auto-quantize checkbox into the resizable layout, and add a tool tip. --------- Co-authored-by: saker Co-authored-by: IanCaio --- include/PianoRoll.h | 1 + include/SetupDialog.h | 2 ++ src/gui/editors/PianoRoll.cpp | 19 +++++++++++++++++-- src/gui/modals/SetupDialog.cpp | 23 +++++++++++++++++++++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/include/PianoRoll.h b/include/PianoRoll.h index 881732be1..35550a5b3 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -376,6 +376,7 @@ private: TimePos m_currentPosition; bool m_recording; + bool m_doAutoQuantization{false}; QList m_recordingNotes; Note * m_currentNote; diff --git a/include/SetupDialog.h b/include/SetupDialog.h index ce81bb477..7a1304d9a 100644 --- a/include/SetupDialog.h +++ b/include/SetupDialog.h @@ -109,6 +109,7 @@ private slots: // MIDI settings widget. void midiInterfaceChanged(const QString & driver); + void toggleMidiAutoQuantization(bool enabled); // Paths settings widget. void openWorkingDir(); @@ -190,6 +191,7 @@ private: MswMap m_midiIfaceSetupWidgets; trMap m_midiIfaceNames; QComboBox * m_assignableMidiDevices; + bool m_midiAutoQuantize; // Paths settings widgets. QString m_workingDir; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index 3b9273ade..7d4a9552a 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -160,6 +160,7 @@ PianoRoll::PianoRoll() : m_midiClip( nullptr ), m_currentPosition(), m_recording( false ), + m_doAutoQuantization(ConfigManager::inst()->value("midi", "autoquantize").toInt() != 0), m_currentNote( nullptr ), m_action( Action::None ), m_noteEditMode( NoteEditMode::Volume ), @@ -240,6 +241,15 @@ PianoRoll::PianoRoll() : connect( markChordAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::MarkCurrentChord); }); connect( unmarkAllAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::UnmarkAll); }); connect( copyAllNotesAction, &QAction::triggered, [this](){ markSemiTone(SemiToneMarkerAction::CopyAllNotesOnKey); }); + connect(ConfigManager::inst(), &ConfigManager::valueChanged, + [this](QString const& cls, QString const& attribute, QString const& value) + { + if (!(cls == "midi" && attribute == "autoquantize")) + { + return; + } + this->m_doAutoQuantization = (value.toInt() != 0); + }); markScaleAction->setEnabled( false ); markChordAction->setEnabled( false ); @@ -4108,8 +4118,13 @@ void PianoRoll::finishRecordNote(const Note & n ) Note n1(n.length(), it->pos(), it->key(), it->getVolume(), it->getPanning(), n.detuning()); - n1.quantizeLength( quantization() ); - m_midiClip->addNote( n1 ); + + if (m_doAutoQuantization) + { + n1.quantizeLength(quantization()); + n1.quantizePos(quantization()); + } + m_midiClip->addNote(n1, false); update(); m_recordingNotes.erase( it ); break; diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 63560e33d..ba7814f31 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -146,6 +146,8 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : "audioengine", "hqaudio").toInt()), m_bufferSize(ConfigManager::inst()->value( "audioengine", "framesperaudiobuffer").toInt()), + m_midiAutoQuantize(ConfigManager::inst()->value( + "midi", "autoquantize", "0").toInt() != 0), m_workingDir(QDir::toNativeSeparators(ConfigManager::inst()->workingDir())), m_vstDir(QDir::toNativeSeparators(ConfigManager::inst()->vstDir())), m_ladspaDir(QDir::toNativeSeparators(ConfigManager::inst()->ladspaDir())), @@ -159,8 +161,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : { setWindowIcon(embed::getIconPixmap("setup_general")); setWindowTitle(tr("Settings")); - // TODO: Equivalent to the new setWindowFlag(Qt::WindowContextHelpButtonHint, false) - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + setWindowFlag(Qt::WindowContextHelpButtonHint, false); setModal(true); Engine::projectJournal()->setJournalling(false); @@ -716,10 +717,22 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : m_assignableMidiDevices->setCurrentIndex(current); } + // MIDI Recording tab + auto* midiRecordingTab = new QGroupBox(tr("Behavior when recording"), midi_w); + auto* midiRecordingLayout = new QVBoxLayout(midiRecordingTab); + { + auto *box = addCheckBox(tr("Auto-quantize notes in Piano Roll"), + midiRecordingTab, midiRecordingLayout, + m_midiAutoQuantize, SLOT(toggleMidiAutoQuantization(bool)), + false); + box->setToolTip(tr("If enabled, notes will be automatically quantized when recording them from a MIDI controller. If disabled, they are always recorded at the highest possible resolution.")); + } + // MIDI layout ordering. midi_layout->addWidget(midiInterfaceBox); midi_layout->addWidget(ms_w); midi_layout->addWidget(midiAutoAssignBox); + midi_layout->addWidget(midiRecordingTab); midi_layout->addStretch(); @@ -965,6 +978,7 @@ void SetupDialog::accept() m_midiIfaceNames[m_midiInterfaces->currentText()]); ConfigManager::inst()->setValue("midi", "midiautoassign", m_assignableMidiDevices->currentText()); + ConfigManager::inst()->setValue("midi", "autoquantize", QString::number(m_midiAutoQuantize)); ConfigManager::inst()->setWorkingDir(QDir::fromNativeSeparators(m_workingDir)); @@ -1253,6 +1267,11 @@ void SetupDialog::midiInterfaceChanged(const QString & iface) m_midiIfaceSetupWidgets[m_midiIfaceNames[iface]]->show(); } +void SetupDialog::toggleMidiAutoQuantization(bool enabled) +{ + m_midiAutoQuantize = enabled; +} + // Paths settings slots.