1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-04-30 07:39:42 +02:00

Bugs 2558 2559: After clip left/right, selection start can be wrong

Problem:
In DoClipMove() in ClipMenus.cpp, there are a couple of problems in the code for the adjustment of the new value t0 due to potential rounding errors:
1. The code uses the start and end of intervals, and these values are not updated after the move.
2. It's assumed that the same correction is valid for all track types.

Fix:
Implement an adjustment which depends on track type, and does not use the start and end values of intervals.
This commit is contained in:
David Bailes 2020-10-07 13:27:09 +01:00
parent 22dbe0a17a
commit cce2c7b883
5 changed files with 49 additions and 14 deletions

View File

@ -662,24 +662,18 @@ double DoClipMove( AudacityProject &project, Track *track,
auto hSlideAmount = state.DoSlideHorizontal( desiredSlideAmount );
// update t0 and t1. There is the possibility that the updated
// t0 may no longer be within the clip due to rounding errors,
// so t0 is adjusted so that it is.
double newT0 = t0 + hSlideAmount;
if (hitTestResult != TrackShifter::HitTestResult::Track) {
// pShifter is still undestroyed in the ClipMoveState
auto &intervals = pShifter->MovingIntervals();
if ( !intervals.empty() ) {
auto &interval = intervals[0];
if (newT0 < interval.Start())
newT0 = interval.Start();
if (newT0 > interval.End())
newT0 = interval.End();
double diff = selectedRegion.duration();
selectedRegion.setTimes(newT0, newT0 + diff);
}
// If necessary, correct for rounding errors. For example,
// for a wavetrack, ensure that t0 is still in the clip
// which it was within before the move.
// (pShifter is still undestroyed in the ClipMoveState.)
newT0 = pShifter->AdjustT0(newT0);
}
double diff = selectedRegion.duration();
selectedRegion.setTimes(newT0, newT0 + diff);
return hSlideAmount;
};
return 0.0;

View File

@ -36,6 +36,19 @@ public:
bool SyncLocks() override { return true; }
// Ensure that t0 is still within the data.
// This corrects for any rounding errors.
double AdjustT0(double t0) const override
{
auto& track = GetTrack();
if (t0 < track.GetStartTime())
t0 = track.GetStartTime();
if (t0 > track.GetEndTime())
t0 = track.GetEndTime();
return t0;
}
private:
std::shared_ptr<NoteTrack> mpTrack;
};

View File

@ -161,6 +161,24 @@ public:
data->GetClip()->Offset( offset );
}
}
// Ensure that t0 is still within the clip which it was in before the move.
// This corrects for any rounding errors.
double AdjustT0( double t0 ) const override
{
if (MovingIntervals().empty())
return t0;
else {
auto data = static_cast<WaveTrack::IntervalData*>(MovingIntervals()[0].Extra());
auto& clip = data->GetClip();
if (t0 < clip->GetStartTime())
t0 = clip->GetStartTime();
if (t0 > clip->GetEndTime())
t0 = clip->GetEndTime();
}
return t0;
}
private:
std::shared_ptr<WaveTrack> mpTrack;

View File

@ -227,6 +227,11 @@ void TrackShifter::DoHorizontalOffset( double offset )
GetTrack().Offset( offset );
}
double TrackShifter::AdjustT0(double t0) const
{
return t0;
}
void TrackShifter::InitIntervals()
{
mMoving.clear();

View File

@ -143,6 +143,11 @@ public:
//! Default moves the whole track, provided `!AllFixed()`; else does nothing
virtual void DoHorizontalOffset( double offset );
// This function is used by the keyboard interface for time shifting.
// It adjusts t0 after the move to take into account
// any rounding errors if this is necessary.
virtual double AdjustT0(double t0) const;
protected:
/*! Unfix any of the intervals that intersect the given one; may be useful to override `SelectInterval()` */
void CommonSelectInterval( const TrackInterval &interval );