Audacity 3.2.0
TimeTrack.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TimeTrack.cpp
6
7 Dr William Bland
8
9*******************************************************************//*******************************************************************/
15
16
17#include "TimeTrack.h"
18
19#include <cfloat>
20#include <wx/wxcrtvararg.h>
21#include "Envelope.h"
22#include "Mix.h"
23#include "Project.h"
24#include "ProjectRate.h"
25
26
27//TODO-MB: are these sensible values?
28#define TIMETRACK_MIN 0.01
29#define TIMETRACK_MAX 10.0
30
32 "timetrack",
34};
35
37{
38 return _("Time Track");
39}
40
42{
43 auto &tracks = TrackList::Get( project );
44 auto result = tracks.Add(std::make_shared<TimeTrack>());
45 result->AttachedTrackObjects::BuildAll();
46 return result;
47}
48
50{
51 CleanState();
52}
53
55{
56 mEnvelope = std::make_unique<BoundedEnvelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
57
58 SetRangeLower( 0.2 );
59 SetRangeUpper( 2.0 );
60 mDisplayLog = false;
61
62 mEnvelope->SetTrackLen(DBL_MAX);
63 mEnvelope->SetOffset(0);
64
65 //Time track is always unique
67}
68
70 const std::optional<double>& oldTempo, double newTempo)
71{
72 assert(IsLeader());
73 if (!oldTempo.has_value())
74 return;
75 const auto ratio = *oldTempo / newTempo;
76 mEnvelope->RescaleTimesBy(ratio);
77}
78
80 double *pT0, double *pT1
81) : UniqueChannelTrack{ orig, std::move(a) }
82{
83 Init(orig); // this copies the TimeTrack metadata (name, range, etc)
84
85 auto len = DBL_MAX;
86 if (pT0 && pT1) {
87 len = *pT1 - *pT0;
88 mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope, *pT0, *pT1 );
89 }
90 else
91 mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope );
92
95
96 mEnvelope->SetTrackLen( len );
97 mEnvelope->SetOffset(0);
98}
99
100// Copy the track metadata but not the contents.
101void TimeTrack::Init(const TimeTrack &orig)
102{
103 Track::Init(orig);
104 SetName(orig.GetName());
106}
107
109{
110}
111
113{
114 return mEnvelope->GetRangeLower();
115}
116
118{
119 return mEnvelope->GetRangeUpper();
120}
121
122void TimeTrack::SetRangeLower(double lower)
123{
124 mEnvelope->SetRangeLower( lower );
125}
126
127void TimeTrack::SetRangeUpper(double upper)
128{
129 mEnvelope->SetRangeUpper( upper );
130}
131
133{
134 static const Track::TypeInfo info{
135 { "time", "time", XO("Time Track") }, true, &Track::ClassTypeInfo() };
136 return info;
137}
138
139auto TimeTrack::GetTypeInfo() const -> const TypeInfo &
140{
141 return typeInfo();
142}
143
145{
146 return typeInfo();
147}
148
150{
151 return false;
152}
153
155 const
156{
157 assert(IsLeader());
158 // Maintain uniqueness of the time track!
159 std::shared_ptr<TimeTrack> pNewTrack;
160 if (auto pTrack = *TrackList::Get(project).Any<TimeTrack>().begin())
161 // leave list unchanged
162 pNewTrack = pTrack->SharedPointer<TimeTrack>();
163 else {
164 pNewTrack = std::make_shared<TimeTrack>();
165 list.Add(pNewTrack);
166 }
167
168 // Should come here only for .aup3 import, not for paste (because the
169 // track is skipped in cut/copy commands)
170 // And for import we agree to replace the track contents completely
171 pNewTrack->CleanState();
172 pNewTrack->Init(*this);
173 pNewTrack->Paste(0.0, *this);
174 pNewTrack->SetRangeLower(this->GetRangeLower());
175 pNewTrack->SetRangeUpper(this->GetRangeUpper());
176 return pNewTrack;
177}
178
179TrackListHolder TimeTrack::Cut(double t0, double t1)
180{
181 assert(IsLeader());
182 auto result = Copy(t0, t1, false);
183 Clear(t0, t1);
184 return result;
185}
186
187TrackListHolder TimeTrack::Copy(double t0, double t1, bool) const
188{
189 auto track =
190 std::make_shared<TimeTrack>(*this, ProtectedCreationArg{}, &t0, &t1);
191 track->Init(*this);
192 return TrackList::Temporary(nullptr, track, nullptr);
193}
194
195namespace {
196double GetRate(const Track &track) {
197 if (auto pList = track.GetOwner()) {
198 if (auto pProject = pList->GetOwner())
199 return ProjectRate::Get(*pProject).GetRate();
200 }
201 return 44100.0;
202}
203}
204
205void TimeTrack::Clear(double t0, double t1)
206{
207 assert(IsLeader());
208 auto sampleTime = 1.0 / GetRate(*this);
209 mEnvelope->CollapseRegion( t0, t1, sampleTime );
210}
211
212void TimeTrack::Paste(double t, const Track &src)
213{
214 bool bOk = src.TypeSwitch<bool>([&](const TimeTrack &tt) {
215 auto sampleTime = 1.0 / GetRate(*this);
216 mEnvelope->PasteEnvelope(t, tt.mEnvelope.get(), sampleTime);
217 return true;
218 });
219
220 if (!bOk)
221 // THROW_INCONSISTENCY_EXCEPTION // ?
222 (void)0;// intentionally do nothing.
223}
224
226 double WXUNUSED(t0), double WXUNUSED(t1), ProgressReporter)
227{
228 assert(IsLeader());
229}
230
231void TimeTrack::InsertSilence(double t, double len)
232{
233 assert(IsLeader());
234 mEnvelope->InsertSpace(t, len);
235}
236
238{
239 assert(IsLeader());
240 auto result = std::make_shared<TimeTrack>(*this, ProtectedCreationArg{});
241 result->Init(*this);
242 return TrackList::Temporary(nullptr, result, nullptr);
243}
244
246{
247 return mEnvelope->GetExponential();
248}
249
250void TimeTrack::SetInterpolateLog(bool interpolateLog) {
251 mEnvelope->SetExponential(interpolateLog);
252}
253
254bool TimeTrack::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
255{
256 if (tag == "timetrack") {
257 mRescaleXMLValues = true; // will be set to false if upper/lower is found
258
259 long nValue;
260
261 for (auto pair : attrs)
262 {
263 auto attr = pair.first;
264 auto value = pair.second;
265
266 if (this->Track::HandleCommonXMLAttribute(attr, value))
267 ;
268 else if (attr == "rangelower")
269 {
270 SetRangeLower( value.Get(GetRangeLower()) );
271 mRescaleXMLValues = false;
272 }
273 else if (attr == "rangeupper")
274 {
275 SetRangeUpper( value.Get(GetRangeUpper()) );
276 mRescaleXMLValues = false;
277 }
278 else if (attr == "displaylog" && value.TryGet(nValue))
279 {
280 SetDisplayLog(nValue != 0);
281 //TODO-MB: This causes a graphical glitch, TrackPanel should probably be Refresh()ed after loading.
282 // I don't know where to do this though.
283 }
284 else if (attr == "interpolatelog" && value.TryGet(nValue))
285 {
286 SetInterpolateLog(nValue != 0);
287 }
288
289 } // while
291 mEnvelope->SetRange(0.0, 1.0); // this will be restored to the actual range later
292 return true;
293 }
294
295 return false;
296}
297
298void TimeTrack::HandleXMLEndTag(const std::string_view& WXUNUSED(tag))
299{
301 {
302 mRescaleXMLValues = false;
303 mEnvelope->RescaleValues(GetRangeLower(), GetRangeUpper());
305 }
306}
307
308XMLTagHandler *TimeTrack::HandleXMLChild(const std::string_view& tag)
309{
310 if (tag == "envelope")
311 return mEnvelope.get();
312
313 return NULL;
314}
315
316void TimeTrack::WriteXML(XMLWriter &xmlFile) const
317// may throw
318{
319 assert(IsLeader());
320 xmlFile.StartTag(wxT("timetrack"));
321 this->Track::WriteCommonXMLAttributes( xmlFile );
322
323 //xmlFile.WriteAttr(wxT("channel"), mChannel);
324 //xmlFile.WriteAttr(wxT("offset"), mOffset, 8);
325 xmlFile.WriteAttr(wxT("rangelower"), GetRangeLower(), 12);
326 xmlFile.WriteAttr(wxT("rangeupper"), GetRangeUpper(), 12);
327 xmlFile.WriteAttr(wxT("displaylog"), GetDisplayLog());
328 xmlFile.WriteAttr(wxT("interpolatelog"), GetInterpolateLog());
329
330 mEnvelope->WriteXML(xmlFile);
331
332 xmlFile.EndTag(wxT("timetrack"));
333}
334
336{
337 return 0;
338}
339
340std::shared_ptr<WideChannelGroupInterval>
342{
343 return {};
344}
345
347{
348 GetEnvelope()->Flatten(0.0);
349 GetEnvelope()->InsertOrReplace(0.0, 0.2);
350 GetEnvelope()->InsertOrReplace(5.0 - 0.001, 0.2);
351 GetEnvelope()->InsertOrReplace(5.0 + 0.001, 1.3);
352 GetEnvelope()->InsertOrReplace(10.0, 1.3);
353
354 double value1 = GetEnvelope()->Integral(2.0, 13.0);
355 double expected1 = (5.0 - 2.0) * 0.2 + (13.0 - 5.0) * 1.3;
356 double value2 = GetEnvelope()->IntegralOfInverse(2.0, 13.0);
357 double expected2 = (5.0 - 2.0) / 0.2 + (13.0 - 5.0) / 1.3;
358 if( fabs(value1 - expected1) > 0.01 )
359 {
360 wxPrintf( "TimeTrack: Integral failed! expected %f got %f\n", expected1, value1);
361 }
362 if( fabs(value2 - expected2) > 0.01 )
363 {
364 wxPrintf( "TimeTrack: IntegralOfInverse failed! expected %f got %f\n", expected2, value2);
365 }
366
367 /*double reqt0 = 10.0 - .1;
368 double reqt1 = 10.0 + .1;
369 double t0 = warp( reqt0 );
370 double t1 = warp( reqt1 );
371 if( t0 > t1 )
372 {
373 wxPrintf( "TimeTrack: Warping reverses an interval! [%.2f,%.2f] -> [%.2f,%.2f]\n",
374 reqt0, reqt1,
375 t0, t1 );
376 }*/
377}
378
381[](const AudacityProject *pProject) -> const BoundedEnvelope*
382{
383 if (pProject) {
384 auto &list = TrackList::Get(*pProject);
385 if (auto pTimeTrack = *list.Any<const TimeTrack>().begin())
386 return pTimeTrack->GetEnvelope();
387 }
388 return nullptr;
389} };
wxT("CloseDown"))
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
an object holding per-project preferred sample rate
const auto tracks
const auto project
static Mixer::WarpOptions::DefaultWarp::Scope installer
Installer of the time warper.
Definition: TimeTrack.cpp:380
static ProjectFileIORegistry::ObjectReaderEntry readerEntry
Definition: TimeTrack.cpp:31
#define TIMETRACK_MAX
Definition: TimeTrack.cpp:29
#define TIMETRACK_MIN
Definition: TimeTrack.cpp:28
static const Track::TypeInfo & typeInfo()
Definition: TimeTrack.cpp:132
std::function< void(double)> ProgressReporter
Definition: Track.h:53
std::shared_ptr< TrackList > TrackListHolder
Definition: Track.h:42
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
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 Integral(double t0, double t1) const
Definition: Envelope.cpp:1180
int InsertOrReplace(double when, double value)
Add a point at a particular absolute time coordinate.
Definition: Envelope.h:176
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1243
void Flatten(double value)
Definition: Envelope.cpp:138
typename GlobalVariable< DefaultWarp, const std::function< const BoundedEnvelope * >, nullptr, Options... >::Scope Scope
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:24
static wxString GetDefaultName()
Definition: TimeTrack.cpp:36
std::shared_ptr< WideChannelGroupInterval > DoGetInterval(size_t iInterval) override
Retrieve an interval.
Definition: TimeTrack.cpp:341
void WriteXML(XMLWriter &xmlFile) const override
Definition: TimeTrack.cpp:316
void SetInterpolateLog(bool interpolateLog)
Definition: TimeTrack.cpp:250
void HandleXMLEndTag(const std::string_view &tag) override
Definition: TimeTrack.cpp:298
void Paste(double t, const Track &src) override
Weak precondition allows overrides to replicate one channel into many.
Definition: TimeTrack.cpp:212
static const TypeInfo & ClassTypeInfo()
Definition: TimeTrack.cpp:144
Track::Holder PasteInto(AudacityProject &project, TrackList &list) const override
Definition: TimeTrack.cpp:154
bool mRescaleXMLValues
Definition: TimeTrack.h:114
void DoOnProjectTempoChange(const std::optional< double > &oldTempo, double newTempo) override
Definition: TimeTrack.cpp:69
void SetDisplayLog(bool displayLog)
Definition: TimeTrack.h:95
void Silence(double t0, double t1, ProgressReporter reportProgress={}) override
Definition: TimeTrack.cpp:225
std::unique_ptr< BoundedEnvelope > mEnvelope
Definition: TimeTrack.h:112
bool GetInterpolateLog() const
Definition: TimeTrack.cpp:245
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
Definition: TimeTrack.cpp:254
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: TimeTrack.cpp:308
void CleanState()
Definition: TimeTrack.cpp:54
TrackListHolder Clone() const override
Definition: TimeTrack.cpp:237
BoundedEnvelope * GetEnvelope()
Definition: TimeTrack.h:83
bool GetDisplayLog() const
Definition: TimeTrack.h:94
size_t NIntervals() const override
Report the number of intervals.
Definition: TimeTrack.cpp:335
void InsertSilence(double t, double len) override
Definition: TimeTrack.cpp:231
bool mDisplayLog
Definition: TimeTrack.h:113
void testMe()
Definition: TimeTrack.cpp:346
const TypeInfo & GetTypeInfo() const override
Definition: TimeTrack.cpp:139
void SetRangeLower(double lower)
Definition: TimeTrack.cpp:122
virtual ~TimeTrack()
Definition: TimeTrack.cpp:108
TrackListHolder Cut(double t0, double t1) override
Create tracks and modify this track.
Definition: TimeTrack.cpp:179
static TimeTrack * New(AudacityProject &project)
Definition: TimeTrack.cpp:41
TrackListHolder Copy(double t0, double t1, bool forClipboard) const override
Create new tracks and don't modify this track.
Definition: TimeTrack.cpp:187
double GetRangeLower() const
Definition: TimeTrack.cpp:112
double GetRangeUpper() const
Definition: TimeTrack.cpp:117
void Clear(double t0, double t1) override
Definition: TimeTrack.cpp:205
bool SupportsBasicEditing() const override
Whether this track type implements cut-copy-paste; by default, true.
Definition: TimeTrack.cpp:149
void Init(const TimeTrack &orig)
Copy the metadata from another track but not the points.
Definition: TimeTrack.cpp:101
void SetRangeUpper(double upper)
Definition: TimeTrack.cpp:127
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:122
static const TypeInfo & ClassTypeInfo()
Definition: Track.cpp:1206
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:254
R TypeSwitch(const Functions &...functions)
Definition: Track.h:418
bool IsLeader() const override
Definition: Track.cpp:291
std::shared_ptr< Track > Holder
Definition: Track.h:225
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
Definition: Track.cpp:1235
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:56
void Init(const Track &orig)
Definition: Track.cpp:50
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
Definition: Track.cpp:1219
void SetName(const wxString &n)
Definition: Track.cpp:61
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:975
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1183
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:347
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &left={}, const Track::Holder &right={})
Definition: Track.cpp:1418
Generates overrides of channel-related functions.
Definition: Track.h:490
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:25
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
double GetRate(const Track &track)
Definition: TimeTrack.cpp:196
STL namespace.
Empty argument passed to some public constructors.
Definition: Track.h:129