Audacity  3.0.3
WaveTrackShifter.cpp
Go to the documentation of this file.
1 
6 #include "../../../ui/TimeShiftHandle.h"
7 #include "ViewInfo.h"
8 #include "../../../../WaveClip.h"
9 #include "../../../../WaveTrack.h"
10 
11 class WaveTrackShifter final : public TrackShifter {
12 public:
14  : mpTrack{ track.SharedPointer<WaveTrack>() }
15  {
16  InitIntervals();
17  }
18  ~WaveTrackShifter() override {}
19  Track &GetTrack() const override { return *mpTrack; }
20 
22  double time, const ViewInfo &viewInfo, HitTestParams* ) override
23  {
24  auto pClip = [&]() {
25  auto ts = mpTrack->TimeToLongSamples(time);
26 
27  for (auto clip : mpTrack->GetClips())
28  {
29  const auto c0 = mpTrack->TimeToLongSamples(clip->GetPlayStartTime());
30  const auto c1 = mpTrack->TimeToLongSamples(clip->GetPlayEndTime());
31  if (ts >= c0 && ts < c1)
32  return clip;
33  }
34  return std::shared_ptr<WaveClip>{};
35  }();
36 
37  if (!pClip)
38  return HitTestResult::Miss;
39 
40  auto t0 = viewInfo.selectedRegion.t0();
41  auto t1 = viewInfo.selectedRegion.t1();
42  if ( mpTrack->IsSelected() && time >= t0 && time < t1 ) {
43  // Unfix maybe many intervals (at least one because of test above)
44  SelectInterval({t0, t1});
46  }
47 
48  // Select just one interval
49  UnfixIntervals( [&](const auto &interval){
50  return
51  static_cast<WaveTrack::IntervalData*>(interval.Extra())
52  ->GetClip() == pClip;
53  } );
54 
56  }
57 
58  void SelectInterval( const TrackInterval &interval ) override
59  {
60  UnfixIntervals( [&](auto &myInterval){
61  // Use a slightly different test from CommonSelectInterval, rounding times
62  // to exact samples according to the clip's rate
63  auto data =
64  static_cast<WaveTrack::IntervalData*>( myInterval.Extra() );
65  auto clip = data->GetClip().get();
66  const auto c0 = mpTrack->TimeToLongSamples(clip->GetPlayStartTime());
67  const auto c1 = mpTrack->TimeToLongSamples(clip->GetPlayEndTime());
68  return
69  mpTrack->TimeToLongSamples(interval.Start()) < c1 &&
70  mpTrack->TimeToLongSamples(interval.End()) >= c0;
71  });
72  }
73 
74  bool SyncLocks() override { return true; }
75 
76  bool MayMigrateTo(Track &other) override
77  {
79  }
80 
81  double HintOffsetLarger(double desiredOffset) override
82  {
83  // set it to a sample point, and minimum of 1 sample point
84  bool positive = (desiredOffset > 0);
85  if (!positive)
86  desiredOffset *= -1;
87  double nSamples = rint(mpTrack->GetRate() * desiredOffset);
88  nSamples = std::max(nSamples, 1.0);
89  desiredOffset = nSamples / mpTrack->GetRate();
90  if (!positive)
91  desiredOffset *= -1;
92  return desiredOffset;
93  }
94 
95  double QuantizeOffset( double desiredOffset ) override
96  {
97  const auto rate = mpTrack->GetRate();
98  // set it to a sample point
99  return rint(desiredOffset * rate) / rate;
100  }
101 
102  double AdjustOffsetSmaller(double desiredOffset) override
103  {
104  std::vector< WaveClip * > movingClips;
105  for ( auto &interval : MovingIntervals() ) {
106  auto data =
107  static_cast<WaveTrack::IntervalData*>( interval.Extra() );
108  movingClips.push_back(data->GetClip().get());
109  }
110  double newAmount = 0;
111  (void) mpTrack->CanOffsetClips(movingClips, desiredOffset, &newAmount);
112  return newAmount;
113  }
114 
115  Intervals Detach() override
116  {
117  for ( auto &interval: mMoving ) {
118  auto pData = static_cast<WaveTrack::IntervalData*>( interval.Extra() );
119  auto pClip = pData->GetClip().get();
120  // interval will still hold the clip, so ignore the return:
121  (void) mpTrack->RemoveAndReturnClip(pClip);
122  mMigrated.erase(pClip);
123  }
124  return std::move( mMoving );
125  }
126 
127  bool AdjustFit(
128  const Track &otherTrack, const Intervals &intervals,
129  double &desiredOffset, double tolerance) override
130  {
131  bool ok = true;
132  auto pOtherWaveTrack = static_cast<const WaveTrack*>(&otherTrack);
133  for ( auto &interval: intervals ) {
134  auto pData =
135  static_cast<WaveTrack::IntervalData*>( interval.Extra() );
136  auto pClip = pData->GetClip().get();
137  ok = pOtherWaveTrack->CanInsertClip(
138  pClip, desiredOffset, tolerance );
139  if( !ok )
140  break;
141  }
142  return ok;
143  }
144 
145  bool Attach( Intervals intervals ) override
146  {
147  for (auto &interval : intervals) {
148  auto pData = static_cast<WaveTrack::IntervalData*>( interval.Extra() );
149  auto pClip = pData->GetClip();
150  if ( !mpTrack->AddClip( pClip ) )
151  return false;
152  mMigrated.insert( pClip.get() );
153  mMoving.emplace_back( std::move( interval ) );
154  }
155  return true;
156  }
157 
158  bool FinishMigration() override
159  {
160  auto rate = mpTrack->GetRate();
161  for (auto pClip : mMigrated) {
162  // Now that user has dropped the clip into a different track,
163  // make sure the sample rate matches the destination track.
164  pClip->Resample(rate);
165  pClip->MarkChanged();
166  }
167  return true;
168  }
169 
170  void DoHorizontalOffset( double offset ) override
171  {
172  for ( auto &interval : MovingIntervals() ) {
173  auto data =
174  static_cast<WaveTrack::IntervalData*>( interval.Extra() );
175  data->GetClip()->Offset( offset );
176  }
177  }
178 
179 
180  // Ensure that t0 is still within the clip which it was in before the move.
181  // This corrects for any rounding errors.
182  double AdjustT0( double t0 ) const override
183  {
184  if (MovingIntervals().empty())
185  return t0;
186  else {
187  auto data = static_cast<WaveTrack::IntervalData*>(MovingIntervals()[0].Extra());
188  auto& clip = data->GetClip();
189  if (t0 < clip->GetPlayStartTime())
190  t0 = clip->GetPlayStartTime();
191  if (t0 > clip->GetPlayEndTime())
192  t0 = clip->GetPlayEndTime();
193  }
194  return t0;
195  }
196 
197 private:
198  std::shared_ptr<WaveTrack> mpTrack;
199 
200  // Clips that may require resampling
201  std::unordered_set<WaveClip *> mMigrated;
202 };
203 
206  return [](WaveTrack &track, AudacityProject&) {
207  return std::make_unique<WaveTrackShifter>(track);
208  };
209 }
WaveTrackShifter::AdjustFit
bool AdjustFit(const Track &otherTrack, const Intervals &intervals, double &desiredOffset, double tolerance) override
Test whether intervals can fit into another track, maybe adjusting the offset slightly.
Definition: WaveTrackShifter.cpp:127
WaveTrackShifter::GetTrack
Track & GetTrack() const override
There is always an associated track.
Definition: WaveTrackShifter.cpp:19
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:69
WaveTrackShifter::mMigrated
std::unordered_set< WaveClip * > mMigrated
Definition: WaveTrackShifter.cpp:201
WaveTrackShifter::QuantizeOffset
double QuantizeOffset(double desiredOffset) override
Given amount to shift by horizontally, do any preferred rounding, before placement constraint checks.
Definition: WaveTrackShifter.cpp:95
WaveTrackShifter::AdjustOffsetSmaller
double AdjustOffsetSmaller(double desiredOffset) override
Given amount to shift by horizontally, maybe adjust it toward zero to meet placement constraints.
Definition: WaveTrackShifter.cpp:102
ConstTrackInterval::End
double End() const
Definition: Track.h:207
ViewInfo
Definition: ViewInfo.h:202
Track::SharedPointer
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:291
DEFINE_ATTACHED_VIRTUAL_OVERRIDE
DEFINE_ATTACHED_VIRTUAL_OVERRIDE(MakeWaveTrackShifter)
Definition: WaveTrackShifter.cpp:205
WaveTrack::IntervalData
Definition: WaveTrack.h:562
TrackShifter::MovingIntervals
const Intervals & MovingIntervals() const
Return special intervals of the track that may move.
Definition: TimeShiftHandle.h:75
TrackShifter::HitTestResult::Miss
@ Miss
Don't shift anything.
TrackInterval
A start and an end time, and mutative access to optional extra information.
Definition: Track.h:219
NotifyingSelectedRegion::t1
double t1() const
Definition: ViewInfo.h:48
TrackShifter::CommonMayMigrateTo
bool CommonMayMigrateTo(Track &otherTrack)
Definition: TimeShiftHandle.cpp:187
WaveTrackShifter
Definition: WaveTrackShifter.cpp:11
TrackShifter
Abstract base class for policies to manipulate a track type with the Time Shift tool.
Definition: TimeShiftHandle.h:33
TrackShifter::HitTestResult::Selection
@ Selection
Shift chosen intervals of this track; may shift other tracks' intervals.
TrackShifter::HitTestResult
HitTestResult
Possibilities for HitTest on the clicked track.
Definition: TimeShiftHandle.h:44
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:229
WaveTrackShifter::HitTest
HitTestResult HitTest(double time, const ViewInfo &viewInfo, HitTestParams *) override
Decide how shift behaves, based on the track that is clicked in.
Definition: WaveTrackShifter.cpp:21
TrackShifter::mMoving
Intervals mMoving
Definition: TimeShiftHandle.h:175
WaveTrackShifter::HintOffsetLarger
double HintOffsetLarger(double desiredOffset) override
Given amount to shift by horizontally, maybe adjust it from zero to suggest minimum distance.
Definition: WaveTrackShifter.cpp:81
WaveTrackShifter::SelectInterval
void SelectInterval(const TrackInterval &interval) override
Notifies the shifter that a region is selected, so it may update its fixed and moving intervals.
Definition: WaveTrackShifter.cpp:58
TrackShifter::InitIntervals
void InitIntervals()
Derived class constructor can initialize all intervals reported by the track as fixed,...
Definition: TimeShiftHandle.cpp:250
WaveTrackShifter::mpTrack
std::shared_ptr< WaveTrack > mpTrack
Definition: WaveTrackShifter.cpp:198
ViewInfo.h
WaveTrackShifter::FinishMigration
bool FinishMigration() override
When dragging is done, do (once) the final steps of migration (which may be expensive)
Definition: WaveTrackShifter.cpp:158
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
TrackShifter::HitTestResult::Intervals
@ Intervals
Shift intervals only of selected track and sister channels.
WaveTrackShifter::Detach
Intervals Detach() override
Remove all moving intervals from the track, if possible.
Definition: WaveTrackShifter.cpp:115
WaveTrackShifter::MayMigrateTo
bool MayMigrateTo(Track &other) override
Whether intervals may migrate to the other track, not yet checking all placement constraints *‍/.
Definition: WaveTrackShifter.cpp:76
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
WaveTrackShifter::~WaveTrackShifter
~WaveTrackShifter() override
Definition: WaveTrackShifter.cpp:18
WaveTrack::IntervalData::GetClip
std::shared_ptr< const WaveClip > GetClip() const
Definition: WaveTrack.h:567
WaveTrackShifter::Attach
bool Attach(Intervals intervals) override
Put moving intervals into the track, which may have migrated from another.
Definition: WaveTrackShifter.cpp:145
AttachedVirtualFunction::Override
For defining overrides of the method.
Definition: AttachedVirtualFunction.h:184
NotifyingSelectedRegion::t0
double t0() const
Definition: ViewInfo.h:47
ConstTrackInterval::Start
double Start() const
Definition: Track.h:206
WaveTrackShifter::WaveTrackShifter
WaveTrackShifter(WaveTrack &track)
Definition: WaveTrackShifter.cpp:13
TrackShifter::UnfixIntervals
void UnfixIntervals(std::function< bool(const TrackInterval &) > pred)
Change intervals satisfying a predicate from fixed to moving.
Definition: TimeShiftHandle.cpp:133
WaveTrackShifter::DoHorizontalOffset
void DoHorizontalOffset(double offset) override
Definition: WaveTrackShifter.cpp:170
TrackShifter::Intervals
std::vector< TrackInterval > Intervals
Definition: TimeShiftHandle.h:69
WaveTrackShifter::AdjustT0
double AdjustT0(double t0) const override
Definition: WaveTrackShifter.cpp:182
TrackShifter::HitTestParams
Optional, more complete information for hit testing.
Definition: TimeShiftHandle.h:52
WaveTrackShifter::SyncLocks
bool SyncLocks() override
Whether unfixing of an interval should propagate to all overlapping intervals in the sync lock group.
Definition: WaveTrackShifter.cpp:74