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