SmpLength InsertSilence(ModSample &smp, const SmpLength nSilenceLength, const SmpLength nStartFrom, CSoundFile &sndFile) //---------------------------------------------------------------------------------------------------------------------- { if(nSilenceLength == 0 || nSilenceLength > MAX_SAMPLE_LENGTH || smp.nLength > MAX_SAMPLE_LENGTH - nSilenceLength || nStartFrom > smp.nLength) return smp.nLength; const bool wasEmpty = smp.nLength == 0 || smp.pSample == nullptr; const SmpLength newLength = smp.nLength + nSilenceLength; char *pNewSmp = nullptr; pNewSmp = static_cast<char *>(ModSample::AllocateSample(newLength, smp.GetBytesPerSample())); if(pNewSmp == nullptr) return smp.nLength; //Sample allocation failed. if(!wasEmpty) { // Copy over old sample const SmpLength silenceOffset = nStartFrom * smp.GetBytesPerSample(); const SmpLength silenceBytes = nSilenceLength * smp.GetBytesPerSample(); if(nStartFrom > 0) { memcpy(pNewSmp, smp.pSample, silenceOffset); } if(nStartFrom < smp.nLength) { memcpy(pNewSmp + silenceOffset + silenceBytes, static_cast<const char *>(smp.pSample) + silenceOffset, smp.GetSampleSizeInBytes() - silenceOffset); } // Update loop points if necessary. if(smp.nLoopStart >= nStartFrom) smp.nLoopStart += nSilenceLength; if(smp.nLoopEnd >= nStartFrom) smp.nLoopEnd += nSilenceLength; } else { // Set loop points automatically smp.nLoopStart = 0; smp.nLoopEnd = newLength; smp.uFlags.set(CHN_LOOP); } ReplaceSample(smp, pNewSmp, newLength, sndFile); PrecomputeLoops(smp, sndFile, true); return smp.nLength; }
SmpLength ResizeSample(ModSample &smp, const SmpLength nNewLength, CSoundFile &sndFile) //------------------------------------------------------------------------------------- { // Invalid sample size if(nNewLength > MAX_SAMPLE_LENGTH || nNewLength == smp.nLength) return smp.nLength; // New sample will be bigger so we'll just use "InsertSilence" as it's already there. if(nNewLength > smp.nLength) return InsertSilence(smp, nNewLength - smp.nLength, smp.nLength, sndFile); // Else: Shrink sample const SmpLength nNewSmpBytes = nNewLength * smp.GetBytesPerSample(); void *pNewSmp = ModSample::AllocateSample(nNewLength, smp.GetBytesPerSample()); if(pNewSmp == nullptr) return smp.nLength; //Sample allocation failed. // Copy over old data and replace sample by the new one memcpy(pNewSmp, smp.pSample, nNewSmpBytes); ReplaceSample(smp, pNewSmp, nNewLength, sndFile); // Adjust loops if(smp.nLoopStart > nNewLength) { smp.nLoopStart = smp.nLoopEnd = 0; smp.uFlags.reset(CHN_LOOP); } if(smp.nLoopEnd > nNewLength) smp.nLoopEnd = nNewLength; if(smp.nSustainStart > nNewLength) { smp.nSustainStart = smp.nSustainEnd = 0; smp.uFlags.reset(CHN_SUSTAINLOOP); } if(smp.nSustainEnd > nNewLength) smp.nSustainEnd = nNewLength; PrecomputeLoops(smp, sndFile); return smp.nLength; }