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