Audacity  2.2.0
Envelope.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Envelope.h
6 
7  Dominic Mazzoni
8 
9 **********************************************************************/
10 
11 #ifndef __AUDACITY_ENVELOPE__
12 #define __AUDACITY_ENVELOPE__
13 
14 #include <stdlib.h>
15 #include <algorithm>
16 #include <vector>
17 
18 #include <wx/dynarray.h>
19 #include <wx/brush.h>
20 #include <wx/pen.h>
21 
22 #include "xml/XMLTagHandler.h"
23 #include "Internat.h"
24 
25 class wxRect;
26 class wxDC;
27 class wxMouseEvent;
28 class wxTextFile;
29 
30 class DirManager;
31 class Envelope;
32 class EnvPoint;
33 
34 class ZoomInfo;
35 
36 class EnvPoint final : public XMLTagHandler {
37 
38 public:
39  EnvPoint() {}
40  inline EnvPoint( double t, double val ) : mT{ t }, mVal{ val } {}
41 
42  double GetT() const { return mT; }
43  void SetT(double t) { mT = t; }
44  double GetVal() const { return mVal; }
45  inline void SetVal( Envelope *pEnvelope, double val );
46 
47  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
48  {
49  if (!wxStrcmp(tag, wxT("controlpoint"))) {
50  while (*attrs) {
51  const wxChar *attr = *attrs++;
52  const wxChar *value = *attrs++;
53  if (!wxStrcmp(attr, wxT("t")))
55  else if (!wxStrcmp(attr, wxT("val")))
56  SetVal( nullptr, Internat::CompatibleToDouble(value) );
57  }
58  return true;
59  }
60  else
61  return false;
62  }
63 
64  XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) override
65  {
66  return NULL;
67  }
68 
69 private:
70  double mT {};
71  double mVal {};
72 
73 };
74 
75 typedef std::vector<EnvPoint> EnvArray;
77 
78 class Envelope final : public XMLTagHandler {
79 public:
80  // Envelope can define a piecewise linear function, or piecewise exponential.
81  Envelope(bool exponential, double minValue, double maxValue, double defaultValue);
82 
83  Envelope(const Envelope &orig);
84 
85  // Create from a subrange of another envelope.
86  Envelope(const Envelope &orig, double t0, double t1);
87 
88  void Initialize(int numPoints);
89 
90  virtual ~Envelope();
91 
92  // Return true if violations of point ordering invariants were detected
93  // and repaired
94  bool ConsistencyCheck();
95 
96  double GetOffset() const { return mOffset; }
97  double GetTrackLen() const { return mTrackLen; }
98 
99  bool GetExponential() const { return mDB; }
100  void SetExponential(bool db) { mDB = db; }
101 
102  void Flatten(double value);
103 
104  double GetMinValue() const { return mMinValue; }
105  double GetMaxValue() const { return mMaxValue; }
106  void SetRange(double minValue, double maxValue);
107 
108  double ClampValue(double value) { return std::max(mMinValue, std::min(mMaxValue, value)); }
109 
110 #if LEGACY_PROJECT_FILE_SUPPORT
111  // File I/O
112 
113  bool Load(wxTextFile * in, DirManager * dirManager) override;
114  bool Save(wxTextFile * out, bool overwrite) override;
115 #endif
116  // Newfangled XML file I/O
117  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
118  XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
119  void WriteXML(XMLWriter &xmlFile) const /* not override */;
120 
121  void DrawPoints(
122  TrackPanelDrawingContext &context,
123  const wxRect & r, const ZoomInfo &zoomInfo,
124  bool dB, double dBRange,
125  float zoomMin, float zoomMax, bool mirrored) const;
126 
127  // Handling Cut/Copy/Paste events
128  // sampleDur determines when the endpoint of the collapse is near enough
129  // to an endpoint of the domain, that an extra control point is not needed.
130  void CollapseRegion(double t0, double t1, double sampleDur);
131 
132  // Envelope has no notion of rate and control point times are not quantized;
133  // but a tolerance is needed in the Paste routine, and better to inform it
134  // of an appropriate number, than use hidden arbitrary constants.
135  void Paste(double t0, const Envelope *e, double sampleDur);
136 
137  void InsertSpace(double t0, double tlen);
138 
139  // Control
140  void SetOffset(double newOffset);
141  void SetTrackLen( double trackLen, double sampleDur = 0.0 );
142  void RescaleValues(double minValue, double maxValue);
143  void RescaleTimes( double newLength );
144 
145  // Accessors
147  double GetValue( double t, double sampleDur = 0 ) const;
148 
153  void GetValues(double *buffer, int len, double t0, double tstep) const;
154 
158  void GetValues
159  ( double aligned_time, double sampleDur,
160  double *buffer, int bufferLen, int leftOffset,
161  const ZoomInfo &zoomInfo) const;
162 
163  // Guarantee an envelope point at the end of the domain.
164  void Cap( double sampleDur );
165 
166 private:
167  std::pair< int, int > ExpandRegion
168  ( double t0, double tlen, double *pLeftVal, double *pRightVal );
169 
171  ( size_t startAt, bool rightward, bool testNeighbors = true );
172 
173  double GetValueRelative(double t, bool leftLimit = false) const;
174  void GetValuesRelative
175  (double *buffer, int len, double t0, double tstep, bool leftLimit = false)
176  const;
177  // relative time
178  int NumberOfPointsAfter(double t) const;
179  // relative time
180  double NextPointAfter(double t) const;
181 
182 public:
183  double Average( double t0, double t1 ) const;
184  double AverageOfInverse( double t0, double t1 ) const;
185  double Integral( double t0, double t1 ) const;
186  double IntegralOfInverse( double t0, double t1 ) const;
187  double SolveIntegralOfInverse( double t0, double area) const;
188 
189  void print() const;
190  void testMe();
191 
192  bool IsDirty() const;
193 
195  int InsertOrReplace(double when, double value)
196  { return InsertOrReplaceRelative( when - mOffset, value ); }
197 
201  int Reassign(double when, double value);
202 
204  void Delete(int point);
205 
207  void Insert(int point, const EnvPoint &p);
208 
210  size_t GetNumberOfPoints() const;
211 
212 private:
213  int InsertOrReplaceRelative(double when, double value);
214 
215  friend class EnvelopeEditor;
217  const EnvPoint &operator[] (int index) const
218  {
219  return mEnv[index];
220  }
221 
222  std::pair<int, int> EqualRange( double when, double sampleDur ) const;
223 
224 public:
226  void GetPoints(double *bufferWhen,
227  double *bufferValue,
228  int bufferLen) const;
229 
230  // UI-related
231  // The drag point needs to display differently.
232  int GetDragPoint() const { return mDragPoint; }
233  // Choose the drag point.
234  void SetDragPoint(int dragPoint);
235  // Mark or unmark the drag point for deletion.
236  void SetDragPointValid(bool valid);
237  bool GetDragPointValid() const { return mDragPointValid; }
238  // Modify the dragged point and change its value.
239  // But consistency constraints may move it less then you ask for.
240 
241 private:
242  void MoveDragPoint(double newWhen, double value);
243  // May delete the drag point. Restores envelope consistency.
244  void ClearDragPoint();
245  void AddPointAtEnd( double t, double val );
246  void CopyRange(const Envelope &orig, size_t begin, size_t end);
247  // relative time
248  void BinarySearchForTime( int &Lo, int &Hi, double t ) const;
249  void BinarySearchForTime_LeftLimit( int &Lo, int &Hi, double t ) const;
250  double GetInterpolationStartValueAtPoint( int iPoint ) const;
251 
252  // The list of envelope control points.
253  EnvArray mEnv;
254 
256  double mOffset { 0.0 };
259  double mTrackLen { 0.0 };
260 
261  // TODO: mTrackEpsilon based on assumption of 200KHz. Needs review if/when
262  // we support higher sample rates.
265  double mTrackEpsilon { 1.0 / 200000.0 };
266  bool mDB;
269 
270  // UI stuff
271  bool mDragPointValid { false };
272  int mDragPoint { -1 };
273 
274  mutable int mSearchGuess { -2 };
275 };
276 
277 inline void EnvPoint::SetVal( Envelope *pEnvelope, double val )
278 {
279  if ( pEnvelope )
280  val = pEnvelope->ClampValue(val);
281  mVal = val;
282 }
283 
284 // A class that holds state for the duration of dragging
285 // of an envelope point.
287 {
288 public:
289  EnvelopeEditor(Envelope &envelope, bool mirrored);
290  ~EnvelopeEditor();
291 
292  // Event Handlers
293  // Each of these returns true if the envelope needs to be redrawn
294  bool MouseEvent(const wxMouseEvent & event, wxRect & r,
295  const ZoomInfo &zoomInfo, bool dB, double dBRange,
296  float zoomMin = -1.0, float zoomMax = 1.0);
297 
298 private:
299  bool HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
300  const ZoomInfo &zoomInfo, bool dB, double dBRange,
301  float zoomMin = -1.0, float zoomMax = 1.0);
302  bool HandleDragging(const wxMouseEvent & event, wxRect & r,
303  const ZoomInfo &zoomInfo, bool dB, double dBRange,
304  float zoomMin = -1.0, float zoomMax = 1.0, float eMin = 0., float eMax = 2.);
305  bool HandleMouseButtonUp();
306 
307 private:
308  float ValueOfPixel(int y, int height, bool upper,
309  bool dB, double dBRange,
310  float zoomMin, float zoomMax);
311  void MoveDragPoint(const wxMouseEvent & event, wxRect & r,
312  const ZoomInfo &zoomInfo, bool dB, double dBRange,
313  float zoomMin, float zoomMax);
314 
316  const bool mMirrored;
317 
320 
321  // double mInitialVal;
322 
323  // int mInitialY;
324  bool mUpper;
325  int mButton;
326  bool mDirty;
327 };
328 
329 #endif
double mMaxValue
Definition: Envelope.h:267
bool HandleDragging(const wxMouseEvent &event, wxRect &r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin=-1.0, float zoomMax=1.0, float eMin=0., float eMax=2.)
Definition: Envelope.cpp:613
void DrawPoints(TrackPanelDrawingContext &context, const wxRect &r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin, float zoomMax, bool mirrored) const
TODO: This should probably move to track artist.
Definition: Envelope.cpp:322
const bool mMirrored
Definition: Envelope.h:316
Creates and manages BlockFile objects.
Definition: DirManager.h:52
void RescaleValues(double minValue, double maxValue)
Definition: Envelope.cpp:115
double Average(double t0, double t1) const
Definition: Envelope.cpp:1400
double GetT() const
Definition: Envelope.h:42
EnvPoint(double t, double val)
Definition: Envelope.h:40
void MoveDragPoint(double newWhen, double value)
Definition: Envelope.cpp:186
double AverageOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1408
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:259
void Flatten(double value)
Definition: Envelope.cpp:137
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
Definition: Envelope.cpp:391
double mTrackEpsilon
The shortest distance appart that points on an envelope can be before being considered the same point...
Definition: Envelope.h:265
size_t GetNumberOfPoints() const
Return number of points.
Definition: Envelope.cpp:980
bool mDB
Definition: Envelope.h:266
void SetOffset(double newOffset)
Definition: Envelope.cpp:1071
int mSearchGuess
Definition: Envelope.h:274
XMLTagHandler * HandleXMLChild(const wxChar *WXUNUSED(tag)) override
Definition: Envelope.h:64
double GetMinValue() const
Definition: Envelope.h:104
Definition: Envelope.h:286
void Initialize(int numPoints)
double mMinValue
Definition: Envelope.h:267
void SetExponential(bool db)
Definition: Envelope.h:100
Envelope(bool exponential, double minValue, double maxValue, double defaultValue)
Definition: Envelope.cpp:48
double mVal
Definition: Envelope.h:71
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: Envelope.cpp:418
int GetDragPoint() const
Definition: Envelope.h:232
virtual ~Envelope()
Definition: Envelope.cpp:56
double SolveIntegralOfInverse(double t0, double area) const
Definition: Envelope.cpp:1625
Draggable curve used in TrackPanel for varying amplification.
Definition: Envelope.h:78
void SetDragPointValid(bool valid)
Definition: Envelope.cpp:149
bool ConsistencyCheck()
Definition: Envelope.cpp:60
void Paste(double t0, const Envelope *e, double sampleDur)
Definition: Envelope.cpp:757
double NextPointAfter(double t) const
Definition: Envelope.cpp:1390
int Reassign(double when, double value)
Move a point at when to value.
Definition: Envelope.cpp:960
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
double GetTrackLen() const
Definition: Envelope.h:97
void CopyRange(const Envelope &orig, size_t begin, size_t end)
Definition: Envelope.cpp:273
void GetPoints(double *bufferWhen, double *bufferValue, int bufferLen) const
Returns the sets of when and value pairs.
Definition: Envelope.cpp:985
void print() const
Definition: Envelope.cpp:1728
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
void ClearDragPoint()
Definition: Envelope.cpp:212
void SetDragPoint(int dragPoint)
Definition: Envelope.cpp:143
void InsertSpace(double t0, double tlen)
Definition: Envelope.cpp:950
void RemoveUnneededPoints(size_t startAt, bool rightward, bool testNeighbors=true)
Definition: Envelope.cpp:834
void testMe()
Definition: Envelope.cpp:1743
Definition: ViewInfo.h:31
void BinarySearchForTime_LeftLimit(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1181
int InsertOrReplaceRelative(double when, double value)
Add a control point to the envelope.
Definition: Envelope.cpp:1014
void Cap(double sampleDur)
Definition: Envelope.cpp:999
bool HandleMouseButtonUp()
Definition: Envelope.cpp:641
double GetMaxValue() const
Definition: Envelope.h:105
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:121
void RescaleTimes(double newLength)
Definition: Envelope.cpp:1098
Envelope & mEnvelope
Definition: Envelope.h:315
void WriteXML(XMLWriter &xmlFile) const
Definition: Envelope.cpp:427
int InsertOrReplace(double when, double value)
Add a point at a particular absolute time coordinate.
Definition: Envelope.h:195
bool MouseEvent(const wxMouseEvent &event, wxRect &r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin=-1.0, float zoomMax=1.0)
Definition: Envelope.cpp:659
void SetTrackLen(double trackLen, double sampleDur=0.0)
Definition: Envelope.cpp:1077
void Delete(int point)
DELETE a point by its position in array.
Definition: Envelope.cpp:648
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1562
int mContourOffset
Number of pixels contour is from the true envelope.
Definition: Envelope.h:319
const EnvPoint & operator[](int index) const
Accessor for points.
Definition: Envelope.h:217
void MoveDragPoint(const wxMouseEvent &event, wxRect &r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin, float zoomMax)
Definition: Envelope.cpp:594
float ValueOfPixel(int y, int height, bool upper, bool dB, double dBRange, float zoomMin, float zoomMax)
Definition: Envelope.cpp:458
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:69
int mDragPoint
Definition: Envelope.h:272
double mT
Definition: Envelope.h:70
void SetT(double t)
Definition: Envelope.h:43
int min(int a, int b)
Definition: CompareAudioCommand.cpp:80
std::vector< EnvPoint > EnvArray
Definition: Envelope.h:75
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:1114
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:256
void SetVal(Envelope *pEnvelope, double val)
Definition: Envelope.h:277
void AddPointAtEnd(double t, double val)
Definition: Envelope.cpp:231
void GetValuesRelative(double *buffer, int len, double t0, double tstep, bool leftLimit=false) const
Definition: Envelope.cpp:1223
double ClampValue(double value)
Definition: Envelope.h:108
EnvPoint()
Definition: Envelope.h:39
std::pair< int, int > ExpandRegion(double t0, double tlen, double *pLeftVal, double *pRightVal)
Definition: Envelope.cpp:900
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
Definition: Envelope.h:47
double GetVal() const
Definition: Envelope.h:44
bool GetDragPointValid() const
Definition: Envelope.h:237
void SetRange(double minValue, double maxValue)
Definition: Envelope.cpp:221
bool mDirty
Definition: Envelope.h:326
void Insert(int point, const EnvPoint &p)
insert a point
Definition: Envelope.cpp:653
bool mDragPointValid
Definition: Envelope.h:271
bool mUpper
Definition: Envelope.h:324
double mDefaultValue
Definition: Envelope.h:268
bool IsDirty() const
~EnvelopeEditor()
Definition: Envelope.cpp:1811
void GetValues(double *buffer, int len, double t0, double tstep) const
Get many envelope points at once.
Definition: Envelope.cpp:1214
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:22
double GetInterpolationStartValueAtPoint(int iPoint) const
Definition: Envelope.cpp:1205
void CollapseRegion(double t0, double t1, double sampleDur)
Definition: Envelope.cpp:674
int NumberOfPointsAfter(double t) const
Definition: Envelope.cpp:1381
int mButton
Definition: Envelope.h:325
EnvArray mEnv
Definition: Envelope.h:253
bool GetExponential() const
Definition: Envelope.h:99
double Integral(double t0, double t1) const
Definition: Envelope.cpp:1499
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:36
bool HandleMouseButtonDown(const wxMouseEvent &event, wxRect &r, const ZoomInfo &zoomInfo, bool dB, double dBRange, float zoomMin=-1.0, float zoomMax=1.0)
Definition: Envelope.cpp:478
Definition: TrackPanelDrawingContext.h:24
EnvelopeEditor(Envelope &envelope, bool mirrored)
Definition: Envelope.cpp:1799
double GetOffset() const
Definition: Envelope.h:96