Audacity  3.0.3
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 "ActiveProject.h"
20 #include <cfloat>
21 #include <wx/wxcrtvararg.h>
22 #include <wx/dc.h>
23 #include <wx/intl.h>
24 #include "widgets/Ruler.h"
25 #include "Envelope.h"
26 #include "Project.h"
27 #include "ProjectRate.h"
28 #include "ViewInfo.h"
29 
30 #include "tracks/ui/TrackView.h"
32 
33 
34 //TODO-MB: are these sensible values?
35 #define TIMETRACK_MIN 0.01
36 #define TIMETRACK_MAX 10.0
37 
39  wxT( "timetrack" ),
40  []( AudacityProject &project ){
41  auto &tracks = TrackList::Get( project );
42  auto &viewInfo = ViewInfo::Get( project );
43  auto result = tracks.Add(std::make_shared<TimeTrack>(&viewInfo));
44  TrackView::Get( *result );
45  TrackControls::Get( *result );
46  return result;
47  }
48 };
49 
50 TimeTrack::TimeTrack(const ZoomInfo *zoomInfo):
51  Track()
52  , mZoomInfo(zoomInfo)
53 {
54  CleanState();
55 }
56 
58 {
59  mEnvelope = std::make_unique<BoundedEnvelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
60 
61  SetRangeLower( 0.9 );
62  SetRangeUpper( 1.1 );
63  mDisplayLog = false;
64 
65  mEnvelope->SetTrackLen(DBL_MAX);
66  mEnvelope->SetOffset(0);
67 
68  SetDefaultName(_("Time Track"));
70 
71  mRuler = std::make_unique<Ruler>();
72  mRuler->SetUseZoomInfo(0, mZoomInfo);
73  mRuler->SetLabelEdges(false);
74  mRuler->SetFormat(Ruler::TimeFormat);
75 }
76 
77 TimeTrack::TimeTrack(const TimeTrack &orig, double *pT0, double *pT1)
78  : Track(orig)
79  , mZoomInfo(orig.mZoomInfo)
80 {
81  Init(orig); // this copies the TimeTrack metadata (name, range, etc)
82 
83  auto len = DBL_MAX;
84  if (pT0 && pT1) {
85  len = *pT1 - *pT0;
86  mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope, *pT0, *pT1 );
87  }
88  else
89  mEnvelope = std::make_unique<BoundedEnvelope>( *orig.mEnvelope );
90 
93 
94  mEnvelope->SetTrackLen( len );
95  mEnvelope->SetOffset(0);
96 
98  mRuler = std::make_unique<Ruler>();
99  mRuler->SetUseZoomInfo(0, mZoomInfo);
100  mRuler->SetLabelEdges(false);
101  mRuler->SetFormat(Ruler::TimeFormat);
102 }
103 
104 // Copy the track metadata but not the contents.
105 void TimeTrack::Init(const TimeTrack &orig)
106 {
107  Track::Init(orig);
109  SetName(orig.GetName());
111 }
112 
114 {
115 }
116 
118 {
119  return mEnvelope->GetRangeLower();
120 }
121 
123 {
124  return mEnvelope->GetRangeUpper();
125 }
126 
127 void TimeTrack::SetRangeLower(double lower)
128 {
129  mEnvelope->SetRangeLower( lower );
130 }
131 
132 void TimeTrack::SetRangeUpper(double upper)
133 {
134  mEnvelope->SetRangeUpper( upper );
135 }
136 
138 {
139  return false;
140 }
141 
143 {
144  // Maintain uniqueness of the time track!
145  std::shared_ptr<TimeTrack> pNewTrack;
146  if( auto pTrack = *TrackList::Get( project ).Any<TimeTrack>().begin() )
147  pNewTrack = pTrack->SharedPointer<TimeTrack>();
148  else
149  pNewTrack = std::make_shared<TimeTrack>( &ViewInfo::Get( project ) );
150 
151  // Should come here only for .aup3 import, not for paste (because the
152  // track is skipped in cut/copy commands)
153  // And for import we agree to replace the track contents completely
154  pNewTrack->CleanState();
155  pNewTrack->Init(*this);
156  pNewTrack->Paste(0.0, this);
157  pNewTrack->SetRangeLower(this->GetRangeLower());
158  pNewTrack->SetRangeUpper(this->GetRangeUpper());
159  return pNewTrack;
160 }
161 
162 Track::Holder TimeTrack::Cut( double t0, double t1 )
163 {
164  auto result = Copy( t0, t1, false );
165  Clear( t0, t1 );
166  return result;
167 }
168 
169 Track::Holder TimeTrack::Copy( double t0, double t1, bool ) const
170 {
171  return std::make_shared<TimeTrack>( *this, &t0, &t1 );
172 }
173 
174 namespace {
175 double GetRate() {
176  auto pProject = GetActiveProject().lock();
177  return pProject
178  ? ProjectRate::Get( *pProject ).GetRate()
179  : 44100.0;
180 }
181 }
182 
183 void TimeTrack::Clear(double t0, double t1)
184 {
185  auto sampleTime = 1.0 / GetRate();
186  mEnvelope->CollapseRegion( t0, t1, sampleTime );
187 }
188 
189 void TimeTrack::Paste(double t, const Track * src)
190 {
191  bool bOk = src && src->TypeSwitch< bool >( [&] (const TimeTrack *tt) {
192  auto sampleTime = 1.0 / GetRate();
193  mEnvelope->PasteEnvelope
194  (t, tt->mEnvelope.get(), sampleTime);
195  return true;
196  } );
197 
198  if (! bOk )
199  // THROW_INCONSISTENCY_EXCEPTION // ?
200  (void)0;// intentionally do nothing.
201 }
202 
203 void TimeTrack::Silence(double WXUNUSED(t0), double WXUNUSED(t1))
204 {
205 }
206 
207 void TimeTrack::InsertSilence(double t, double len)
208 {
209  mEnvelope->InsertSpace(t, len);
210 }
211 
213 {
214  return std::make_shared<TimeTrack>(*this);
215 }
216 
218 {
219  return mEnvelope->GetExponential();
220 }
221 
222 void TimeTrack::SetInterpolateLog(bool interpolateLog) {
223  mEnvelope->SetExponential(interpolateLog);
224 }
225 
226 bool TimeTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs)
227 {
228  if (!wxStrcmp(tag, wxT("timetrack"))) {
229  mRescaleXMLValues = true; // will be set to false if upper/lower is found
230  long nValue;
231  while(*attrs) {
232  const wxChar *attr = *attrs++;
233  const wxChar *value = *attrs++;
234 
235  if (!value)
236  break;
237 
238  const wxString strValue = value;
239  if (this->Track::HandleCommonXMLAttribute(attr, strValue))
240  ;
241  else if (!wxStrcmp(attr, wxT("rangelower")))
242  {
244  mRescaleXMLValues = false;
245  }
246  else if (!wxStrcmp(attr, wxT("rangeupper")))
247  {
249  mRescaleXMLValues = false;
250  }
251  else if (!wxStrcmp(attr, wxT("displaylog")) &&
252  XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
253  {
254  SetDisplayLog(nValue != 0);
255  //TODO-MB: This causes a graphical glitch, TrackPanel should probably be Refresh()ed after loading.
256  // I don't know where to do this though.
257  }
258  else if (!wxStrcmp(attr, wxT("interpolatelog")) &&
259  XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
260  {
261  SetInterpolateLog(nValue != 0);
262  }
263 
264  } // while
266  mEnvelope->SetRange(0.0, 1.0); // this will be restored to the actual range later
267  return true;
268  }
269 
270  return false;
271 }
272 
273 void TimeTrack::HandleXMLEndTag(const wxChar * WXUNUSED(tag))
274 {
276  {
277  mRescaleXMLValues = false;
278  mEnvelope->RescaleValues(GetRangeLower(), GetRangeUpper());
280  }
281 }
282 
284 {
285  if (!wxStrcmp(tag, wxT("envelope")))
286  return mEnvelope.get();
287 
288  return NULL;
289 }
290 
291 void TimeTrack::WriteXML(XMLWriter &xmlFile) const
292 // may throw
293 {
294  xmlFile.StartTag(wxT("timetrack"));
295  this->Track::WriteCommonXMLAttributes( xmlFile );
296 
297  //xmlFile.WriteAttr(wxT("channel"), mChannel);
298  //xmlFile.WriteAttr(wxT("offset"), mOffset, 8);
299  xmlFile.WriteAttr(wxT("rangelower"), GetRangeLower(), 12);
300  xmlFile.WriteAttr(wxT("rangeupper"), GetRangeUpper(), 12);
301  xmlFile.WriteAttr(wxT("displaylog"), GetDisplayLog());
302  xmlFile.WriteAttr(wxT("interpolatelog"), GetInterpolateLog());
303 
304  mEnvelope->WriteXML(xmlFile);
305 
306  xmlFile.EndTag(wxT("timetrack"));
307 }
308 
310 {
311  GetEnvelope()->Flatten(0.0);
312  GetEnvelope()->InsertOrReplace(0.0, 0.2);
313  GetEnvelope()->InsertOrReplace(5.0 - 0.001, 0.2);
314  GetEnvelope()->InsertOrReplace(5.0 + 0.001, 1.3);
315  GetEnvelope()->InsertOrReplace(10.0, 1.3);
316 
317  double value1 = GetEnvelope()->Integral(2.0, 13.0);
318  double expected1 = (5.0 - 2.0) * 0.2 + (13.0 - 5.0) * 1.3;
319  double value2 = GetEnvelope()->IntegralOfInverse(2.0, 13.0);
320  double expected2 = (5.0 - 2.0) / 0.2 + (13.0 - 5.0) / 1.3;
321  if( fabs(value1 - expected1) > 0.01 )
322  {
323  wxPrintf( "TimeTrack: Integral failed! expected %f got %f\n", expected1, value1);
324  }
325  if( fabs(value2 - expected2) > 0.01 )
326  {
327  wxPrintf( "TimeTrack: IntegralOfInverse failed! expected %f got %f\n", expected2, value2);
328  }
329 
330  /*double reqt0 = 10.0 - .1;
331  double reqt1 = 10.0 + .1;
332  double t0 = warp( reqt0 );
333  double t1 = warp( reqt1 );
334  if( t0 > t1 )
335  {
336  wxPrintf( "TimeTrack: Warping reverses an interval! [%.2f,%.2f] -> [%.2f,%.2f]\n",
337  reqt0, reqt1,
338  t0, t1 );
339  }*/
340 }
341 
XMLWriter
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:23
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:241
TimeTrack::GetRangeLower
double GetRangeLower() const
Definition: TimeTrack.cpp:117
TimeTrack::InsertSilence
void InsertSilence(double t, double len) override
Definition: TimeTrack.cpp:207
Track::GetDefaultName
wxString GetDefaultName() const
Definition: Track.h:428
Track::WriteCommonXMLAttributes
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
Definition: Track.cpp:1255
TimeTrack::WriteXML
void WriteXML(XMLWriter &xmlFile) const override
Definition: TimeTrack.cpp:291
TrackView::Get
static TrackView & Get(Track &)
Definition: TrackView.cpp:63
TIMETRACK_MAX
#define TIMETRACK_MAX
Definition: TimeTrack.cpp:36
XMLValueChecker::IsGoodInt
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
Definition: XMLTagHandler.cpp:157
TrackView.h
Track::GetName
wxString GetName() const
Definition: Track.h:426
Project.h
TimeTrack::Silence
void Silence(double t0, double t1) override
Definition: TimeTrack.cpp:203
ProjectRate::Get
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:42
ZoomInfo
Definition: ZoomInfo.h:47
TrackControls::Get
static TrackControls & Get(Track &track)
Definition: TrackControls.cpp:25
TimeTrack::GetRangeUpper
double GetRangeUpper() const
Definition: TimeTrack.cpp:122
XMLMethodRegistry::ObjectReaderEntry
Definition: XMLMethodRegistry.h:82
Track::SharedPointer
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:291
TimeTrack::mDisplayLog
bool mDisplayLog
Definition: TimeTrack.h:106
TimeTrack::Clone
Track::Holder Clone() const override
Definition: TimeTrack.cpp:212
GetActiveProject
AUDACITY_DLL_API std::weak_ptr< AudacityProject > GetActiveProject()
Definition: ActiveProject.cpp:24
TimeTrack::HandleXMLChild
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: TimeTrack.cpp:283
readerEntry
static ProjectFileIORegistry::ObjectReaderEntry readerEntry
Definition: TimeTrack.cpp:38
TimeTrack.h
TimeTrack::HandleXMLTag
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
Definition: TimeTrack.cpp:226
Track::HandleCommonXMLAttribute
bool HandleCommonXMLAttribute(const wxChar *attr, const wxChar *value)
Definition: Track.cpp:1269
Envelope::IntegralOfInverse
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1233
TimeTrack::Paste
void Paste(double t, const Track *src) override
Definition: TimeTrack.cpp:189
TimeTrack::GetDisplayLog
bool GetDisplayLog() const
Definition: TimeTrack.h:88
Ruler::TimeFormat
@ TimeFormat
Definition: Ruler.h:33
TimeTrack::CleanState
void CleanState()
Definition: TimeTrack.cpp:57
TimeTrack::Clear
void Clear(double t0, double t1) override
Definition: TimeTrack.cpp:183
TimeTrack::PasteInto
Holder PasteInto(AudacityProject &) const override
Find or create the destination track for a paste, maybe in a different project.
Definition: TimeTrack.cpp:142
TimeTrack::GetInterpolateLog
bool GetInterpolateLog() const
Definition: TimeTrack.cpp:217
TimeTrack::SetDisplayLog
void SetDisplayLog(bool displayLog)
Definition: TimeTrack.h:89
TimeTrack::TimeTrack
TimeTrack(const ZoomInfo *zoomInfo)
Definition: TimeTrack.cpp:50
Track::Holder
std::shared_ptr< Track > Holder
Definition: Track.h:336
Track::SetDefaultName
void SetDefaultName(const wxString &n)
Definition: Track.h:429
TimeTrack::Cut
Holder Cut(double t0, double t1) override
Definition: TimeTrack.cpp:162
anonymous_namespace{TimeTrack.cpp}::GetRate
double GetRate()
Definition: TimeTrack.cpp:175
TimeTrack::testMe
void testMe()
Definition: TimeTrack.cpp:309
TimeTrack::GetEnvelope
BoundedEnvelope * GetEnvelope()
Definition: TimeTrack.h:77
TrackControls.h
TimeTrack::mZoomInfo
const ZoomInfo *const mZoomInfo
Definition: TimeTrack.h:103
Envelope::InsertOrReplace
int InsertOrReplace(double when, double value)
Add a point at a particular absolute time coordinate.
Definition: Envelope.h:181
TIMETRACK_MIN
#define TIMETRACK_MIN
Definition: TimeTrack.cpp:35
ProjectRate::GetRate
double GetRate() const
Definition: ProjectRate.cpp:68
ViewInfo.h
Ruler.h
XMLTagHandler
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:62
Envelope.h
Track::TypeSwitch
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:709
TimeTrack::mRescaleXMLValues
bool mRescaleXMLValues
Definition: TimeTrack.h:107
TimeTrack::SupportsBasicEditing
bool SupportsBasicEditing() const override
Whether this track type implements cut-copy-paste; by default, true.
Definition: TimeTrack.cpp:137
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:506
TimeTrack::mEnvelope
std::unique_ptr< BoundedEnvelope > mEnvelope
Definition: TimeTrack.h:104
Track::SetName
void SetName(const wxString &n)
Definition: Track.cpp:82
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:239
_
#define _(s)
Definition: Internat.h:75
Track::Init
void Init(const Track &orig)
Definition: Track.cpp:70
TimeTrack::~TimeTrack
virtual ~TimeTrack()
Definition: TimeTrack.cpp:113
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
TimeTrack::Copy
Holder Copy(double t0, double t1, bool forClipboard) const override
Definition: TimeTrack.cpp:169
TimeTrack::SetInterpolateLog
void SetInterpolateLog(bool interpolateLog)
Definition: TimeTrack.cpp:222
ProjectRate.h
an object holding per-project preferred sample rate
ActiveProject.h
Handle changing of active project and keep global project pointer.
Envelope::Flatten
void Flatten(double value)
Definition: Envelope.cpp:134
TimeTrack::SetRangeLower
void SetRangeLower(double lower)
Definition: TimeTrack.cpp:127
Envelope::Integral
double Integral(double t0, double t1) const
Definition: Envelope.cpp:1170
TimeTrack::HandleXMLEndTag
void HandleXMLEndTag(const wxChar *tag) override
Definition: TimeTrack.cpp:273
TimeTrack::mRuler
std::unique_ptr< Ruler > mRuler
Definition: TimeTrack.h:105
TimeTrack::Init
void Init(const TimeTrack &orig)
Copy the metadata from another track but not the points.
Definition: TimeTrack.cpp:105
TimeTrack::SetRangeUpper
void SetRangeUpper(double upper)
Definition: TimeTrack.cpp:132
TimeTrack
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:24
Internat::CompatibleToDouble
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:134