diff --git a/libraries/lib-builtin-effects/AutoDuckBase.cpp b/libraries/lib-builtin-effects/AutoDuckBase.cpp index 138416bed..2fcd0e485 100644 --- a/libraries/lib-builtin-effects/AutoDuckBase.cpp +++ b/libraries/lib-builtin-effects/AutoDuckBase.cpp @@ -379,7 +379,7 @@ bool AutoDuckBase::ApplyDuckFade( buf[(i - pos).as_size_t()] *= DB_TO_LINEAR(gain); } - if (!track.SetFloats(buf.get(), pos, len)) + if (!track.SetFloats(buf.get(), pos, len, widestSampleFormat, pos + len >= end)) { cancel = true; break; diff --git a/libraries/lib-builtin-effects/ClickRemovalBase.cpp b/libraries/lib-builtin-effects/ClickRemovalBase.cpp index 8a78314f5..9c91742c1 100644 --- a/libraries/lib-builtin-effects/ClickRemovalBase.cpp +++ b/libraries/lib-builtin-effects/ClickRemovalBase.cpp @@ -167,7 +167,7 @@ bool ClickRemovalBase::ProcessOne( if (mbDidSomething) { // RemoveClicks() actually did something. - if (!track.SetFloats(buffer.get(), start + s, block)) + if (!track.SetFloats(buffer.get(), start + s, block, widestSampleFormat, (len - (s + block)) <= windowSize / 2)) { bResult = false; break; diff --git a/libraries/lib-builtin-effects/NormalizeBase.cpp b/libraries/lib-builtin-effects/NormalizeBase.cpp index 69409716b..21a92d650 100644 --- a/libraries/lib-builtin-effects/NormalizeBase.cpp +++ b/libraries/lib-builtin-effects/NormalizeBase.cpp @@ -340,7 +340,7 @@ bool NormalizeBase::ProcessOne( ProcessData(buffer.get(), block, offset); // Copy the newly-changed samples back onto the track. - if (!track.SetFloats(buffer.get(), s, block)) + if (!track.SetFloats(buffer.get(), s, block, widestSampleFormat, s >= end)) { rc = false; break; diff --git a/libraries/lib-builtin-effects/TwoPassSimpleMono.cpp b/libraries/lib-builtin-effects/TwoPassSimpleMono.cpp index ba5fd985f..a4f0abf34 100644 --- a/libraries/lib-builtin-effects/TwoPassSimpleMono.cpp +++ b/libraries/lib-builtin-effects/TwoPassSimpleMono.cpp @@ -176,7 +176,7 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveChannel &track, // onto the track. if (mSecondPassDisabled || mPass != 0) { if (!outTrack.SetFloats(buffer1.get(), s - samples1, - samples1)) + samples1, widestSampleFormat, s + samples2 >= end)) return false; } else @@ -218,7 +218,7 @@ bool EffectTwoPassSimpleMono::ProcessOne(WaveChannel &track, // onto the track. if (mSecondPassDisabled || mPass != 0) { if (!outTrack.SetFloats(buffer1.get(), s - samples1, - samples1)) + samples1, widestSampleFormat, s >= end)) return false; } else diff --git a/libraries/lib-wave-track/Sequence.cpp b/libraries/lib-wave-track/Sequence.cpp index e23b0c2ab..0b86926ae 100644 --- a/libraries/lib-wave-track/Sequence.cpp +++ b/libraries/lib-wave-track/Sequence.cpp @@ -458,7 +458,9 @@ std::unique_ptr Sequence::Copy( const SampleBlockFactoryPtr &pFactory, // Increase ref count or duplicate file } +#if defined(_DEBUG) dest->ConsistencyCheck(wxT("Sequence::Copy()")); +#endif return dest; } @@ -600,7 +602,9 @@ void Sequence::Paste(sampleCount s, const Sequence *src) // This consistency check won't throw, it asserts. // Proof that we kept consistency is not hard. - ConsistencyCheck(wxT("Paste branch two"), false); +#if defined(_DEBUG) + ConsistencyCheck(wxT("Paste branch two")); +#endif mSampleFormats.UpdateEffective(src->mSampleFormats.Effective()); return; } @@ -1635,9 +1639,11 @@ void Sequence::Delete(sampleCount start, sampleCount len) mNumSamples -= len; +#if defined(_DEBUG) // This consistency check won't throw, it asserts. // Proof that we kept consistency is not hard. - ConsistencyCheck(wxT("Delete - branch one"), false); + ConsistencyCheck(wxT("Delete - branch one")); +#endif return; } @@ -1745,15 +1751,15 @@ void Sequence::Delete(sampleCount start, sampleCount len) (newBlock, mNumSamples - len, wxT("Delete - branch two")); } -void Sequence::ConsistencyCheck(const wxChar *whereStr, bool mayThrow) const +#if defined(_DEBUG) +void Sequence::ConsistencyCheck(const wxChar *whereStr) const { - ConsistencyCheck(mBlock, mMaxSamples, 0, mNumSamples, whereStr, mayThrow); + ConsistencyCheck(mBlock, mMaxSamples, 0, mNumSamples, whereStr); } void Sequence::ConsistencyCheck (const BlockArray &mBlock, size_t maxSamples, size_t from, - sampleCount mNumSamples, const wxChar *whereStr, - bool WXUNUSED(mayThrow)) + sampleCount mNumSamples, const wxChar *whereStr) { // Construction of the exception at the appropriate line of the function // gives a little more discrimination @@ -1794,17 +1800,17 @@ void Sequence::ConsistencyCheck wxT("Recommended course of action:\n") wxT("Undo the failed operation(s), then export or save your work and quit.")); - //if (mayThrow) - //throw *ex; - //else - wxASSERT(false); + wxASSERT(false); } } +#endif void Sequence::CommitChangesIfConsistent (BlockArray &newBlock, sampleCount numSamples, const wxChar *whereStr) { +#if defined(_DEBUG) ConsistencyCheck( newBlock, mMaxSamples, 0, numSamples, whereStr ); // may throw +#endif // now commit // use No-fail-guarantee @@ -1848,9 +1854,11 @@ void Sequence::AppendBlocksIfConsistent std::copy( additionalBlocks.begin(), additionalBlocks.end(), std::back_inserter( mBlock ) ); +#if defined(_DEBUG) // Check consistency only of the blocks that were added, // avoiding quadratic time for repeated checking of repeating appends ConsistencyCheck( mBlock, mMaxSamples, prevSize, numSamples, whereStr ); // may throw +#endif // now commit // use No-fail-guarantee diff --git a/libraries/lib-wave-track/Sequence.h b/libraries/lib-wave-track/Sequence.h index f5239f804..2ceeb9c2c 100644 --- a/libraries/lib-wave-track/Sequence.h +++ b/libraries/lib-wave-track/Sequence.h @@ -308,10 +308,12 @@ class WAVE_TRACK_API Sequence final : public XMLTagHandler{ static bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, size_t blockRelativeStart, size_t len, bool mayThrow); - + +#if defined(_DEBUG) // This function throws if the track is messed up // because of inconsistent block starts & lengths - void ConsistencyCheck (const wxChar *whereStr, bool mayThrow = true) const; + void ConsistencyCheck (const wxChar *whereStr) const; +#endif // This function prints information to stdout about the blocks in the // tracks and indicates if there are inconsistencies. @@ -319,10 +321,11 @@ class WAVE_TRACK_API Sequence final : public XMLTagHandler{ (const BlockArray &block, sampleCount numSamples, wxString *dest); private: +#if defined(_DEBUG) static void ConsistencyCheck (const BlockArray &block, size_t maxSamples, size_t from, - sampleCount numSamples, const wxChar *whereStr, - bool mayThrow = true); + sampleCount numSamples, const wxChar *whereStr); +#endif // The next two are used in methods that give a strong guarantee. // They either throw because final consistency check fails, or swap the diff --git a/libraries/lib-wave-track/WaveChannelUtilities.h b/libraries/lib-wave-track/WaveChannelUtilities.h index 39b5ebe98..be24e94b9 100644 --- a/libraries/lib-wave-track/WaveChannelUtilities.h +++ b/libraries/lib-wave-track/WaveChannelUtilities.h @@ -163,14 +163,6 @@ WAVE_TRACK_API void SetFloatsFromTime(WaveChannel &channel, double t, const float* buffer, size_t numSamples, sampleFormat effectiveFormat, PlaybackDirection direction); -/*! - @copydoc SetFloatsFromTime(WaveChannel &, double, const float *, size_t, - sampleFormat, PlaybackDirection) - */ -WAVE_TRACK_API void SetFloatsFromTime(Clip &channel, - double t, const float* buffer, size_t numSamples, - sampleFormat effectiveFormat, PlaybackDirection direction); - /*! @brief Similar to GetNextClip, but returns `nullptr` if the neighbour clip is not adjacent. diff --git a/libraries/lib-wave-track/WaveClip.cpp b/libraries/lib-wave-track/WaveClip.cpp index bb9a0926e..fc61f318c 100644 --- a/libraries/lib-wave-track/WaveClip.cpp +++ b/libraries/lib-wave-track/WaveClip.cpp @@ -169,10 +169,10 @@ sampleCount WaveClipChannel::GetPlayEndSample() const } void WaveClipChannel::SetSamples(constSamplePtr buffer, sampleFormat format, - sampleCount start, size_t len, sampleFormat effectiveFormat) + sampleCount start, size_t len, sampleFormat effectiveFormat, bool end) { return GetClip().SetSamples(miChannel, - buffer, format, start, len, effectiveFormat); + buffer, format, start, len, effectiveFormat, end); } void WaveClipChannel::WriteXML(XMLWriter &xmlFile) const @@ -395,7 +395,7 @@ bool WaveClip::GetSamples(samplePtr buffers[], sampleFormat format, void WaveClip::SetSamples(size_t ii, constSamplePtr buffer, sampleFormat format, - sampleCount start, size_t len, sampleFormat effectiveFormat) + sampleCount start, size_t len, sampleFormat effectiveFormat, bool end) { assert(ii < NChannels()); // use Strong-guarantee @@ -403,7 +403,8 @@ void WaveClip::SetSamples(size_t ii, start + TimeToSamples(mTrimLeft), len, effectiveFormat); // use No-fail-guarantee - MarkChanged(); + if (end) + MarkChanged(); } void WaveClip::SetEnvelope(std::unique_ptr p) diff --git a/libraries/lib-wave-track/WaveClip.h b/libraries/lib-wave-track/WaveClip.h index 28baab286..16cd354a0 100644 --- a/libraries/lib-wave-track/WaveClip.h +++ b/libraries/lib-wave-track/WaveClip.h @@ -169,6 +169,7 @@ class WAVE_TRACK_API WaveClipChannel If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur. */ + , bool end = true ); void WriteXML(XMLWriter &xmlFile) const; @@ -553,6 +554,7 @@ class WAVE_TRACK_API WaveClip final : If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur. */ + , bool end = true ); //! @} diff --git a/libraries/lib-wave-track/WaveTrack.cpp b/libraries/lib-wave-track/WaveTrack.cpp index 943fed3da..236971072 100644 --- a/libraries/lib-wave-track/WaveTrack.cpp +++ b/libraries/lib-wave-track/WaveTrack.cpp @@ -1551,7 +1551,7 @@ bool WaveTrack::ReplaceTrackData( { const auto len = limitSampleBufferSize(GetMaxBlockSize(), end - pos); src.DoGet(0, channels, buffersCast, floatSample, seek, len, false); - if (!track.SetFloats(buffers, pos, len)) + if (!track.SetFloats(buffers, pos, len, widestSampleFormat, pos + len >= end)) retval = false; seek += len; pos += len; @@ -2852,7 +2852,7 @@ WaveChannel::GetSampleView(double t0, double t1, bool mayThrow) const /*! @excsafety{Weak} */ bool WaveChannel::Set(constSamplePtr buffer, sampleFormat format, - sampleCount start, size_t len, sampleFormat effectiveFormat) + sampleCount start, size_t len, sampleFormat effectiveFormat, bool end) { for (const auto &clip: Intervals()) { @@ -2889,7 +2889,7 @@ bool WaveChannel::Set(constSamplePtr buffer, sampleFormat format, clip->SetSamples( buffer + startDelta.as_size_t() * SAMPLE_SIZE(format), - format, inclipDelta, samplesToCopy.as_size_t(), effectiveFormat ); + format, inclipDelta, samplesToCopy.as_size_t(), effectiveFormat, end ); } } return true; @@ -3341,14 +3341,14 @@ void WaveTrack::Resample(int rate, BasicUI::ProgressDialog *progress) } bool WaveTrack::SetFloats(const float *const *buffers, - sampleCount start, size_t len, sampleFormat effectiveFormat) + sampleCount start, size_t len, sampleFormat effectiveFormat, bool end) { bool result = true; size_t ii = 0; for (const auto &pChannel : Channels()) { const auto buffer = buffers[ii++]; assert(buffer); // precondition - result = pChannel->SetFloats(buffer, start, len, effectiveFormat) + result = pChannel->SetFloats(buffer, start, len, effectiveFormat, end) && result; } return result; diff --git a/libraries/lib-wave-track/WaveTrack.h b/libraries/lib-wave-track/WaveTrack.h index f43178ded..8b44df933 100644 --- a/libraries/lib-wave-track/WaveTrack.h +++ b/libraries/lib-wave-track/WaveTrack.h @@ -156,6 +156,7 @@ class WAVE_TRACK_API WaveChannel final If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur. */ + , bool end = true ); //! Random-access assignment of a range of samples @@ -167,10 +168,11 @@ class WAVE_TRACK_API WaveChannel final If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur. */ + , bool end = true ) { return Set(reinterpret_cast(buffer), floatSample, - start, len, effectiveFormat); + start, len, effectiveFormat, end); } bool AppendBuffer(constSamplePtr buffer, sampleFormat format, size_t len, unsigned stride, sampleFormat effectiveFormat); @@ -659,6 +661,7 @@ class WAVE_TRACK_API WaveTrack final If the data are later narrowed from stored format, but not narrower than the effective, then no dithering will occur. */ + , bool end = true ); const TypeInfo &GetTypeInfo() const override; diff --git a/libraries/lib-wave-track/WaveTrackUtilities.cpp b/libraries/lib-wave-track/WaveTrackUtilities.cpp index 170697f3a..4c22990d6 100644 --- a/libraries/lib-wave-track/WaveTrackUtilities.cpp +++ b/libraries/lib-wave-track/WaveTrackUtilities.cpp @@ -101,14 +101,14 @@ bool ReverseOneClip(WaveTrack &track, track.GetFloats(0, width, pointers1, second, block); reverseBuffers(pointers1, block); // Don't dither on later rendering if only reversing samples + len -= 2 * block; const bool success = - track.SetFloats(pointers1, first, block, narrowestSampleFormat) + track.SetFloats(pointers1, first, block, narrowestSampleFormat, len <= 1) && - track.SetFloats(pointers0, second, block, narrowestSampleFormat); + track.SetFloats(pointers0, second, block, narrowestSampleFormat, len <= 1); if (!success) return false; - len -= 2 * block; first += block; if (!report(