From: <sv...@op...> - 2024-12-21 19:26:18
|
Author: sagamusix Date: Sat Dec 21 20:26:11 2024 New Revision: 22594 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22594 Log: Merged revision(s) 22591-22593 from trunk/OpenMPT: [Imp] MO3: Import dummy command W (XM). ........ [Imp] Pressing Ctrl while moving loop points or clicking loop start/end spin buttons now moves the loop, keeping the loop length constant. ........ [Ref] Remove unused variable. ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/mptrack/Ctrl_smp.cpp branches/OpenMPT-1.31/mptrack/View_smp.cpp branches/OpenMPT-1.31/soundlib/Load_mo3.cpp branches/OpenMPT-1.31/soundlib/ModSample.h branches/OpenMPT-1.31/soundlib/modsmp_ctrl.cpp branches/OpenMPT-1.31/tracklib/SampleEdit.cpp branches/OpenMPT-1.31/tracklib/SampleEdit.h Modified: branches/OpenMPT-1.31/mptrack/Ctrl_smp.cpp ============================================================================== --- branches/OpenMPT-1.31/mptrack/Ctrl_smp.cpp Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/mptrack/Ctrl_smp.cpp Sat Dec 21 20:26:11 2024 (r22594) @@ -2938,99 +2938,29 @@ } -#define SMPLOOP_ACCURACY 7 // 5% -#define BIDILOOP_ACCURACY 2 // 5% - - -bool MPT_LoopCheck(int sstart0, int sstart1, int send0, int send1) -{ - int dse0 = send0 - sstart0; - if ((dse0 < -SMPLOOP_ACCURACY) || (dse0 > SMPLOOP_ACCURACY)) return false; - int dse1 = send1 - sstart1; - if ((dse1 < -SMPLOOP_ACCURACY) || (dse1 > SMPLOOP_ACCURACY)) return false; - int dstart = sstart1 - sstart0; - int dend = send1 - send0; - if (!dstart) dstart = dend >> 7; - if (!dend) dend = dstart >> 7; - if ((dstart ^ dend) < 0) return false; - int delta = dend - dstart; - return ((delta > -SMPLOOP_ACCURACY) && (delta < SMPLOOP_ACCURACY)); -} - - -bool MPT_BidiEndCheck(int spos0, int spos1, int spos2) -{ - int delta0 = spos1 - spos0; - int delta1 = spos2 - spos1; - int delta2 = spos2 - spos0; - if (!delta0) delta0 = delta1 >> 7; - if (!delta1) delta1 = delta0 >> 7; - if ((delta1 ^ delta0) < 0) return false; - return ((delta0 >= -1) && (delta0 <= 0) && (delta1 >= -1) && (delta1 <= 0) && (delta2 >= -1) && (delta2 <= 0)); -} - - -bool MPT_BidiStartCheck(int spos0, int spos1, int spos2) -{ - int delta1 = spos1 - spos0; - int delta0 = spos2 - spos1; - int delta2 = spos2 - spos0; - if (!delta0) delta0 = delta1 >> 7; - if (!delta1) delta1 = delta0 >> 7; - if ((delta1 ^ delta0) < 0) return false; - return ((delta0 >= -1) && (delta0 <= 0) && (delta1 > -1) && (delta1 <= 0) && (delta2 >= -1) && (delta2 <= 0)); -} - - - void CCtrlSamples::OnVScroll(UINT nCode, UINT, CScrollBar *scrollBar) { - TCHAR s[256]; + TCHAR s[32]; if(IsLocked()) return; ModSample &sample = m_sndFile.GetSample(m_nSample); - const uint8 *pSample = mpt::byte_cast<const uint8 *>(sample.sampleb()); - const uint32 inc = sample.GetBytesPerSample(); - SmpLength i; - int pos; + const bool moveLoop = CMainFrame::GetInputHandler()->CtrlPressed(); bool redraw = false; static CScrollBar *lastScrollbar = nullptr; LockControls(); - if ((!sample.nLength) || (!pSample)) goto NoSample; - if (sample.uFlags[CHN_16BIT]) - { - pSample++; - } // Loop Start - if ((pos = m_SpinLoopStart.GetPos32()) != 0 && sample.nLoopEnd > 0) + if(int pos = m_SpinLoopStart.GetPos32(); pos != 0 && sample.nLoopEnd > 0 && sample.HasSampleData()) { - bool bOk = false; - const uint8 *p = pSample + sample.nLoopStart * inc; - int find0 = (int)pSample[sample.nLoopEnd*inc-inc]; - int find1 = (int)pSample[sample.nLoopEnd*inc]; - // Find Next LoopStart Point - if (pos > 0) - { - for (i = sample.nLoopStart + 1; i + 16 < sample.nLoopEnd; i++) - { - p += inc; - bOk = sample.uFlags[CHN_PINGPONGLOOP] ? MPT_BidiStartCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; - } - } else - // Find Prev LoopStart Point + if(SmpLength i = SampleEdit::FindLoopStart(sample, false, pos > 0, moveLoop); i < sample.nLength) { - for (i = sample.nLoopStart; i; ) + if(!m_startedEdit && lastScrollbar != scrollBar) + PrepareUndo(moveLoop ? "Move Loop" : "Set Loop Start"); + if(moveLoop) { - i--; - p -= inc; - bOk = sample.uFlags[CHN_PINGPONGLOOP] ? MPT_BidiStartCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; + sample.nLoopEnd = i + (sample.nLoopEnd - sample.nLoopStart); + wsprintf(s, _T("%u"), sample.nLoopEnd); + m_EditLoopEnd.SetWindowText(s); } - } - if (bOk) - { - if(!m_startedEdit && lastScrollbar != scrollBar) PrepareUndo("Set Loop Start"); sample.nLoopStart = i; wsprintf(s, _T("%u"), sample.nLoopStart); m_EditLoopStart.SetWindowText(s); @@ -3040,34 +2970,18 @@ m_SpinLoopStart.SetPos(0); } // Loop End - if ((pos = m_SpinLoopEnd.GetPos32()) != 0) + if(int pos = m_SpinLoopEnd.GetPos32(); pos != 0 && sample.HasSampleData()) { - bool bOk = false; - const uint8 *p = pSample + sample.nLoopEnd * inc; - int find0 = (int)pSample[sample.nLoopStart*inc]; - int find1 = (int)pSample[sample.nLoopStart*inc+inc]; - // Find Next LoopEnd Point - if (pos > 0) - { - for (i = sample.nLoopEnd + 1; i <= sample.nLength; i++, p += inc) - { - bOk = sample.uFlags[CHN_PINGPONGLOOP] ? MPT_BidiEndCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; - } - } else - // Find Prev LoopEnd Point + if(SmpLength i = SampleEdit::FindLoopEnd(sample, false, pos > 0, moveLoop); i > 0) { - for (i = sample.nLoopEnd; i > sample.nLoopStart + 16; ) + if(!m_startedEdit && lastScrollbar != scrollBar) + PrepareUndo(moveLoop ? "Move Loop" : "Set Loop End"); + if(moveLoop) { - i--; - p -= inc; - bOk = sample.uFlags[CHN_PINGPONGLOOP] ? MPT_BidiEndCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; + sample.nLoopStart = i - (sample.nLoopEnd - sample.nLoopStart); + wsprintf(s, _T("%u"), sample.nLoopStart); + m_EditLoopStart.SetWindowText(s); } - } - if (bOk) - { - if(!m_startedEdit && lastScrollbar != scrollBar) PrepareUndo("Set Loop End"); sample.nLoopEnd = i; wsprintf(s, _T("%u"), sample.nLoopEnd); m_EditLoopEnd.SetWindowText(s); @@ -3077,35 +2991,18 @@ m_SpinLoopEnd.SetPos(0); } // Sustain Loop Start - if ((pos = m_SpinSustainStart.GetPos32()) != 0 && sample.nSustainEnd > 0) + if(int pos = m_SpinSustainStart.GetPos32(); pos != 0 && sample.nSustainEnd > 0 && sample.HasSampleData()) { - bool bOk = false; - const uint8 *p = pSample + sample.nSustainStart * inc; - int find0 = (int)pSample[sample.nSustainEnd*inc-inc]; - int find1 = (int)pSample[sample.nSustainEnd*inc]; - // Find Next Sustain LoopStart Point - if (pos > 0) - { - for (i = sample.nSustainStart + 1; i + 16 < sample.nSustainEnd; i++) - { - p += inc; - bOk = sample.uFlags[CHN_PINGPONGSUSTAIN] ? MPT_BidiStartCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; - } - } else - // Find Prev Sustain LoopStart Point + if(SmpLength i = SampleEdit::FindLoopStart(sample, true, pos > 0, moveLoop); i < sample.nLength) { - for (i = sample.nSustainStart; i; ) + if(!m_startedEdit && lastScrollbar != scrollBar) + PrepareUndo(moveLoop ? "Move Sustain Loop" : "Set Sustain Loop Start"); + if(moveLoop) { - i--; - p -= inc; - bOk = sample.uFlags[CHN_PINGPONGSUSTAIN] ? MPT_BidiStartCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; + sample.nSustainEnd = i + (sample.nSustainEnd - sample.nSustainStart); + wsprintf(s, _T("%u"), sample.nSustainEnd); + m_EditSustainEnd.SetWindowText(s); } - } - if (bOk) - { - if(!m_startedEdit && lastScrollbar != scrollBar) PrepareUndo("Set Sustain Loop Start"); sample.nSustainStart = i; wsprintf(s, _T("%u"), sample.nSustainStart); m_EditSustainStart.SetWindowText(s); @@ -3115,34 +3012,18 @@ m_SpinSustainStart.SetPos(0); } // Sustain Loop End - if ((pos = m_SpinSustainEnd.GetPos32()) != 0) + if(int pos = m_SpinSustainEnd.GetPos32(); pos != 0 && sample.HasSampleData()) { - bool bOk = false; - const uint8 *p = pSample + sample.nSustainEnd * inc; - int find0 = (int)pSample[sample.nSustainStart*inc]; - int find1 = (int)pSample[sample.nSustainStart*inc+inc]; - // Find Next LoopEnd Point - if (pos > 0) - { - for (i = sample.nSustainEnd + 1; i + 1 < sample.nLength; i++, p += inc) - { - bOk = sample.uFlags[CHN_PINGPONGSUSTAIN] ? MPT_BidiEndCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; - } - } else - // Find Prev LoopEnd Point + if(SmpLength i = SampleEdit::FindLoopEnd(sample, true, pos > 0, moveLoop); i > 0) { - for (i = sample.nSustainEnd; i > sample.nSustainStart + 16; ) + if(!m_startedEdit && lastScrollbar != scrollBar) + PrepareUndo(moveLoop ? "Move Sustain Loop" : "Set Sustain Loop End"); + if(moveLoop) { - i--; - p -= inc; - bOk = sample.uFlags[CHN_PINGPONGSUSTAIN] ? MPT_BidiEndCheck(p[0], p[inc], p[inc*2]) : MPT_LoopCheck(find0, find1, p[0], p[inc]); - if (bOk) break; + sample.nSustainStart = i - (sample.nSustainEnd - sample.nSustainStart); + wsprintf(s, _T("%u"), sample.nSustainStart); + m_EditSustainStart.SetWindowText(s); } - } - if (bOk) - { - if(!m_startedEdit && lastScrollbar != scrollBar) PrepareUndo("Set Sustain Loop End"); sample.nSustainEnd = i; wsprintf(s, _T("%u"), sample.nSustainEnd); m_EditSustainEnd.SetWindowText(s); @@ -3151,9 +3032,8 @@ } m_SpinSustainEnd.SetPos(0); } -NoSample: // FineTune / C-5 Speed - if ((pos = m_SpinFineTune.GetPos32()) != 0) + if(int pos = m_SpinFineTune.GetPos32(); pos != 0) { if(!m_startedEdit && lastScrollbar != scrollBar) PrepareUndo("Finetune"); @@ -3366,8 +3246,7 @@ CSampleXFadeDlg dlg(this, sample); if(dlg.DoModal() == IDOK) { - const SmpLength loopStart = dlg.m_useSustainLoop ? sample.nSustainStart: sample.nLoopStart; - const SmpLength loopEnd = dlg.m_useSustainLoop ? sample.nSustainEnd: sample.nLoopEnd; + const auto [loopStart, loopEnd] = dlg.m_useSustainLoop ? sample.GetSustainLoop() : sample.GetLoop(); const SmpLength maxSamples = std::min({ sample.nLength, loopStart, loopEnd / 2 }); SmpLength fadeSamples = dlg.PercentToSamples(dlg.m_fadeLength); LimitMax(fadeSamples, maxSamples); Modified: branches/OpenMPT-1.31/mptrack/View_smp.cpp ============================================================================== --- branches/OpenMPT-1.31/mptrack/View_smp.cpp Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/mptrack/View_smp.cpp Sat Dec 21 20:26:11 2024 (r22594) @@ -1857,9 +1857,11 @@ m_startDragValue = ScreenToSample(point.x); } + const bool moveLoop = (flags & MK_CONTROL); bool update = false; SmpLength *updateLoopPoint = nullptr; const char *updateLoopDesc = nullptr; + SmpLength loopLength = 0; switch(m_dragItem) { case HitTestItem::SelectionStart: @@ -1872,28 +1874,50 @@ } break; case HitTestItem::LoopStart: - if(x < sample.nLoopEnd) + if(moveLoop) + { + updateLoopPoint = &sample.nLoopStart; + updateLoopDesc = "Move Loop"; + loopLength = sample.nLoopEnd - sample.nLoopStart; + } else if(x < sample.nLoopEnd) { updateLoopPoint = &sample.nLoopStart; updateLoopDesc = "Set Loop Start"; } break; case HitTestItem::LoopEnd: - if(x > sample.nLoopStart) + if(moveLoop) + { + updateLoopPoint = &sample.nLoopStart; + updateLoopDesc = "Move Loop"; + loopLength = sample.nLoopEnd - sample.nLoopStart; + x = (x > loopLength) ? x - loopLength : 0; + } else if(x > sample.nLoopStart) { updateLoopPoint = &sample.nLoopEnd; updateLoopDesc = "Set Loop End"; } break; case HitTestItem::SustainStart: - if(x < sample.nSustainEnd) + if(moveLoop) + { + updateLoopPoint = &sample.nSustainStart; + updateLoopDesc = "Move Sustain Loop"; + loopLength = sample.nSustainEnd - sample.nSustainStart; + } else if(x < sample.nSustainEnd) { updateLoopPoint = &sample.nSustainStart; updateLoopDesc = "Set Sustain Start"; } break; case HitTestItem::SustainEnd: - if(x > sample.nSustainStart) + if(moveLoop) + { + updateLoopPoint = &sample.nSustainStart; + updateLoopDesc = "Move Loop"; + loopLength = sample.nSustainEnd - sample.nSustainStart; + x = (x > loopLength) ? x - loopLength : 0; + } else if(x > sample.nSustainStart) { updateLoopPoint = &sample.nSustainEnd; updateLoopDesc = "Set Sustain End"; @@ -1909,6 +1933,9 @@ break; } + if(loopLength) + LimitMax(x, sample.nLength - loopLength); + if(updateLoopPoint && updateLoopDesc && *updateLoopPoint != x) { if(!m_dragPreparedUndo) @@ -1916,6 +1943,10 @@ m_dragPreparedUndo = true; update = true; *updateLoopPoint = x; + if(loopLength && updateLoopPoint == &sample.nLoopStart) + sample.nLoopEnd = sample.nLoopStart + loopLength; + else if(loopLength && updateLoopPoint == &sample.nSustainStart) + sample.nSustainEnd = sample.nSustainStart + loopLength; sample.PrecomputeLoops(sndFile, true); SetModified(SampleHint().Info(), true, false); } @@ -2050,7 +2081,7 @@ } else { // ctrl + click = play from cursor pos - if(flags & MK_CONTROL) + if((flags & MK_CONTROL) && point.y >= m_timelineHeight) PlayNote(NOTE_MIDDLEC, ScreenToSample(point.x)); } } Modified: branches/OpenMPT-1.31/soundlib/Load_mo3.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_mo3.cpp Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/soundlib/Load_mo3.cpp Sat Dec 21 20:26:11 2024 (r22594) @@ -1016,7 +1016,7 @@ CMD_PORTAMENTOUP, CMD_TREMOR, CMD_RETRIG, CMD_FINEVIBRATO, CMD_CHANNELVOLUME, CMD_CHANNELVOLSLIDE, CMD_PANNINGSLIDE, CMD_S3MCMDEX, CMD_TEMPO, CMD_GLOBALVOLSLIDE, CMD_PANBRELLO, CMD_MIDI, - CMD_NONE,/*FineVolSld*/ CMD_NONE,/*PortaDown*/ CMD_NONE, /*PortaUp*/ CMD_NONE, + CMD_NONE,/*FineVolSld*/ CMD_NONE,/*PortaDown*/ CMD_NONE, /*PortaUp*/ CMD_DUMMY, CMD_NONE,/*ITVolCol*/ CMD_XPARAM, CMD_SMOOTHMIDI, CMD_DELAYCUT, CMD_FINETUNE, CMD_FINETUNE_SMOOTH, }; Modified: branches/OpenMPT-1.31/soundlib/ModSample.h ============================================================================== --- branches/OpenMPT-1.31/soundlib/ModSample.h Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/soundlib/ModSample.h Sat Dec 21 20:26:11 2024 (r22594) @@ -144,6 +144,10 @@ void SetLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile); // Set sustain loop points and update loop wrap-around buffer void SetSustainLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile); + // Retrieve the normal loop points + std::pair<SmpLength, SmpLength> GetLoop() const noexcept { return std::make_pair(nLoopStart, nLoopEnd); } + // Retrieve the sustain loop points + std::pair<SmpLength, SmpLength> GetSustainLoop() const noexcept { return std::make_pair(nSustainStart, nSustainEnd); } // Update loop wrap-around buffer void PrecomputeLoops(CSoundFile &sndFile, bool updateChannels = true); Modified: branches/OpenMPT-1.31/soundlib/modsmp_ctrl.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/modsmp_ctrl.cpp Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/soundlib/modsmp_ctrl.cpp Sat Dec 21 20:26:11 2024 (r22594) @@ -177,8 +177,7 @@ bool XFadeSample(ModSample &smp, SmpLength fadeLength, int fadeLaw, bool afterloopFade, bool useSustainLoop, CSoundFile &sndFile) { if(!smp.HasSampleData()) return false; - const SmpLength loopStart = useSustainLoop ? smp.nSustainStart : smp.nLoopStart; - const SmpLength loopEnd = useSustainLoop ? smp.nSustainEnd : smp.nLoopEnd; + const auto [loopStart, loopEnd] = useSustainLoop ? smp.GetSustainLoop() : smp.GetLoop(); if(loopEnd <= loopStart || loopEnd > smp.nLength) return false; if(loopStart < fadeLength) return false; Modified: branches/OpenMPT-1.31/tracklib/SampleEdit.cpp ============================================================================== --- branches/OpenMPT-1.31/tracklib/SampleEdit.cpp Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/tracklib/SampleEdit.cpp Sat Dec 21 20:26:11 2024 (r22594) @@ -796,8 +796,7 @@ || (!smp.HasPingPongSustainLoop() && sustainLoop)) return false; - const SmpLength loopStart = sustainLoop ? smp.nSustainStart : smp.nLoopStart; - const SmpLength loopEnd = sustainLoop ? smp.nSustainEnd : smp.nLoopEnd; + const auto [loopStart, loopEnd] = sustainLoop ? smp.GetSustainLoop(): smp.GetLoop(); const SmpLength oldLoopLength = loopEnd - loopStart; const SmpLength oldLength = smp.nLength; @@ -1056,6 +1055,184 @@ return newSelEnd; } + +static constexpr int SMPLOOP_ACCURACY = 7; // 5% + +static bool LoopCheck(int sstart0, int sstart1, int send0, int send1) +{ + int dse0 = send0 - sstart0; + if((dse0 < -SMPLOOP_ACCURACY) || (dse0 > SMPLOOP_ACCURACY)) + return false; + int dse1 = send1 - sstart1; + if((dse1 < -SMPLOOP_ACCURACY) || (dse1 > SMPLOOP_ACCURACY)) + return false; + int dstart = sstart1 - sstart0; + int dend = send1 - send0; + if(!dstart) + dstart = dend >> 7; + if(!dend) + dend = dstart >> 7; + if((dstart ^ dend) < 0) + return false; + int delta = dend - dstart; + return ((delta > -SMPLOOP_ACCURACY) && (delta < SMPLOOP_ACCURACY)); +} + + +static bool BidiEndCheck(int spos0, int spos1, int spos2) +{ + int delta0 = spos1 - spos0; + int delta1 = spos2 - spos1; + int delta2 = spos2 - spos0; + if(!delta0) + delta0 = delta1 >> 7; + if(!delta1) + delta1 = delta0 >> 7; + if((delta1 ^ delta0) < 0) + return false; + return ((delta0 >= -1) && (delta0 <= 0) && (delta1 >= -1) && (delta1 <= 0) && (delta2 >= -1) && (delta2 <= 0)); +} + + +static bool BidiStartCheck(int spos0, int spos1, int spos2) +{ + int delta1 = spos1 - spos0; + int delta0 = spos2 - spos1; + int delta2 = spos2 - spos0; + if(!delta0) + delta0 = delta1 >> 7; + if(!delta1) + delta1 = delta0 >> 7; + if((delta1 ^ delta0) < 0) + return false; + return ((delta0 >= -1) && (delta0 <= 0) && (delta1 > -1) && (delta1 <= 0) && (delta2 >= -1) && (delta2 <= 0)); +} + + +SmpLength FindLoopStart(const ModSample &sample, bool sustainLoop, bool goForward, bool moveLoop) +{ + const uint8 *pSample = mpt::byte_cast<const uint8 *>(sample.sampleb()); + if(sample.uFlags[CHN_16BIT] && mpt::endian_is_little()) + pSample++; + const uint32 inc = sample.GetBytesPerSample(); + const auto [loopStart, loopEnd] = sustainLoop ? sample.GetSustainLoop() : sample.GetLoop(); + const SmpLength loopLength = loopEnd - loopStart; + const bool pingpong = sample.uFlags[sustainLoop ? CHN_PINGPONGSUSTAIN : CHN_PINGPONGLOOP]; + + const uint8 *p = pSample + loopStart * inc; + int find0 = static_cast<int>(pSample[loopEnd * inc - inc]); + int find1 = static_cast<int>(pSample[loopEnd * inc]); + if(goForward) + { + // Find Next LoopStart Point + const SmpLength searchEnd = moveLoop ? sample.nLength - loopLength : (std::max(loopEnd, SmpLength(16)) - 16); + for(SmpLength i = sample.nLoopStart + 1; i <= searchEnd; i++) + { + p += inc; + if(pingpong) + { + if(BidiStartCheck(p[0], p[inc], p[inc * 2])) + return i; + } else + { + if(moveLoop) + { + find0 = static_cast<int>(pSample[(i + loopLength - 1) * inc]); + find1 = static_cast<int>(pSample[(i + loopLength) * inc]); + } + if(LoopCheck(find0, find1, p[0], p[inc])) + return i; + } + } + } else + { + // Find Prev LoopStart Point + for(SmpLength i = sample.nLoopStart; i;) + { + i--; + p -= inc; + if(pingpong) + { + if(BidiStartCheck(p[0], p[inc], p[inc * 2])) + return i; + } else + { + if(moveLoop) + { + find0 = static_cast<int>(pSample[(i + loopLength - 1) * inc]); + find1 = static_cast<int>(pSample[(i + loopLength) * inc]); + } + if(LoopCheck(find0, find1, p[0], p[inc])) + return i; + } + } + } + return sample.nLength; +} + + +SmpLength FindLoopEnd(const ModSample &sample, bool sustainLoop, bool goForward, bool moveLoop) +{ + const uint8 *pSample = mpt::byte_cast<const uint8 *>(sample.sampleb()); + if(sample.uFlags[CHN_16BIT] && mpt::endian_is_little()) + pSample++; + const uint32 inc = sample.GetBytesPerSample(); + const auto [loopStart, loopEnd] = sustainLoop ? sample.GetSustainLoop() : sample.GetLoop(); + const SmpLength loopLength = loopEnd - loopStart; + const bool pingpong = sample.uFlags[sustainLoop ? CHN_PINGPONGSUSTAIN : CHN_PINGPONGLOOP]; + + const uint8 *p = pSample + loopEnd * inc; + int find0 = static_cast<int>(pSample[loopStart * inc]); + int find1 = static_cast<int>(pSample[loopStart * inc + inc]); + if(goForward) + { + // Find Next LoopEnd Point + for(SmpLength i = loopEnd + 1; i <= sample.nLength; i++) + { + p += inc; + if(pingpong) + { + if(BidiEndCheck(p[0], p[inc], p[inc * 2])) + return i; + } else + { + if(moveLoop) + { + find0 = static_cast<int>(pSample[(i - loopLength) * inc]); + find1 = static_cast<int>(pSample[(i - loopLength + 1) * inc]); + } + if(LoopCheck(find0, find1, p[0], p[inc])) + return i; + } + } + } else + { + // Find Prev LoopEnd Point + const SmpLength searchEnd = moveLoop ? loopLength : (loopStart + 16); + for(SmpLength i = loopEnd; i > searchEnd;) + { + i--; + p -= inc; + if(pingpong) + { + if(BidiEndCheck(p[0], p[inc], p[inc * 2])) + return i; + } else + { + if(moveLoop) + { + find0 = static_cast<int>(pSample[(i - loopLength) * inc]); + find1 = static_cast<int>(pSample[(i - loopLength + 1) * inc]); + } + if(LoopCheck(find0, find1, p[0], p[inc])) + return i; + } + } + } + return 0; +} + + } // namespace SampleEdit OPENMPT_NAMESPACE_END Modified: branches/OpenMPT-1.31/tracklib/SampleEdit.h ============================================================================== --- branches/OpenMPT-1.31/tracklib/SampleEdit.h Sat Dec 21 17:35:48 2024 (r22593) +++ branches/OpenMPT-1.31/tracklib/SampleEdit.h Sat Dec 21 20:26:11 2024 (r22594) @@ -98,6 +98,15 @@ // 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); +// Find a suitable loop start going either forward or backward from the current loop start. +// If moveLoop is true, the calculations are done assuming that the loop length stays the same (i.e. the loop end is moved by the same amount). +// Returns a valid loop start less than the sample length if it was successful. +SmpLength FindLoopStart(const ModSample &sample, bool sustainLoop, bool goForward, bool moveLoop); +// Find a suitable loop end going either forward or backward from the current loop end. +// If moveLoop is true, the calculations are done assuming that the loop length stays the same (i.e. the loop start is moved by the same amount). +// Returns a valid loop end greater than 0 if it was successful. +SmpLength FindLoopEnd(const ModSample &sample, bool sustainLoop, bool goForward, bool moveLoop); + } // namespace SampleEdit OPENMPT_NAMESPACE_END |