From: <sv...@op...> - 2024-10-26 23:30:51
|
Author: sagamusix Date: Sun Oct 27 01:30:39 2024 New Revision: 21996 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=21996 Log: [Imp] Resampling Dialog: Add an option to change notes in MOD format to compensate for the change in middle-C Frequency (https://forum.openmpt.org/index.php?topic=7245.0). Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/Ctrl_smp.h trunk/OpenMPT/mptrack/SampleEditorDialogs.cpp trunk/OpenMPT/mptrack/SampleEditorDialogs.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/tracklib/SampleEdit.cpp trunk/OpenMPT/tracklib/SampleEdit.h Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp Sun Oct 27 01:30:39 2024 (r21996) @@ -1793,7 +1793,7 @@ } const uint32 oldRate = sample.GetSampleRate(m_sndFile.GetType()); - CResamplingDlg dlg(this, oldRate, TrackerSettings::Instance().sampleEditorDefaultResampler, first != last); + CResamplingDlg dlg(this, oldRate, TrackerSettings::Instance().sampleEditorDefaultResampler, first != last, m_sndFile.GetBestSaveFormat() == MOD_TYPE_MOD); if(dlg.DoModal() != IDOK) return; @@ -1808,12 +1808,12 @@ newFreq = sampleFreq / 2; else if(newFreq == sampleFreq) continue; - ApplyResample(smp, newFreq, dlg.GetFilter(), first != last, dlg.UpdatePatternCommands()); + ApplyResample(smp, newFreq, dlg.GetFilter(), first != last, dlg.UpdatePatternCommands(), dlg.UpdatePatternNotes()); } } -void CCtrlSamples::ApplyResample(SAMPLEINDEX smp, uint32 newRate, ResamplingMode mode, bool ignoreSelection, bool updatePatternCommands) +void CCtrlSamples::ApplyResample(SAMPLEINDEX smp, uint32 newRate, ResamplingMode mode, bool ignoreSelection, bool updatePatternCommands, bool updatePatternNotes) { BeginWaitCursor(); @@ -1848,7 +1848,7 @@ { m_modDoc.PrepareUndoForAllPatterns(false, "Resample (Adjust Offsets)"); }; - SmpLength newSelEnd = SampleEdit::Resample(sample, selection.nStart, selection.nEnd, newRate, mode, m_sndFile, updatePatternCommands, prepareSampleUndoFunc, preparePatternUndoFunc); + SmpLength newSelEnd = SampleEdit::Resample(sample, selection.nStart, selection.nEnd, newRate, mode, m_sndFile, updatePatternCommands, updatePatternNotes, prepareSampleUndoFunc, preparePatternUndoFunc); if(!newSelEnd) { MessageBeep(MB_ICONWARNING); @@ -1857,7 +1857,7 @@ } SetModified(smp, SampleHint().Info().Data(), smp == m_nSample, true); - if(updatePatternCommands) + if(updatePatternCommands || updatePatternNotes) { m_modDoc.UpdateAllViews(nullptr, PatternHint().Data(), this); } Modified: trunk/OpenMPT/mptrack/Ctrl_smp.h ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.h Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/mptrack/Ctrl_smp.h Sun Oct 27 01:30:39 2024 (r21996) @@ -77,7 +77,7 @@ void RemoveDCOffset(bool allSamples); void ApplyAmplify(const double amp, const double fadeInStart, const double fadeOutEnd, const bool fadeIn, const bool fadeOut, const Fade::Law fadeLaw); - void ApplyResample(SAMPLEINDEX smp, uint32 newRate, ResamplingMode mode, bool ignoreSelection = false, bool updatePatternCommands = false); + void ApplyResample(SAMPLEINDEX smp, uint32 newRate, ResamplingMode mode, bool ignoreSelection = false, bool updatePatternCommands = false, bool updatePatternNotes = false); SampleSelectionPoints GetSelectionPoints(); void SetSelectionPoints(SmpLength nStart, SmpLength nEnd); Modified: trunk/OpenMPT/mptrack/SampleEditorDialogs.cpp ============================================================================== --- trunk/OpenMPT/mptrack/SampleEditorDialogs.cpp Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/mptrack/SampleEditorDialogs.cpp Sun Oct 27 01:30:39 2024 (r21996) @@ -790,18 +790,20 @@ CResamplingDlg::ResamplingOption CResamplingDlg::m_lastChoice = CResamplingDlg::Upsample; uint32 CResamplingDlg::m_lastFrequency = 0; -bool CResamplingDlg::m_updatePatterns = false; +bool CResamplingDlg::m_updatePatternCommands = false; +bool CResamplingDlg::m_updatePatternNotes = false; BEGIN_MESSAGE_MAP(CResamplingDlg, DialogBase) ON_EN_SETFOCUS(IDC_EDIT1, &CResamplingDlg::OnFocusEdit) END_MESSAGE_MAP() -CResamplingDlg::CResamplingDlg(CWnd *parent, uint32 frequency, ResamplingMode srcMode, bool resampleAll) +CResamplingDlg::CResamplingDlg(CWnd *parent, uint32 frequency, ResamplingMode srcMode, bool resampleAll, bool allowAdjustNotes) : DialogBase{IDD_RESAMPLE, parent} , m_srcMode{srcMode} , m_frequency{frequency} , m_resampleAll{resampleAll} + , m_allowAdjustNotes{allowAdjustNotes} { } @@ -848,7 +850,9 @@ } cbnResampling->SetRedraw(TRUE); - CheckDlgButton(IDC_CHECK1, m_updatePatterns ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(IDC_CHECK1, m_updatePatternCommands ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(IDC_CHECK2, (m_updatePatternNotes && m_allowAdjustNotes) ? BST_CHECKED : BST_UNCHECKED); + GetDlgItem(IDC_CHECK2)->EnableWindow(m_allowAdjustNotes ? TRUE : FALSE); return TRUE; } @@ -883,7 +887,8 @@ CComboBox *cbnResampling = static_cast<CComboBox *>(GetDlgItem(IDC_COMBO_FILTER)); m_srcMode = static_cast<ResamplingMode>(cbnResampling->GetItemData(cbnResampling->GetCurSel())); - m_updatePatterns = IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED; + m_updatePatternCommands = IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED; + m_updatePatternNotes = IsDlgButtonChecked(IDC_CHECK2) != BST_UNCHECKED; DialogBase::OnOK(); } Modified: trunk/OpenMPT/mptrack/SampleEditorDialogs.h ============================================================================== --- trunk/OpenMPT/mptrack/SampleEditorDialogs.h Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/mptrack/SampleEditorDialogs.h Sun Oct 27 01:30:39 2024 (r21996) @@ -224,17 +224,20 @@ protected: ResamplingMode m_srcMode; uint32 m_frequency; - bool m_resampleAll; + const bool m_resampleAll; + const bool m_allowAdjustNotes; static uint32 m_lastFrequency; static ResamplingOption m_lastChoice; - static bool m_updatePatterns; + static bool m_updatePatternCommands; + static bool m_updatePatternNotes; public: - CResamplingDlg(CWnd *parent, uint32 frequency, ResamplingMode srcMode, bool resampleAll); + CResamplingDlg(CWnd *parent, uint32 frequency, ResamplingMode srcMode, bool resampleAll, bool allowAdjustNotes); uint32 GetFrequency() const { return m_frequency; } ResamplingMode GetFilter() const { return m_srcMode; } static ResamplingOption GetResamplingOption() { return m_lastChoice; } - static bool UpdatePatternCommands() { return m_updatePatterns; } + static bool UpdatePatternCommands() { return m_updatePatternCommands; } + static bool UpdatePatternNotes() { return m_updatePatternNotes; } protected: BOOL OnInitDialog() override; Modified: trunk/OpenMPT/mptrack/mptrack.rc ============================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/mptrack/mptrack.rc Sun Oct 27 01:30:39 2024 (r21996) @@ -371,7 +371,7 @@ CTEXT "",IDC_SCANTEXT,6,7,306,20,SS_NOPREFIX END -IDD_RESAMPLE DIALOGEX 0, 0, 197, 110 +IDD_RESAMPLE DIALOGEX 0, 0, 197, 122 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Resample" FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -388,6 +388,7 @@ DEFPUSHBUTTON "&OK",IDOK,138,6,50,14 PUSHBUTTON "&Cancel",IDCANCEL,138,24,50,14 CONTROL "&Adjust Offset Commands in Patterns",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,90,133,10 + CONTROL "Adjust &Notes in Patterns",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,105,94,10 END IDD_WECLOME DIALOGEX 0, 0, 257, 266 @@ -809,7 +810,7 @@ LEFTMARGIN, 7 RIGHTMARGIN, 190 TOPMARGIN, 7 - BOTTOMMARGIN, 103 + BOTTOMMARGIN, 115 END IDD_WECLOME, DIALOG Modified: trunk/OpenMPT/tracklib/SampleEdit.cpp ============================================================================== --- trunk/OpenMPT/tracklib/SampleEdit.cpp Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/tracklib/SampleEdit.cpp Sun Oct 27 01:30:39 2024 (r21996) @@ -12,6 +12,7 @@ #include "SampleEdit.h" #include "../soundlib/AudioCriticalSection.h" #include "../soundlib/MixFuncTable.h" +#include "../soundlib/mod_specifications.h" #include "../soundlib/modsmp_ctrl.h" #include "../soundlib/SampleCopy.h" #include "../soundlib/Sndfile.h" @@ -830,7 +831,7 @@ // Resample using given resampling method (SRCMODE_DEFAULT = r8brain). // Returns end point of resampled data, or 0 on failure. -SmpLength Resample(ModSample &smp, SmpLength start, SmpLength end, uint32 newRate, ResamplingMode mode, CSoundFile &sndFile, bool updatePatternCommands, const std::function<void()> &prepareSampleUndoFunc, const std::function<void()> &preparePatternUndoFunc) +SmpLength Resample(ModSample &smp, SmpLength start, SmpLength end, uint32 newRate, ResamplingMode mode, CSoundFile &sndFile, bool updatePatternCommands, bool updatePatternNotes, const std::function<void()> &prepareSampleUndoFunc, const std::function<void()> &preparePatternUndoFunc) { if(!smp.HasSampleData() || smp.uFlags[CHN_ADLIB] || start >= end) return 0; @@ -1013,15 +1014,15 @@ LimitMax(point, newTotalLength); } + const SAMPLEINDEX sampleIndex = static_cast<SAMPLEINDEX>(std::distance(&sndFile.GetSample(0), &smp)); + bool patternUndoCreated = false; if(updatePatternCommands) { - const SAMPLEINDEX sample = static_cast<SAMPLEINDEX>(std::distance(&sndFile.GetSample(0), &smp)); - bool patternUndoCreated = false; sndFile.Patterns.ForEachModCommand([&](ModCommand &m) { if(m.command != CMD_OFFSET && m.command != CMD_REVERSEOFFSET && m.command != CMD_OFFSETPERCENTAGE) return; - if(sndFile.GetSampleIndex(m.note, m.instr) != sample) + if(sndFile.GetSampleIndex(m.note, m.instr) != sampleIndex) return; SmpLength point = m.param * 256u; @@ -1051,10 +1052,50 @@ }); } - if(!partialResample && sndFile.GetType() != MOD_TYPE_MOD) + const double transpose = 12.0 * std::log(static_cast<double>(newRate) / oldRate) / std::log(2.0); + int noteAdjust = mpt::saturate_round<int>(transpose); + if(updatePatternNotes && noteAdjust != 0) { - smp.nC5Speed = newRate; - smp.FrequencyToTranspose(); + sndFile.Patterns.ForEachModCommand([&](ModCommand &m) + { + if(!m.IsNote()) + return; + if(sndFile.GetSampleIndex(m.note, m.instr) != sampleIndex) + return; + + const auto newNote = static_cast<ModCommand::NOTE>(Clamp(m.note + noteAdjust, sndFile.GetModSpecifications().noteMin, sndFile.GetModSpecifications().noteMax)); + if(m.note == newNote) + return; + + if(!patternUndoCreated) + { + patternUndoCreated = true; + preparePatternUndoFunc(); + } + m.note = newNote; + }); + } + + if(!partialResample || updatePatternNotes) + { + if (sndFile.GetBestSaveFormat() == MOD_TYPE_MOD) + { + int finetuneAdjust = smp.nFineTune / 16 + mpt::saturate_round<int>((transpose - noteAdjust) * 8.0); + if(finetuneAdjust >= 8) + { + finetuneAdjust -= 16; + noteAdjust++; + } else if(finetuneAdjust < -8) + { + finetuneAdjust += 16; + noteAdjust--; + } + smp.nFineTune = MOD2XMFineTune(finetuneAdjust); + } else + { + smp.nC5Speed = newRate; + smp.FrequencyToTranspose(); + } } smp.ReplaceWaveform(newSample, newTotalLength, sndFile); Modified: trunk/OpenMPT/tracklib/SampleEdit.h ============================================================================== --- trunk/OpenMPT/tracklib/SampleEdit.h Sun Oct 27 00:19:04 2024 (r21995) +++ trunk/OpenMPT/tracklib/SampleEdit.h Sun Oct 27 01:30:39 2024 (r21996) @@ -96,7 +96,7 @@ // Resample using given resampling method (SRCMODE_DEFAULT = r8brain). // Returns end point of resampled data, or 0 on failure. -SmpLength Resample(ModSample &smp, SmpLength start, SmpLength end, uint32 newRate, ResamplingMode mode, CSoundFile &sndFile, bool updatePatternCommands, const std::function<void()> &prepareSampleUndoFunc, const std::function<void()> &preparePatternUndoFunc); +SmpLength Resample(ModSample &smp, SmpLength start, SmpLength end, uint32 newRate, ResamplingMode mode, CSoundFile &sndFile, bool updatePatternCommands, bool updatePatternNotes, const std::function<void()> &prepareSampleUndoFunc, const std::function<void()> &preparePatternUndoFunc); } // namespace SampleEdit |