From: <sv...@op...> - 2024-10-26 22:19:17
|
Author: sagamusix Date: Sun Oct 27 00:19:04 2024 New Revision: 21995 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=21995 Log: [New] Stream Export: Allow easier export of all sub-songs (https://bugs.openmpt.org/view.php?id=1515). [Imp] Stream Export: Repeat count can now also be set when exporting an order list selection, or selecting multiple sub-songs. Modified: trunk/OpenMPT/mptrack/Mod2wave.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/mod2wave.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/Mod2wave.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Mod2wave.cpp Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/mptrack/Mod2wave.cpp Sun Oct 27 00:19:04 2024 (r21995) @@ -12,6 +12,7 @@ #include "mod2wave.h" #include "Dlsbank.h" #include "Mainfrm.h" +#include "Moddoc.h" #include "Mpdlgs.h" #include "Mptrack.h" #include "Reporting.h" @@ -56,21 +57,22 @@ // CWaveConvert - setup for converting a wave file BEGIN_MESSAGE_MAP(CWaveConvert, DialogBase) - ON_COMMAND(IDC_CHECK2, &CWaveConvert::OnCheckTimeLimit) - ON_COMMAND(IDC_CHECK4, &CWaveConvert::OnCheckChannelMode) - ON_COMMAND(IDC_CHECK6, &CWaveConvert::OnCheckInstrMode) - ON_COMMAND(IDC_RADIO1, &CWaveConvert::UpdateDialog) - ON_COMMAND(IDC_RADIO2, &CWaveConvert::UpdateDialog) - ON_COMMAND(IDC_RADIO3, &CWaveConvert::UpdateDialog) - ON_COMMAND(IDC_RADIO4, &CWaveConvert::OnExportModeChanged) - ON_COMMAND(IDC_RADIO5, &CWaveConvert::OnExportModeChanged) - ON_COMMAND(IDC_PLAYEROPTIONS, &CWaveConvert::OnPlayerOptions) - ON_CBN_SELCHANGE(IDC_COMBO5, &CWaveConvert::OnFileTypeChanged) - ON_CBN_SELCHANGE(IDC_COMBO1, &CWaveConvert::OnSamplerateChanged) - ON_CBN_SELCHANGE(IDC_COMBO4, &CWaveConvert::OnChannelsChanged) - ON_CBN_SELCHANGE(IDC_COMBO6, &CWaveConvert::OnDitherChanged) - ON_CBN_SELCHANGE(IDC_COMBO2, &CWaveConvert::OnFormatChanged) - ON_CBN_SELCHANGE(IDC_COMBO9, &CWaveConvert::OnSampleSlotChanged) + ON_COMMAND(IDC_CHECK2, &CWaveConvert::OnCheckTimeLimit) + ON_COMMAND(IDC_CHECK4, &CWaveConvert::OnCheckChannelMode) + ON_COMMAND(IDC_CHECK6, &CWaveConvert::OnCheckInstrMode) + ON_COMMAND(IDC_RADIO1, &CWaveConvert::UpdateDialog) + ON_COMMAND(IDC_RADIO2, &CWaveConvert::UpdateDialog) + ON_COMMAND(IDC_RADIO3, &CWaveConvert::UpdateDialog) + ON_COMMAND(IDC_RADIO4, &CWaveConvert::OnExportModeChanged) + ON_COMMAND(IDC_RADIO5, &CWaveConvert::OnExportModeChanged) + ON_COMMAND(IDC_PLAYEROPTIONS, &CWaveConvert::OnPlayerOptions) + ON_CBN_SELCHANGE(IDC_COMBO5, &CWaveConvert::OnFileTypeChanged) + ON_CBN_SELCHANGE(IDC_COMBO1, &CWaveConvert::OnSamplerateChanged) + ON_CBN_SELCHANGE(IDC_COMBO4, &CWaveConvert::OnChannelsChanged) + ON_CBN_SELCHANGE(IDC_COMBO6, &CWaveConvert::OnDitherChanged) + ON_CBN_SELCHANGE(IDC_COMBO2, &CWaveConvert::OnFormatChanged) + ON_CBN_SELCHANGE(IDC_COMBO9, &CWaveConvert::OnSampleSlotChanged) + ON_EN_CHANGE(IDC_EDIT12, &CWaveConvert::OnSubsongChanged) END_MESSAGE_MAP() @@ -78,24 +80,23 @@ : DialogBase(IDD_WAVECONVERT, parent) , m_Settings(theApp.GetSettings(), encFactories) , m_SndFile(sndFile) + , m_subSongs{sndFile.GetAllSubSongs()} + , m_nNumOrders{numOrders} { - ASSERT(!encFactories.empty()); + MPT_ASSERT(!encFactories.empty()); encTraits = m_Settings.GetTraits(); - m_bGivePlugsIdleTime = false; if(minOrder != ORDERINDEX_INVALID && maxOrder != ORDERINDEX_INVALID) { // render selection m_Settings.minOrder = minOrder; m_Settings.maxOrder = maxOrder; } - m_Settings.repeatCount = 1; - m_Settings.minSequence = m_Settings.maxSequence = m_SndFile.Order.GetCurrentSequenceIndex(); - m_nNumOrders = numOrders; - - m_dwSongLimit = 0; } +CWaveConvert::~CWaveConvert() {} + + void CWaveConvert::DoDataExchange(CDataExchange *pDX) { DialogBase::DoDataExchange(pDX); @@ -107,8 +108,7 @@ DDX_Control(pDX, IDC_SPIN3, m_SpinMinOrder); DDX_Control(pDX, IDC_SPIN4, m_SpinMaxOrder); DDX_Control(pDX, IDC_SPIN5, m_SpinLoopCount); - DDX_Control(pDX, IDC_SPIN6, m_SpinMinSequence); - DDX_Control(pDX, IDC_SPIN7, m_SpinMaxSequence); + DDX_Control(pDX, IDC_SPIN6, m_SpinSubsongIndex); DDX_Control(pDX, IDC_COMBO9, m_CbnSampleSlot); DDX_Control(pDX, IDC_COMBO3, m_CbnGenre); @@ -131,8 +131,9 @@ CheckDlgButton(IDC_CHECK4, BST_UNCHECKED); CheckDlgButton(IDC_CHECK6, BST_UNCHECKED); + // Export limits const bool selection = (m_Settings.minOrder != ORDERINDEX_INVALID && m_Settings.maxOrder != ORDERINDEX_INVALID); - CheckRadioButton(IDC_RADIO1, IDC_RADIO3, selection ? IDC_RADIO2 : IDC_RADIO1); + CheckRadioButton(IDC_RADIO1, IDC_RADIO3, selection ? IDC_RADIO2 : IDC_RADIO3); if(selection) { SetDlgItemInt(IDC_EDIT3, m_Settings.minOrder); @@ -141,17 +142,18 @@ m_SpinMinOrder.SetRange32(0, m_nNumOrders); m_SpinMaxOrder.SetRange32(0, m_nNumOrders); - const SEQUENCEINDEX numSequences = m_SndFile.Order.GetNumSequences(); - const BOOL enableSeq = numSequences > 1 ? TRUE : FALSE; - GetDlgItem(IDC_RADIO3)->EnableWindow(enableSeq); - m_SpinMinSequence.SetRange32(1, numSequences); - m_SpinMaxSequence.SetRange32(1, numSequences); - SetDlgItemInt(IDC_EDIT12, m_Settings.minSequence + 1); - SetDlgItemInt(IDC_EDIT13, m_Settings.maxSequence + 1); - SetDlgItemInt(IDC_EDIT5, m_Settings.repeatCount, FALSE); m_SpinLoopCount.SetRange32(1, int16_max); + m_SpinSubsongIndex.SetRange32(1, static_cast<int>(m_subSongs.size())); + SetDlgItemInt(IDC_EDIT12, static_cast<UINT>(m_selectedSong + 1), FALSE); + if(m_subSongs.size() <= 1) + { + GetDlgItem(IDC_RADIO3)->SetWindowText(_T("&Entire Song")); + GetDlgItem(IDC_RADIO1)->EnableWindow(FALSE); + } + UpdateSubsongName(); + FillFileTypes(); FillSamplerates(); FillChannels(); @@ -181,6 +183,7 @@ { GetDlgItem(IDC_GIVEPLUGSIDLETIME)->EnableWindow(TRUE); GetDlgItem(IDC_RENDERSILENCE)->EnableWindow(TRUE); + CheckDlgButton(IDC_RENDERSILENCE, BST_CHECKED); break; } } @@ -203,6 +206,7 @@ CheckRadioButton(IDC_RADIO4, IDC_RADIO5, m_Settings.outputToSample ? IDC_RADIO5 : IDC_RADIO4); UpdateDialog(); + return TRUE; } @@ -238,8 +242,8 @@ DWORD_PTR dwFormat = m_CbnSampleFormat.GetItemData(m_CbnSampleFormat.GetCurSel()); Encoder::Mode mode = (Encoder::Mode)((dwFormat >> 24) & 0xff); - CheckDlgButton(IDC_CHECK3, encTraits->canCues?encSettings.Cues?TRUE:FALSE:FALSE); - ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK3), encTraits->canCues?TRUE:FALSE); + CheckDlgButton(IDC_CHECK3, (encTraits->canCues && encSettings.Cues) ? BST_CHECKED : BST_UNCHECKED); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK3), encTraits->canCues ? TRUE : FALSE); const BOOL canTags = encTraits->canTags ? TRUE : FALSE; CheckDlgButton(IDC_CHECK7, encSettings.Tags ? canTags : FALSE); @@ -565,6 +569,26 @@ } +void CWaveConvert::OnSubsongChanged() +{ + BOOL ok = FALSE; + const auto newSubSong = std::clamp(static_cast<size_t>(GetDlgItemInt(IDC_EDIT12, &ok, FALSE)), size_t(1), m_subSongs.size()) - 1; + if(m_selectedSong == newSubSong || !ok) + return; + m_selectedSong = newSubSong; + UpdateSubsongName(); +} + + +void CWaveConvert::UpdateSubsongName() +{ + const auto subsongText = GetDlgItem(IDC_SUBSONG); + if(subsongText == nullptr || m_selectedSong >= m_subSongs.size()) + return; + subsongText->SetWindowText(m_SndFile.GetpModDoc()->FormatSubsongName(m_subSongs[m_selectedSong]).c_str()); +} + + void CWaveConvert::UpdateDialog() { CheckDlgButton(IDC_CHECK2, (m_dwSongLimit) ? BST_CHECKED : 0); @@ -578,15 +602,8 @@ m_SpinMinOrder.EnableWindow(sel == IDC_RADIO2); m_SpinMaxOrder.EnableWindow(sel == IDC_RADIO2); - GetDlgItem(IDC_EDIT5)->EnableWindow(sel == IDC_RADIO1); - m_SpinLoopCount.EnableWindow(sel == IDC_RADIO1); - - const SEQUENCEINDEX numSequences = m_SndFile.Order.GetNumSequences(); - const BOOL enableSeq = (numSequences > 1 && sel == IDC_RADIO3) ? TRUE : FALSE; - GetDlgItem(IDC_EDIT12)->EnableWindow(enableSeq); - GetDlgItem(IDC_EDIT13)->EnableWindow(enableSeq); - m_SpinMinSequence.EnableWindow(enableSeq); - m_SpinMaxSequence.EnableWindow(enableSeq); + GetDlgItem(IDC_EDIT12)->EnableWindow(sel == IDC_RADIO1); + m_SpinSubsongIndex.EnableWindow(sel == IDC_RADIO1); // No free slots => Cannot do instrument- or channel-based export to sample BOOL canDoMultiExport = (IsDlgButtonChecked(IDC_RADIO4) != BST_UNCHECKED /* normal export */ || m_CbnSampleSlot.GetItemData(0) == 0 /* "free slot" is in list */) ? TRUE : FALSE; @@ -691,6 +708,7 @@ if(selection) { // Play selection + m_subSongs.clear(); m_Settings.minOrder = static_cast<ORDERINDEX>(GetDlgItemInt(IDC_EDIT3, NULL, FALSE)); m_Settings.maxOrder = static_cast<ORDERINDEX>(GetDlgItemInt(IDC_EDIT4, NULL, FALSE)); if(m_Settings.minOrder > m_Settings.maxOrder) @@ -699,16 +717,11 @@ { m_Settings.minOrder = m_Settings.maxOrder = ORDERINDEX_INVALID; } - if(IsDlgButtonChecked(IDC_RADIO3)) + if(IsDlgButtonChecked(IDC_RADIO1)) { - const UINT maxSequence = m_SndFile.Order.GetNumSequences(); - m_Settings.minSequence = static_cast<SEQUENCEINDEX>(std::clamp(GetDlgItemInt(IDC_EDIT12, NULL, FALSE), 1u, maxSequence) - 1u); - m_Settings.maxSequence = static_cast<SEQUENCEINDEX>(std::clamp(GetDlgItemInt(IDC_EDIT13, NULL, FALSE), 1u, maxSequence) - 1u); - if(m_Settings.minSequence > m_Settings.maxSequence) - std::swap(m_Settings.minSequence, m_Settings.maxSequence); - } else - { - m_Settings.minSequence = m_Settings.maxSequence = m_SndFile.Order.GetCurrentSequenceIndex(); + // Specific subsong + size_t subsong = std::clamp(static_cast<size_t>(GetDlgItemInt(IDC_EDIT12, nullptr, FALSE)), size_t(1), m_subSongs.size()) - 1; + m_subSongs = {m_subSongs[subsong]}; } m_Settings.repeatCount = static_cast<uint16>(GetDlgItemInt(IDC_EDIT5, NULL, FALSE)); @@ -883,12 +896,6 @@ , EncoderName(conf, U_("Export"), U_("Encoder"), U_("")) , EncoderIndex(FindEncoder(EncoderName)) , storedTags(conf) - , repeatCount(0) - , minOrder(ORDERINDEX_INVALID), maxOrder(ORDERINDEX_INVALID) - , sampleSlot(0) - , normalize(false) - , silencePlugBuffers(false) - , outputToSample(false) { Tags.encoder = Version::Current().GetOpenMPTVersionString(); for(const auto & factory : EncoderFactories) @@ -1063,38 +1070,31 @@ // Calculate maximum samples uint64 max = m_dwSongLimit ? ullMaxSamples : uint64_max; - // Reset song position tracking - m_SndFile.ResetPlayPos(); m_SndFile.m_PlayState.m_flags.reset(SONG_PATTERNLOOP); ORDERINDEX startOrder = 0; - GetLengthTarget target; + double duration = m_subSong.duration; if(m_Settings.minOrder != ORDERINDEX_INVALID && m_Settings.maxOrder != ORDERINDEX_INVALID) { - m_SndFile.SetRepeatCount(0); startOrder = m_Settings.minOrder; ORDERINDEX endOrder = m_Settings.maxOrder; while(!m_SndFile.Order().IsValidPat(endOrder) && endOrder > startOrder) { endOrder--; } + GetLengthTarget target; if(m_SndFile.Order().IsValidPat(endOrder)) { target = GetLengthTarget(endOrder, m_SndFile.Patterns[m_SndFile.Order()[endOrder]].GetNumRows() - 1); } target.StartPos(m_SndFile.Order.GetCurrentSequenceIndex(), startOrder, 0); - m_SndFile.m_nMaxOrderPosition = endOrder + 1; - } else - { - m_SndFile.SetRepeatCount(std::max(0, m_Settings.repeatCount - 1)); + m_SndFile.m_restartOverridePos = m_Settings.minOrder; + m_SndFile.m_maxOrderPosition = endOrder + 1; + duration = m_SndFile.GetLength(eNoAdjust, target).front().duration; } - uint64 l = mpt::saturate_round<uint64>(m_SndFile.GetLength(eNoAdjust, target).front().duration * samplerate * (1 + m_SndFile.GetRepeatCount())); - - m_SndFile.SetCurrentOrder(startOrder); - m_SndFile.GetLength(eAdjust, GetLengthTarget(startOrder, 0)); // adjust playback variables / visited rows vector - m_SndFile.m_PlayState.m_nCurrentOrder = startOrder; - - if (l < max) max = l; + m_SndFile.SetRepeatCount(std::max(0, m_Settings.repeatCount - 1)); + uint64 l = mpt::saturate_round<uint64>(duration * samplerate * (1 + m_SndFile.GetRepeatCount())); + LimitMax(max, l); SetRange(0, max); EnableTaskbarProgress(); @@ -1105,17 +1105,20 @@ // Process the conversion - // For calculating the remaining time - auto dwStartTime = timeGetTime(), prevTime = dwStartTime; - uint32 timeRemaining = 0; - - uint64 bytesWritten = 0; - auto mainFrame = CMainFrame::GetMainFrame(); mainFrame->PauseMod(); - m_SndFile.m_PlayState.m_flags.reset(SONG_STEP | SONG_PATTERNLOOP); + + // Reset song position tracking + m_SndFile.ResetPlayPos(); + m_SndFile.GetLength(eAdjust, GetLengthTarget(m_subSong.startOrder, m_subSong.startRow).StartPos(m_subSong.sequence, 0, 0)); + m_SndFile.m_PlayState.m_flags.reset(); + mainFrame->InitRenderer(&m_SndFile); + // For calculating the remaining time + auto dwStartTime = timeGetTime(), prevTime = dwStartTime; + uint32 timeRemaining = 0; + uint64 bytesWritten = 0; while(true) { UINT lRead = 0; @@ -1262,7 +1265,7 @@ } } - m_SndFile.m_nMaxOrderPosition = 0; + m_SndFile.m_restartOverridePos = m_SndFile.m_maxOrderPosition = 0; mainFrame->StopRenderer(&m_SndFile); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/mptrack/Moddoc.cpp Sun Oct 27 00:19:04 2024 (r21995) @@ -1759,23 +1759,33 @@ int oldRepeat = m_SndFile.GetRepeatCount(); const SEQUENCEINDEX currentSeq = m_SndFile.Order.GetCurrentSequenceIndex(); - for(SEQUENCEINDEX seq = wsdlg.m_Settings.minSequence; seq <= wsdlg.m_Settings.maxSequence; seq++) + if(wsdlg.m_subSongs.empty()) { - m_SndFile.Order.SetSequence(seq); + // Render selection + SubSong subsong{}; + subsong.sequence = currentSeq; + subsong.startOrder = wsdlg.m_Settings.minOrder; + wsdlg.m_subSongs.push_back(subsong); + } + for(size_t subsong = 0; subsong < wsdlg.m_subSongs.size(); subsong++) + { + const auto &song = wsdlg.m_subSongs[subsong]; mpt::ustring fileNameAdd; for(int i = 0; i < nRenderPasses; i++) { mpt::PathString thisName = fileName; CString caption = _T("file"); fileNameAdd.clear(); - if(wsdlg.m_Settings.minSequence != wsdlg.m_Settings.maxSequence) + if(wsdlg.m_subSongs.size() > 1) { - fileNameAdd = MPT_UFORMAT("-{}")(mpt::ufmt::dec0<2>(seq + 1)); - mpt::ustring seqName = m_SndFile.Order(seq).GetName(); + fileNameAdd = MPT_UFORMAT("-{}")(mpt::ufmt::dec0<2>(subsong + 1)); + mpt::ustring seqName = m_SndFile.Order(song.sequence).GetName(); if(!seqName.empty()) - { fileNameAdd += UL_("-") + seqName; - } + const auto startPattern = m_SndFile.Order(song.sequence).PatternAt(song.startOrder); + const auto orderName = startPattern ? startPattern->GetName() : std::string{}; + if(!orderName.empty()) + fileNameAdd += UL_("-") + mpt::ToUnicode(m_SndFile.GetCharsetInternal(), orderName); } // Channel mode @@ -1878,7 +1888,7 @@ } else { BypassInputHandler bih; - CDoWaveConvert dwcdlg(m_SndFile, f, caption, wsdlg.m_Settings, pMainFrm); + CDoWaveConvert dwcdlg(m_SndFile, f, caption, wsdlg.m_Settings, song, pMainFrm); dwcdlg.m_bGivePlugsIdleTime = wsdlg.m_bGivePlugsIdleTime; dwcdlg.m_dwSongLimit = wsdlg.m_dwSongLimit; cancel = dwcdlg.DoModal() != IDOK; Modified: trunk/OpenMPT/mptrack/mod2wave.h ============================================================================== --- trunk/OpenMPT/mptrack/mod2wave.h Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/mptrack/mod2wave.h Sun Oct 27 00:19:04 2024 (r21995) @@ -23,6 +23,7 @@ OPENMPT_NAMESPACE_BEGIN class CSoundFile; +struct SubSong; struct CWaveConvertSettings { @@ -35,14 +36,13 @@ StoredTags storedTags; FileTags Tags; - int repeatCount; - ORDERINDEX minOrder, maxOrder; - SAMPLEINDEX sampleSlot; - SEQUENCEINDEX minSequence, maxSequence; - - bool normalize : 1; - bool silencePlugBuffers : 1; - bool outputToSample : 1; + int repeatCount = 1; + ORDERINDEX minOrder = ORDERINDEX_INVALID, maxOrder = ORDERINDEX_INVALID; + SAMPLEINDEX sampleSlot = 0; + + bool normalize = false; + bool silencePlugBuffers = false; + bool outputToSample = false; std::size_t FindEncoder(const mpt::ustring &name) const; void SelectEncoder(std::size_t index); @@ -58,21 +58,29 @@ { public: CWaveConvertSettings m_Settings; - const Encoder::Traits *encTraits; CSoundFile &m_SndFile; - uint64 m_dwSongLimit; - ORDERINDEX m_nNumOrders; + uint64 m_dwSongLimit = 0; + std::vector<SubSong> m_subSongs; - CComboBox m_CbnFileType, m_CbnSampleRate, m_CbnChannels, m_CbnDither, m_CbnSampleFormat, m_CbnSampleSlot; - CSpinButtonCtrl m_SpinLoopCount, m_SpinMinOrder, m_SpinMaxOrder, m_SpinMinSequence, m_SpinMaxSequence; + bool m_bGivePlugsIdleTime = false; + bool m_bChannelMode = false; // Render by channel + bool m_bInstrumentMode = false; // Render by instrument + +private: + const Encoder::Traits *encTraits = nullptr; - bool m_bGivePlugsIdleTime; - bool m_bChannelMode; // Render by channel - bool m_bInstrumentMode; // Render by instrument + CComboBox m_CbnFileType, m_CbnSampleRate, m_CbnChannels, m_CbnDither, m_CbnSampleFormat, m_CbnSampleSlot; + CSpinButtonCtrl m_SpinLoopCount, m_SpinMinOrder, m_SpinMaxOrder, m_SpinSubsongIndex; CEdit m_EditTitle, m_EditAuthor, m_EditURL, m_EditAlbum, m_EditYear; CComboBox m_CbnGenre; CEdit m_EditGenre; + size_t m_selectedSong = 0; + const ORDERINDEX m_nNumOrders; + +public: + CWaveConvert(CWnd *parent, ORDERINDEX minOrder, ORDERINDEX maxOrder, ORDERINDEX numOrders, CSoundFile &sndFile, const std::vector<EncoderFactoryBase *> &encFactories); + ~CWaveConvert(); private: void FillFileTypes(); @@ -87,14 +95,13 @@ void SaveEncoderSettings(); void SaveTags(); -public: - CWaveConvert(CWnd *parent, ORDERINDEX minOrder, ORDERINDEX maxOrder, ORDERINDEX numOrders, CSoundFile &sndFile, const std::vector<EncoderFactoryBase*> &encFactories); - -public: + void UpdateSubsongName(); void UpdateDialog(); + BOOL OnInitDialog() override; void DoDataExchange(CDataExchange *pDX) override; void OnOK() override; + afx_msg void OnCheckTimeLimit(); afx_msg void OnCheckChannelMode(); afx_msg void OnCheckInstrMode(); @@ -103,9 +110,11 @@ afx_msg void OnChannelsChanged(); afx_msg void OnDitherChanged(); afx_msg void OnFormatChanged(); + afx_msg void OnSubsongChanged(); afx_msg void OnPlayerOptions(); afx_msg void OnExportModeChanged(); afx_msg void OnSampleSlotChanged(); + DECLARE_MESSAGE_MAP() }; @@ -113,23 +122,27 @@ class CDoWaveConvert: public CProgressDialog { public: - const CWaveConvertSettings &m_Settings; - CSoundFile &m_SndFile; - std::ostream &fileStream; - const CString &caption; - uint64 m_dwSongLimit; - bool m_bGivePlugsIdleTime; + uint64 m_dwSongLimit = 0; + bool m_bGivePlugsIdleTime = false; public: - CDoWaveConvert(CSoundFile &sndFile, std::ostream &f, const CString &caption, const CWaveConvertSettings &settings, CWnd *parent = NULL) + CDoWaveConvert(CSoundFile &sndFile, std::ostream &f, const CString &caption, const CWaveConvertSettings &settings, const SubSong &subSong, CWnd *parent = nullptr) : CProgressDialog(parent) , m_Settings(settings) , m_SndFile(sndFile) , fileStream(f) , caption(caption) - , m_dwSongLimit(0) + , m_subSong(subSong) { } + void Run() override; + +private: + const CWaveConvertSettings &m_Settings; + CSoundFile &m_SndFile; + std::ostream &fileStream; + const CString &caption; + const SubSong &m_subSong; }; Modified: trunk/OpenMPT/mptrack/mptrack.rc ============================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/mptrack/mptrack.rc Sun Oct 27 00:19:04 2024 (r21995) @@ -1164,13 +1164,13 @@ LTEXT "50ms",IDC_STATIC,211,257,23,8 END -IDD_WAVECONVERT DIALOGEX 0, 0, 388, 239 +IDD_WAVECONVERT DIALOGEX 0, 0, 389, 290 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Export" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - DEFPUSHBUTTON "OK",IDOK,270,216,50,14 - PUSHBUTTON "Cancel",IDCANCEL,330,216,50,14 + DEFPUSHBUTTON "&OK",IDOK,270,270,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,330,270,50,14 GROUPBOX "For&mat",IDC_STATIC,6,6,186,66 COMBOBOX IDC_COMBO5,12,18,174,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO1,12,36,54,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP @@ -1178,8 +1178,8 @@ COMBOBOX IDC_COMBO6,120,36,66,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO2,12,54,174,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP GROUPBOX "Render",IDC_STATIC,6,78,186,84 - PUSHBUTTON "Player &Options",IDC_PLAYEROPTIONS,12,90,60,14,BS_CENTER - CONTROL "&Channel mode (one file per channel)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,108,174,12 + PUSHBUTTON "Pla&yer Options",IDC_PLAYEROPTIONS,12,90,60,14,BS_CENTER + CONTROL "C&hannel mode (one file per channel)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,108,174,12 CONTROL "&Instrument mode (one file per instrument)",IDC_CHECK6, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,120,174,12 CONTROL "&Normalize Output",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,132,174,12 @@ -1190,44 +1190,43 @@ "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_MULTILINE | WS_TABSTOP,12,180,174,12 CONTROL "Clear plugin &buffers before exporting",IDC_RENDERSILENCE, "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_MULTILINE | WS_TABSTOP,12,192,174,12 - GROUPBOX "Limit",IDC_STATIC,198,6,186,84 + GROUPBOX "Limit",IDC_STATIC,198,6,186,126 CONTROL "Limit song &length to: (seconds)",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,18,114,10 EDITTEXT IDC_EDIT2,324,18,50,12,ES_AUTOHSCROLL - CONTROL "&Sequences",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,204,36,72,12 - CONTROL "Play &entire song",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,204,54,72,12 - CONTROL "From &position",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,204,73,72,12 - EDITTEXT IDC_EDIT12,276,36,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPIN6,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,300,41,11,11 - CTEXT "to",IDC_STATIC,318,36,8,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT13,330,36,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPIN7,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,354,41,11,11 - EDITTEXT IDC_EDIT5,276,54,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPIN5,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,300,60,11,11 - LTEXT "times",IDC_STATIC,319,55,59,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT3,276,73,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,300,78,11,11 - CTEXT "to",IDC_STATIC,318,73,8,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT4,330,73,36,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPIN4,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,354,78,11,11 - GROUPBOX "Tags",IDC_STATIC,198,96,186,114 - CONTROL "Incl&ude Song Information",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,108,174,10 - LTEXT "Title:",IDC_STATIC,204,122,17,8 - EDITTEXT IDC_EDIT11,240,120,138,12,ES_AUTOHSCROLL - LTEXT "Author:",IDC_STATIC,204,140,30,8 - EDITTEXT IDC_EDIT6,240,138,138,12,ES_AUTOHSCROLL - LTEXT "Album:",IDC_STATIC,204,158,30,8 - EDITTEXT IDC_EDIT7,240,156,138,12,ES_AUTOHSCROLL - LTEXT "URL:",IDC_STATIC,204,176,30,8 - EDITTEXT IDC_EDIT8,240,174,138,12,ES_AUTOHSCROLL - LTEXT "Genre:",IDC_STATIC,204,194,29,8 - EDITTEXT IDC_EDIT10,240,192,78,12,ES_AUTOHSCROLL - RTEXT "Year:",IDC_STATIC,324,194,18,8 - EDITTEXT IDC_EDIT9,348,192,30,12,ES_AUTOHSCROLL | ES_NUMBER - LTEXT "Export To:",IDC_STATIC,6,219,48,8 - CONTROL "&File",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,54,219,38,8 - CONTROL "S&le Slot",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,96,219,56,8 - COMBOBOX IDC_COMBO9,156,217,96,119,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_COMBO3,240,192,78,64,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Repea&t",IDC_STATIC,204,34,36,12,SS_CENTERIMAGE + EDITTEXT IDC_EDIT5,240,34,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN5,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,264,40,11,11 + LTEXT "times",IDC_STATIC,282,34,59,12,SS_CENTERIMAGE + CONTROL "All Sub Songs (S&eparate Files)",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,204,54,138,12 + CONTROL "&Sub Song:",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,204,72,72,12 + CONTROL "From &position",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,204,114,72,12 + EDITTEXT IDC_EDIT12,276,72,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN6,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,306,72,11,11 + CONTROL "",IDC_SUBSONG,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX | WS_GROUP,215,90,163,18 + EDITTEXT IDC_EDIT3,276,114,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,300,119,11,11 + CTEXT "to",IDC_STATIC,318,114,8,12,SS_CENTERIMAGE + EDITTEXT IDC_EDIT4,330,114,36,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN4,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,354,119,11,11 + GROUPBOX "Tags",IDC_STATIC,198,138,186,126 + CONTROL "Incl&ude Song Information",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,204,156,174,10 + LTEXT "Title:",IDC_STATIC,204,174,17,8 + EDITTEXT IDC_EDIT11,240,170,138,12,ES_AUTOHSCROLL + LTEXT "Author:",IDC_STATIC,204,190,30,8 + EDITTEXT IDC_EDIT6,240,190,138,12,ES_AUTOHSCROLL + LTEXT "Album:",IDC_STATIC,204,209,30,8 + EDITTEXT IDC_EDIT7,240,206,138,12,ES_AUTOHSCROLL + LTEXT "URL:",IDC_STATIC,204,226,30,8 + EDITTEXT IDC_EDIT8,240,225,138,12,ES_AUTOHSCROLL + LTEXT "Genre:",IDC_STATIC,204,244,29,8 + EDITTEXT IDC_EDIT10,240,242,78,12,ES_AUTOHSCROLL + COMBOBOX IDC_COMBO3,240,242,78,64,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + RTEXT "Year:",IDC_STATIC,324,244,18,8 + EDITTEXT IDC_EDIT9,348,242,30,12,ES_AUTOHSCROLL | ES_NUMBER + GROUPBOX "Export To",IDC_STATIC,6,216,186,48 + CONTROL "&File",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,12,228,38,8 + CONTROL "Sampl&e Slot",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,12,246,56,8 + COMBOBOX IDC_COMBO9,72,243,114,119,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP END IDD_PROGRESS DIALOGEX 0, 0, 220, 55 @@ -2329,8 +2328,8 @@ IDD_WAVECONVERT, DIALOG BEGIN - RIGHTMARGIN, 337 - BOTTOMMARGIN, 236 + RIGHTMARGIN, 338 + BOTTOMMARGIN, 287 END IDD_PROGRESS, DIALOG Modified: trunk/OpenMPT/soundlib/Sndfile.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/soundlib/Sndfile.cpp Sun Oct 27 00:19:04 2024 (r21995) @@ -695,7 +695,7 @@ if(UseFinetuneAndTranspose()) m_playBehaviour.reset(kPeriodsAreHertz); - m_nMaxOrderPosition = 0; + m_restartOverridePos = m_maxOrderPosition = 0; RecalculateSamplesPerTick(); Modified: trunk/OpenMPT/soundlib/Sndfile.h ============================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/soundlib/Sndfile.h Sun Oct 27 00:19:04 2024 (r21995) @@ -527,7 +527,7 @@ ResamplingMode m_nResampling; // Resampling mode (if overriding the globally set resampling) int32 m_nRepeatCount = 0; // -1 means repeat infinitely. - ORDERINDEX m_nMaxOrderPosition; + ORDERINDEX m_restartOverridePos = 0, m_maxOrderPosition = 0; std::vector<ModChannelSettings> ChnSettings; // Initial channels settings CPatternContainer Patterns; ModSequenceSet Order; // Pattern sequences (order lists) Modified: trunk/OpenMPT/soundlib/Sndmix.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp Sat Oct 26 22:21:46 2024 (r21994) +++ trunk/OpenMPT/soundlib/Sndmix.cpp Sun Oct 27 00:19:04 2024 (r21995) @@ -252,12 +252,6 @@ } else { // No new pattern data - #ifdef MODPLUG_TRACKER - if((m_nMaxOrderPosition) && (m_PlayState.m_nCurrentOrder >= m_nMaxOrderPosition)) - { - m_PlayState.m_flags.set(SONG_ENDREACHED); - } - #endif // MODPLUG_TRACKER if(IsRenderingToDisc()) { // Disable song fade when rendering or when requested in libopenmpt. @@ -462,15 +456,18 @@ // Check if pattern is valid if(!m_PlayState.m_flags[SONG_PATTERNLOOP]) { - m_PlayState.m_nPattern = (m_PlayState.m_nCurrentOrder < Order().size()) ? Order()[m_PlayState.m_nCurrentOrder] : PATTERNINDEX_INVALID; - if (m_PlayState.m_nPattern < Patterns.Size() && !Patterns[m_PlayState.m_nPattern].IsValid()) m_PlayState.m_nPattern = PATTERNINDEX_SKIP; - while (m_PlayState.m_nPattern >= Patterns.Size()) + const size_t songEnd = m_maxOrderPosition ? m_maxOrderPosition : Order().size(); + m_PlayState.m_nPattern = (m_PlayState.m_nCurrentOrder < songEnd) ? Order()[m_PlayState.m_nCurrentOrder] : PATTERNINDEX_INVALID; + if(m_PlayState.m_nPattern < Patterns.Size() && !Patterns[m_PlayState.m_nPattern].IsValid()) + m_PlayState.m_nPattern = PATTERNINDEX_SKIP; + + while(m_PlayState.m_nPattern >= Patterns.Size()) { // End of song? - if ((m_PlayState.m_nPattern == PATTERNINDEX_INVALID) || (m_PlayState.m_nCurrentOrder >= Order().size())) + if ((m_PlayState.m_nPattern == PATTERNINDEX_INVALID) || (m_PlayState.m_nCurrentOrder >= songEnd)) { - ORDERINDEX restartPosOverride = Order().GetRestartPos(); - if(restartPosOverride == 0 && m_PlayState.m_nCurrentOrder <= Order().size() && m_PlayState.m_nCurrentOrder > 0) + ORDERINDEX restartPosOverride = m_maxOrderPosition ? m_restartOverridePos : Order().GetRestartPos(); + if(restartPosOverride == 0 && m_PlayState.m_nCurrentOrder <= songEnd && m_PlayState.m_nCurrentOrder > 0) { // Subtune detection. Subtunes are separated by "---" order items, so if we're in a // subtune and there's no restart position, we go to the first order of the subtune @@ -564,10 +561,6 @@ m_PlayState.m_nPattern = PATTERNINDEX_SKIP; } m_PlayState.m_nNextOrder = m_PlayState.m_nCurrentOrder; - -#ifdef MODPLUG_TRACKER - if ((m_nMaxOrderPosition) && (m_PlayState.m_nCurrentOrder >= m_nMaxOrderPosition)) return false; -#endif // MODPLUG_TRACKER } // Weird stuff? |