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.9 );
59 SetRangeUpper( 1.1 );
60 mDisplayLog = false;
61
62 mEnvelope->SetTrackLen(DBL_MAX);
63 mEnvelope->SetOffset(0);
64
65 //Time track is always unique
67}
68
70 double *pT0, double *pT1
71) : Track(orig, std::move(a))
72{
73 Init(orig); // this copies the TimeTrack metadata (name, range, etc)
74
75 auto len = DBL_MAX;
76 if (pT0 && pT1) {
77 len = *pT1 - *pT0;
78 mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope, *pT0, *pT1 );
79 }
80 else
81 mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope );
82
85
86 mEnvelope->SetTrackLen( len );
87 mEnvelope->SetOffset(0);
88}
89
90// Copy the track metadata but not the contents.
91void TimeTrack::Init(const TimeTrack &orig)
92{
93 Track::Init(orig);
94 SetName(orig.GetName());
96}
97
99{
100}
101
103{
104 return mEnvelope->GetRangeLower();
105}
106
108{
109 return mEnvelope->GetRangeUpper();
110}
111
112void TimeTrack::SetRangeLower(double lower)
113{
114 mEnvelope->SetRangeLower( lower );
115}
116
117void TimeTrack::SetRangeUpper(double upper)
118{
119 mEnvelope->SetRangeUpper( upper );
120}
121
123{
124 static const Track::TypeInfo info{
125 { "time", "time", XO("Time Track") }, true, &Track::ClassTypeInfo() };
126 return info;
127}
128
129auto TimeTrack::GetTypeInfo() const -> const TypeInfo &
130{
131 return typeInfo();
132}
133
135{
136 return typeInfo();
137}
138
140{
141 return false;
142}
143
145{
146 // Maintain uniqueness of the time track!
147 std::shared_ptr<TimeTrack> pNewTrack;
148 if( auto pTrack = *TrackList::Get( project ).Any<TimeTrack>().begin() )
149 pNewTrack = pTrack->SharedPointer<TimeTrack>();
150 else
151 pNewTrack = std::make_shared<TimeTrack>();
152
153 // Should come here only for .aup3 import, not for paste (because the
154 // track is skipped in cut/copy commands)
155 // And for import we agree to replace the track contents completely
156 pNewTrack->CleanState();
157 pNewTrack->Init(*this);
158 pNewTrack->Paste(0.0, this);
159 pNewTrack->SetRangeLower(this->GetRangeLower());
160 pNewTrack->SetRangeUpper(this->GetRangeUpper());
161 return pNewTrack;
162}
163
164Track::Holder TimeTrack::Cut( double t0, double t1 )
165{
166 auto result = Copy( t0, t1, false );
167 Clear( t0, t1 );
168 return result;
169}
170
171Track::Holder TimeTrack::Copy( double t0, double t1, bool ) const
172{
173 auto result = std::make_shared<TimeTrack>(*this, ProtectedCreationArg{}, &t0, &t1);
174 result->Init(*this);
175 return result;
176}
177
178namespace {
179double GetRate(const Track &track) {
180 if (auto pList = track.GetOwner()) {
181 if (auto pProject = pList->GetOwner())
182 return ProjectRate::Get(*pProject).GetRate();
183 }
184 return 44100.0;
185}
186}
187
188void TimeTrack::Clear(double t0, double t1)
189{
190 auto sampleTime = 1.0 / GetRate(*this);
191 mEnvelope->CollapseRegion( t0, t1, sampleTime );
192}
193
194void TimeTrack::Paste(double t, const Track * src)
195{
196 bool bOk = src && src->TypeSwitch< bool >( [&] (const TimeTrack *tt) {
197 auto sampleTime = 1.0 / GetRate(*this);
198 mEnvelope->PasteEnvelope
199 (t, tt->mEnvelope.get(), sampleTime);
200 return true;
201 } );
202
203 if (! bOk )
204 // THROW_INCONSISTENCY_EXCEPTION // ?
205 (void)0;// intentionally do nothing.
206}
207
208void TimeTrack::Silence(double WXUNUSED(t0), double WXUNUSED(t1))
209{
210}
211
212void TimeTrack::InsertSilence(double t, double len)
213{
214 mEnvelope->InsertSpace(t, len);
215}
216
218{
219 auto result = std::make_shared<TimeTrack>(*this, ProtectedCreationArg{});
220 result->Init(*this);
221 return result;
222}
223
225{
226 return mEnvelope->GetExponential();
227}
228
229void TimeTrack::SetInterpolateLog(bool interpolateLog) {
230 mEnvelope->SetExponential(interpolateLog);
231}
232
233bool TimeTrack::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
234{
235 if (tag == "timetrack") {
236 mRescaleXMLValues = true; // will be set to false if upper/lower is found
237
238 long nValue;
239
240 for (auto pair : attrs)
241 {
242 auto attr = pair.first;
243 auto value = pair.second;
244
245 if (this->Track::HandleCommonXMLAttribute(attr, value))
246 ;
247 else if (attr == "rangelower")
248 {
249 SetRangeLower( value.Get(GetRangeLower()) );
250 mRescaleXMLValues = false;
251 }
252 else if (attr == "rangeupper")
253 {
254 SetRangeUpper( value.Get(GetRangeUpper()) );
255 mRescaleXMLValues = false;
256 }
257 else if (attr == "displaylog" && value.TryGet(nValue))
258 {
259 SetDisplayLog(nValue != 0);
260 //TODO-MB: This causes a graphical glitch, TrackPanel should probably be Refresh()ed after loading.
261 // I don't know where to do this though.
262 }
263 else if (attr == "interpolatelog" && value.TryGet(nValue))
264 {
265 SetInterpolateLog(nValue != 0);
266 }
267
268 } // while
270 mEnvelope->SetRange(0.0, 1.0); // this will be restored to the actual range later
271 return true;
272 }
273
274 return false;
275}
276
277void TimeTrack::HandleXMLEndTag(const std::string_view& WXUNUSED(tag))
278{
280 {
281 mRescaleXMLValues = false;
282 mEnvelope->RescaleValues(GetRangeLower(), GetRangeUpper());
284 }
285}
286
287XMLTagHandler *TimeTrack::HandleXMLChild(const std::string_view& tag)
288{
289 if (tag == "envelope")
290 return mEnvelope.get();
291
292 return NULL;
293}
294
295void TimeTrack::WriteXML(XMLWriter &xmlFile) const
296// may throw
297{
298 xmlFile.StartTag(wxT("timetrack"));
299 this->Track::WriteCommonXMLAttributes( xmlFile );
300
301 //xmlFile.WriteAttr(wxT("channel"), mChannel);
302 //xmlFile.WriteAttr(wxT("offset"), mOffset, 8);
303 xmlFile.WriteAttr(wxT("rangelower"), GetRangeLower(), 12);
304 xmlFile.WriteAttr(wxT("rangeupper"), GetRangeUpper(), 12);
305 xmlFile.WriteAttr(wxT("displaylog"), GetDisplayLog());
306 xmlFile.WriteAttr(wxT("interpolatelog"), GetInterpolateLog());
307
308 mEnvelope->WriteXML(xmlFile);
309
310 xmlFile.EndTag(wxT("timetrack"));
311}
312
314{
315 GetEnvelope()->Flatten(0.0);
316 GetEnvelope()->InsertOrReplace(0.0, 0.2);
317 GetEnvelope()->InsertOrReplace(5.0 - 0.001, 0.2);
318 GetEnvelope()->InsertOrReplace(5.0 + 0.001, 1.3);
319 GetEnvelope()->InsertOrReplace(10.0, 1.3);
320
321 double value1 = GetEnvelope()->Integral(2.0, 13.0);
322 double expected1 = (5.0 - 2.0) * 0.2 + (13.0 - 5.0) * 1.3;
323 double value2 = GetEnvelope()->IntegralOfInverse(2.0, 13.0);
324 double expected2 = (5.0 - 2.0) / 0.2 + (13.0 - 5.0) / 1.3;
325 if( fabs(value1 - expected1) > 0.01 )
326 {
327 wxPrintf( "TimeTrack: Integral failed! expected %f got %f\n", expected1, value1);
328 }
329 if( fabs(value2 - expected2) > 0.01 )
330 {
331 wxPrintf( "TimeTrack: IntegralOfInverse failed! expected %f got %f\n", expected2, value2);
332 }
333
334 /*double reqt0 = 10.0 - .1;
335 double reqt1 = 10.0 + .1;
336 double t0 = warp( reqt0 );
337 double t1 = warp( reqt1 );
338 if( t0 > t1 )
339 {
340 wxPrintf( "TimeTrack: Warping reverses an interval! [%.2f,%.2f] -> [%.2f,%.2f]\n",
341 reqt0, reqt1,
342 t0, t1 );
343 }*/
344}
345
348[](const TrackList &list) -> const BoundedEnvelope*
349{
350 if (auto pTimeTrack = *list.Any<const TimeTrack>().begin())
351 return pTimeTrack->GetEnvelope();
352 else
353 return nullptr;
354} };
wxT("CloseDown"))
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:73
an object holding per-project preferred sample rate
static Mixer::WarpOptions::DefaultWarp::Scope installer
Installer of the time warper.
Definition: TimeTrack.cpp:347
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:122
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:1171
int InsertOrReplace(double when, double value)
Add a point at a particular absolute time coordinate.
Definition: Envelope.h:175
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1234
void Flatten(double value)
Definition: Envelope.cpp:137
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:22
static wxString GetDefaultName()
Definition: TimeTrack.cpp:36
void Paste(double t, const Track *src) override
Definition: TimeTrack.cpp:194
void WriteXML(XMLWriter &xmlFile) const override
Definition: TimeTrack.cpp:295
void SetInterpolateLog(bool interpolateLog)
Definition: TimeTrack.cpp:229
void HandleXMLEndTag(const std::string_view &tag) override
Definition: TimeTrack.cpp:277
static const TypeInfo & ClassTypeInfo()
Definition: TimeTrack.cpp:134
bool mRescaleXMLValues
Definition: TimeTrack.h:106
void SetDisplayLog(bool displayLog)
Definition: TimeTrack.h:95
std::unique_ptr< BoundedEnvelope > mEnvelope
Definition: TimeTrack.h:104
Holder Copy(double t0, double t1, bool forClipboard) const override
Definition: TimeTrack.cpp:171
Track::Holder Clone() const override
Definition: TimeTrack.cpp:217
bool GetInterpolateLog() const
Definition: TimeTrack.cpp:224
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
Definition: TimeTrack.cpp:233
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
Definition: TimeTrack.cpp:287
void CleanState()
Definition: TimeTrack.cpp:54
Holder Cut(double t0, double t1) override
Definition: TimeTrack.cpp:164
BoundedEnvelope * GetEnvelope()
Definition: TimeTrack.h:83
bool GetDisplayLog() const
Definition: TimeTrack.h:94
void InsertSilence(double t, double len) override
Definition: TimeTrack.cpp:212
bool mDisplayLog
Definition: TimeTrack.h:105
void testMe()
Definition: TimeTrack.cpp:313
const TypeInfo & GetTypeInfo() const override
Definition: TimeTrack.cpp:129
void SetRangeLower(double lower)
Definition: TimeTrack.cpp:112
virtual ~TimeTrack()
Definition: TimeTrack.cpp:98
void Silence(double t0, double t1) override
Definition: TimeTrack.cpp:208
static TimeTrack * New(AudacityProject &project)
Definition: TimeTrack.cpp:41
double GetRangeLower() const
Definition: TimeTrack.cpp:102
double GetRangeUpper() const
Definition: TimeTrack.cpp:107
Holder PasteInto(AudacityProject &) const override
Find or create the destination track for a paste, maybe in a different project.
Definition: TimeTrack.cpp:144
void Clear(double t0, double t1) override
Definition: TimeTrack.cpp:188
bool SupportsBasicEditing() const override
Whether this track type implements cut-copy-paste; by default, true.
Definition: TimeTrack.cpp:139
void Init(const TimeTrack &orig)
Copy the metadata from another track but not the points.
Definition: TimeTrack.cpp:91
void SetRangeUpper(double upper)
Definition: TimeTrack.cpp:117
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:162
static const TypeInfo & ClassTypeInfo()
Definition: Track.cpp:1159
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:344
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:766
std::shared_ptr< Track > Holder
Definition: Track.h:303
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
Definition: Track.cpp:1198
const wxString & GetName() const
Name is always the same for all channels of a group.
Definition: Track.cpp:68
void Init(const Track &orig)
Definition: Track.cpp:57
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
Definition: Track.cpp:1182
void SetName(const wxString &n)
Definition: Track.cpp:73
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1212
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:385
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:179
STL namespace.
Empty argument passed to some public constructors.
Definition: Track.h:169