diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp b/Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp new file mode 100644 index 00000000..1f9b21d1 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/mptrack/SampleTrimmer.cpp @@ -0,0 +1,178 @@ +/* + * SampleTrimmer.cpp + * ----------------- + * Purpose: Automatic trimming of unused sample parts for module size optimization. + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" +#include <numeric> +#include "InputHandler.h" +#include "Mainfrm.h" +#include "Moddoc.h" +#include "ProgressDialog.h" +#include "../tracklib/SampleEdit.h" +#include "../soundlib/OPL.h" + +OPENMPT_NAMESPACE_BEGIN + +class CRenderProgressDlg : public CProgressDialog +{ + CSoundFile &m_SndFile; + + class DummyAudioTarget : public IAudioTarget + { + public: + void Process(mpt::audio_span_interleaved<MixSampleInt>) override { } + void Process(mpt::audio_span_interleaved<MixSampleFloat>) override { } + }; + +public: + std::vector<SmpLength> m_SamplePlayLengths; + + CRenderProgressDlg(CWnd *parent, CSoundFile &sndFile) + : CProgressDialog{parent} + , m_SndFile{sndFile} + { + m_SndFile.m_SamplePlayLengths = &m_SamplePlayLengths; + } + + ~CRenderProgressDlg() + { + m_SndFile.m_SamplePlayLengths = nullptr; + } + + void Run() override + { + // We're not interested in plugin rendering + std::bitset<MAX_MIXPLUGINS> plugMuteStatus; + for(PLUGINDEX i = 0; i < MAX_MIXPLUGINS; i++) + { + plugMuteStatus[i] = m_SndFile.m_MixPlugins[i].IsBypassed(); + m_SndFile.m_MixPlugins[i].SetBypass(true); + } + + m_SamplePlayLengths.assign(m_SndFile.GetNumSamples() + 1, 0); + + const auto origSequence = m_SndFile.Order.GetCurrentSequenceIndex(); + const auto origRepeatCount = m_SndFile.GetRepeatCount(); + auto opl = std::move(m_SndFile.m_opl); + m_SndFile.SetRepeatCount(0); + m_SndFile.m_bIsRendering = true; + + auto prevTime = timeGetTime(); + const auto subSongs = m_SndFile.GetAllSubSongs(); + SetRange(0, mpt::saturate_round<uint64>(std::accumulate(subSongs.begin(), subSongs.end(), 0.0, [](double acc, const auto& song) { return acc + song.duration; }) * m_SndFile.GetSampleRate())); + size_t totalSamples = 0; + for(size_t i = 0; i < subSongs.size() && !m_abort; i++) + { + SetWindowText(MPT_CFORMAT("Automatic Sample Trimmer - Song {} / {}")(i + 1, subSongs.size())); + + const auto &song = subSongs[i]; + m_SndFile.ResetPlayPos(); + m_SndFile.GetLength(eAdjust, GetLengthTarget(song.startOrder, song.startRow).StartPos(song.sequence, 0, 0)); + m_SndFile.m_SongFlags.reset(SONG_PLAY_FLAGS); + + size_t subsongSamples = 0; + DummyAudioTarget target; + while(!m_abort) + { + auto count = m_SndFile.Read(MIXBUFFERSIZE, target); + if(count == 0) + break; + + totalSamples += count; + subsongSamples += count; + + auto currentTime = timeGetTime(); + if(currentTime - prevTime >= 16) + { + prevTime = currentTime; + auto timeSec = subsongSamples / m_SndFile.GetSampleRate(); + SetText(MPT_CFORMAT("Analyzing... {}:{}:{}")(timeSec / 3600, mpt::cfmt::dec0<2>((timeSec / 60) % 60), mpt::cfmt::dec0<2>(timeSec % 60))); + SetProgress(totalSamples); + ProcessMessages(); + } + } + } + + // Reset globals to previous values + m_SndFile.Order.SetSequence(origSequence); + m_SndFile.SetRepeatCount(origRepeatCount); + m_SndFile.ResetPlayPos(); + m_SndFile.StopAllVsti(); + m_SndFile.m_bIsRendering = false; + m_SndFile.m_opl = std::move(opl); + + for(PLUGINDEX i = 0; i < MAX_MIXPLUGINS; i++) + { + m_SndFile.m_MixPlugins[i].SetBypass(plugMuteStatus[i]); + } + + EndDialog(IDOK); + } +}; + + +void CModDoc::OnShowSampleTrimmer() +{ + BypassInputHandler bih; + CMainFrame::GetMainFrame()->StopMod(this); + CRenderProgressDlg dlg(CMainFrame::GetMainFrame(), m_SndFile); + dlg.DoModal(); + SAMPLEINDEX numTrimmed = 0; + SmpLength numBytes = 0; + for(SAMPLEINDEX smp = 1; smp <= GetNumSamples(); smp++) + { + ModSample &sample = m_SndFile.GetSample(smp); + auto &newLength = dlg.m_SamplePlayLengths[smp]; + if(newLength == 0) + continue; + // Take interpolation look-ahead into account + if((!sample.uFlags[CHN_LOOP] || newLength != sample.nLoopEnd) + && (!sample.uFlags[CHN_SUSTAINLOOP] || newLength != sample.nSustainEnd)) + { + newLength = std::min(newLength + InterpolationMaxLookahead, sample.nLength); + } + if(sample.nLength > newLength) + { + numTrimmed++; + numBytes += (sample.nLength - newLength) * sample.GetBytesPerSample(); + } + } + if(numTrimmed == 0) + { + Reporting::Information(_T("No samples can be trimmed, because all samples are played in their full length.")); + return; + } + + mpt::ustring s = MPT_UFORMAT("{} sample{} can be trimmed, saving {} byte{}.")(numTrimmed, (numTrimmed == 1) ? U_("") : U_("s"), mpt::ufmt::dec(3, ',', numBytes), numBytes != 1 ? U_("s") : U_("")); + if(dlg.m_abort) + { + s += U_("\n\nWARNING: Only partial results are available, possibly causing used sample parts to be trimmed.\nContinue anyway?"); + } else + { + s += U_(" Continue?"); + } + if(Reporting::Confirm(s, false, dlg.m_abort) == cnfYes) + { + for(SAMPLEINDEX smp = 1; smp <= GetNumSamples(); smp++) + { + ModSample &sample = m_SndFile.GetSample(smp); + if(dlg.m_SamplePlayLengths[smp] != 0 && sample.nLength > dlg.m_SamplePlayLengths[smp]) + { + GetSampleUndo().PrepareUndo(smp, sundo_delete, "Automatic Sample Trimming", dlg.m_SamplePlayLengths[smp], sample.nLength); + SampleEdit::ResizeSample(sample, dlg.m_SamplePlayLengths[smp], m_SndFile); + sample.uFlags.set(SMP_MODIFIED); + } + } + + SetModified(); + UpdateAllViews(SampleHint().Data().Info()); + } +} + +OPENMPT_NAMESPACE_END |