diff --git a/src/Menus.cpp b/src/Menus.cpp index e0b23c4d6..fa1829805 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -6606,9 +6606,8 @@ AudacityProject::FoundClipBoundary AudacityProject::FindNextClipBoundary(const W return clip->GetEndTime() > timeEnd; }); if (pStart != clips.end() && pEnd != clips.end()) { - if ((*pStart)->GetStartSample() == (*pEnd)->GetEndSample()) { - // boundary between two clips which are immediately next to each other. Tested for - // using samples rather than times because of rounding errors + if ((*pEnd)->SharesBoundaryWithNextClip(*pStart)) { + // boundary between two clips which are immediately next to each other. result.nFound = 2; result.time = (*pEnd)->GetEndTime(); result.index1 = std::distance(clips.begin(), pEnd); @@ -6653,9 +6652,8 @@ AudacityProject::FoundClipBoundary AudacityProject::FindPrevClipBoundary(const W return clip->GetEndTime() < timeEnd; }); if (pStart != clips.rend() && pEnd != clips.rend()) { - if ((*pStart)->GetStartSample() == (*pEnd)->GetEndSample()) { - // boundary between two clips which are immediately next to each other. Tested for - // using samples rather than times because of rounding errors + if ((*pEnd)->SharesBoundaryWithNextClip(*pStart)) { + // boundary between two clips which are immediately next to each other. result.nFound = 2; result.time = (*pStart)->GetStartTime(); result.index1 = static_cast(clips.size()) - 1 - std::distance(clips.rbegin(), pStart); @@ -6697,7 +6695,7 @@ double AudacityProject::AdjustForFindingStartTimes(const std::vectorGetEndTime() == time; }); if (q != clips.end() && q + 1 != clips.end() && - (*q)->GetEndSample() == (*(q+1))->GetStartSample()) { + (*q)->SharesBoundaryWithNextClip(*(q+1))) { time = (*(q+1))->GetStartTime(); } @@ -6715,7 +6713,7 @@ double AudacityProject::AdjustForFindingEndTimes(const std::vectorGetStartTime() == time; }); if (q != clips.end() && q != clips.begin() && - (*(q - 1))->GetEndSample() == (*q)->GetStartSample()) { + (*(q - 1))->SharesBoundaryWithNextClip(*q)) { time = (*(q-1))->GetEndTime(); } diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index aea155503..71ce8d494 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -1948,3 +1948,17 @@ void WaveClip::Resample(int rate, ProgressDialog *progress) mRate = rate; } } + +// Used by commands which interact with clips using the keyboard. +// When two clips are immediately next to each other, the GetEndTime() +// of the first clip and the GetStartTime() of the second clip may not +// be exactly equal due to rounding errors. +bool WaveClip::SharesBoundaryWithNextClip(const WaveClip* next) const +{ + double endThis = GetRate() * GetOffset() + GetNumSamples().as_double(); + double startNext = next->GetRate() * next->GetOffset(); + + // given that a double has about 15 significant digits, using a criterion + // of half a sample should be safe in all normal usage. + return fabs(startNext - endThis) < 0.5; +} diff --git a/src/WaveClip.h b/src/WaveClip.h index 0438b34d8..a4a9d41a2 100644 --- a/src/WaveClip.h +++ b/src/WaveClip.h @@ -378,6 +378,9 @@ public: bool GetIsPlaceholder() const { return mIsPlaceholder; } void SetIsPlaceholder(bool val) { mIsPlaceholder = val; } + // used by commands which interact with clips using the keyboard + bool SharesBoundaryWithNextClip(const WaveClip* next) const; + public: // Cache of values to colour pixels of Spectrogram - used by TrackArtist mutable std::unique_ptr mSpecPxCache; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index edbd46f5d..f56e56ef0 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -2228,7 +2228,7 @@ WaveClip* WaveTrack::GetClipAtTime(double time) // second clip is found by the above code. So correct this. if (p != clips.rend() & p != clips.rbegin() && time == (*p)->GetEndTime() && - (*p)->GetEndSample() == (*(p-1))->GetStartSample()) { + (*p)->SharesBoundaryWithNextClip(*(p-1))) { p--; }