From: <sv...@op...> - 2025-03-17 20:24:37
|
Author: sagamusix Date: Mon Mar 17 21:24:16 2025 New Revision: 23055 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=23055 Log: [Imp] Sample tab: Also copy sample loop and cue point information when copying sample selections (https://bugs.openmpt.org/view.php?id=1869) Modified: trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/soundlib/WAVTools.cpp trunk/OpenMPT/soundlib/WAVTools.h Modified: trunk/OpenMPT/mptrack/View_smp.cpp ============================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp Mon Mar 17 15:26:59 2025 (r23054) +++ trunk/OpenMPT/mptrack/View_smp.cpp Mon Mar 17 21:24:16 2025 (r23055) @@ -2556,21 +2556,18 @@ return; } - bool addLoopInfo = true; - size_t smpSize = sample.nLength; - size_t smpOffset = 0; + SmpLength rangeStart = 0, rangeEnd = sample.nLength; // First things first: Calculate sample size, taking partial selections into account. LimitMax(m_dwEndSel, sample.nLength); if(m_dwEndSel > m_dwBeginSel) { - smpSize = m_dwEndSel - m_dwBeginSel; - smpOffset = m_dwBeginSel; - addLoopInfo = false; + rangeStart = m_dwBeginSel; + rangeEnd = m_dwEndSel; } - smpSize *= sample.GetBytesPerSample(); - smpOffset *= sample.GetBytesPerSample(); + size_t smpSize = (rangeEnd - rangeStart) * sample.GetBytesPerSample(); + size_t smpOffset = rangeStart * sample.GetBytesPerSample(); // Ok, now calculate size of the resulting WAV file. size_t memSize = sizeof(RIFFHeader) // RIFF Header @@ -2582,15 +2579,12 @@ static_assert((MAX_SAMPLENAME % 2u) == 0); static_assert((MAX_SAMPLEFILENAME % 2u) == 0); - if(addLoopInfo) - { - // We want to store some loop metadata as well. - memSize += sizeof(RIFFChunk) + sizeof(WAVSampleInfoChunk) + 2 * sizeof(WAVSampleLoop); - // ...and cue points, too. - memSize += sizeof(RIFFChunk) + sizeof(uint32) + std::size(sample.cues) * sizeof(WAVCuePoint); - } + // We want to store some loop metadata as well. + memSize += sizeof(RIFFChunk) + sizeof(WAVSampleInfoChunk) + 2 * sizeof(WAVSampleLoop); + // ...and cue points, too. + memSize += sizeof(RIFFChunk) + sizeof(uint32) + std::size(sample.cues) * sizeof(WAVCuePoint); - ASSERT((memSize % 2u) == 0); + MPT_ASSERT((memSize % 2u) == 0); BeginWaitCursor(); Clipboard clipboard(CF_WAVE, memSize); @@ -2618,11 +2612,8 @@ } ff.SeekRelative(smpSize); - if(addLoopInfo) - { - file.WriteLoopInformation(sample); - file.WriteCueInformation(sample); - } + file.WriteLoopInformation(sample, rangeStart, rangeEnd); + file.WriteCueInformation(sample, rangeStart, rangeEnd); file.WriteExtraInformation(sample, sndFile.GetType(), sndFile.GetSampleName(m_nSample)); mpt::IO::Offset totalSize = file.Finalize(); Modified: trunk/OpenMPT/soundlib/WAVTools.cpp ============================================================================== --- trunk/OpenMPT/soundlib/WAVTools.cpp Mon Mar 17 15:26:59 2025 (r23054) +++ trunk/OpenMPT/soundlib/WAVTools.cpp Mon Mar 17 21:24:16 2025 (r23055) @@ -348,12 +348,17 @@ // Write a sample loop information chunk to the file. -void WAVSampleWriter::WriteLoopInformation(const ModSample &sample) +void WAVSampleWriter::WriteLoopInformation(const ModSample &sample, SmpLength rangeStart, SmpLength rangeEnd) { if(!sample.uFlags[CHN_LOOP | CHN_SUSTAINLOOP] && !ModCommand::IsNote(sample.rootNote)) { return; } + if(rangeEnd <= rangeStart) + { + rangeStart = 0; + rangeEnd = sample.nLength; + } StartChunk(RIFFChunk::idsmpl); WAVSampleInfoChunk info; @@ -367,16 +372,17 @@ info.ConvertToWAV(sampleRate, sample.rootNote); // Set up loops - WAVSampleLoop loops[2]; - Clear(loops); - if(sample.uFlags[CHN_SUSTAINLOOP]) + std::array<WAVSampleLoop, 2> loops{{}}; + const bool writeSustainLoop = sample.uFlags[CHN_SUSTAINLOOP] && sample.nSustainStart < rangeEnd && sample.nSustainEnd >= rangeStart; + const bool writeNormalLoop = sample.uFlags[CHN_LOOP] && sample.nLoopStart < rangeEnd && sample.nLoopEnd >= rangeStart; + if(writeSustainLoop) { - loops[info.numLoops++].ConvertToWAV(sample.nSustainStart, sample.nSustainEnd, sample.uFlags[CHN_PINGPONGSUSTAIN]); + loops[info.numLoops++].ConvertToWAV(std::max(sample.nSustainStart, rangeStart) - rangeStart, std::clamp(sample.nSustainEnd, rangeStart, rangeEnd) - rangeStart, sample.uFlags[CHN_PINGPONGSUSTAIN]); } - if(sample.uFlags[CHN_LOOP]) + if(writeNormalLoop) { - loops[info.numLoops++].ConvertToWAV(sample.nLoopStart, sample.nLoopEnd, sample.uFlags[CHN_PINGPONGLOOP]); - } else if(sample.uFlags[CHN_SUSTAINLOOP]) + loops[info.numLoops++].ConvertToWAV(std::max(sample.nLoopStart, rangeStart) - rangeStart, std::clamp(sample.nLoopEnd, rangeStart, rangeEnd) - rangeStart, sample.uFlags[CHN_PINGPONGLOOP]); + } else if(writeSustainLoop) { // Since there are no "loop types" to distinguish between sustain and normal loops, OpenMPT assumes // that the first loop is a sustain loop if there are two loops. If we only want a sustain loop, @@ -393,12 +399,18 @@ // Write a sample's cue points to the file. -void WAVSampleWriter::WriteCueInformation(const ModSample &sample) +void WAVSampleWriter::WriteCueInformation(const ModSample &sample, SmpLength rangeStart, SmpLength rangeEnd) { + if(rangeEnd <= rangeStart) + { + rangeStart = 0; + rangeEnd = sample.nLength; + } + uint32 numMarkers = 0; for(const auto cue : sample.cues) { - if(cue < sample.nLength) + if(mpt::is_in_range(cue, rangeStart, rangeEnd)) numMarkers++; } @@ -407,9 +419,9 @@ uint32 i = 0; for(const auto cue : sample.cues) { - if(cue < sample.nLength) + if(mpt::is_in_range(cue, rangeStart, rangeEnd)) { - WAVCuePoint cuePoint = ConvertToWAVCuePoint(i++, cue); + WAVCuePoint cuePoint = ConvertToWAVCuePoint(i++, cue - rangeStart); mpt::IO::Write(s, cuePoint); } } Modified: trunk/OpenMPT/soundlib/WAVTools.h ============================================================================== --- trunk/OpenMPT/soundlib/WAVTools.h Mon Mar 17 15:26:59 2025 (r23054) +++ trunk/OpenMPT/soundlib/WAVTools.h Mon Mar 17 21:24:16 2025 (r23055) @@ -227,9 +227,9 @@ public: // Write a sample loop information chunk to the file. - void WriteLoopInformation(const ModSample &sample); + void WriteLoopInformation(const ModSample &sample, SmpLength rangeStart = 0, SmpLength rangeEnd = 0); // Write a sample's cue points to the file. - void WriteCueInformation(const ModSample &sample); + void WriteCueInformation(const ModSample &sample, SmpLength rangeStart = 0, SmpLength rangeEnd = 0); // Write MPT's sample information chunk to the file. void WriteExtraInformation(const ModSample &sample, MODTYPE modType, const char *sampleName = nullptr); }; |