Audacity  2.2.2
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/brush.h>
19 #include <wx/pen.h>
20 
21 #include "xml/XMLTagHandler.h"
22 #include "Internat.h"
23 
24 class wxRect;
25 class wxDC;
26 class wxMouseEvent;
27 class wxTextFile;
28 
29 class DirManager;
30 class Envelope;
31 class EnvPoint;
32 
33 class ZoomInfo;
34 
35 class EnvPoint final : public XMLTagHandler {
36 
37 public:
38  EnvPoint() {}
39  inline EnvPoint( double t, double val ) : mT{ t }, mVal{ val } {}
40 
41  double GetT() const { return mT; }
42  void SetT(double t) { mT = t; }
43  double GetVal() const { return mVal; }
44  inline void SetVal( Envelope *pEnvelope, double val );
45 
46  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
47  {
48  if (!wxStrcmp(tag, wxT("controlpoint"))) {
49  while (*attrs) {
50  const wxChar *attr = *attrs++;
51  const wxChar *value = *attrs++;
52  if (!wxStrcmp(attr, wxT("t")))
54  else if (!wxStrcmp(attr, wxT("val")))
55  SetVal( nullptr, Internat::CompatibleToDouble(value) );
56  }
57  return true;
58  }
59  else
60  return false;
61  }
62 
63  XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) override
64  {
65  return NULL;
66  }
67 
68 private:
69  double mT {};
70  double mVal {};
71 
72 };
73 
74 typedef std::vector<EnvPoint> EnvArray;
76 
77 class Envelope final : public XMLTagHandler {
78 public:
79  // Envelope can define a piecewise linear function, or piecewise exponential.
80  Envelope(bool exponential, double minValue, double maxValue, double defaultValue);
81 
82  Envelope(const Envelope &orig);
83 
84  // Create from a subrange of another envelope.
85  Envelope(const Envelope &orig, double t0, double t1);
86 
87  void Initialize(int numPoints);
88 
89  virtual ~Envelope();
90 
91  // Return true if violations of point ordering invariants were detected
92  // and repaired
93  bool ConsistencyCheck();
94 
95  double GetOffset() const { return mOffset; }
96  double GetTrackLen() const { return mTrackLen; }
97 
98  bool GetExponential() const { return mDB; }
99  void SetExponential(bool db) { mDB = db; }
100 
101  void Flatten(double value);
102 
103  double GetMinValue() const { return mMinValue; }
104  double GetMaxValue() const { return mMaxValue; }
105  void SetRange(double minValue, double maxValue);
106 
107  double ClampValue(double value) { return std::max(mMinValue, std::min(mMaxValue, value)); }
108 
109 #if LEGACY_PROJECT_FILE_SUPPORT
110  // File I/O
111 
112  bool Load(wxTextFile * in, DirManager * dirManager) override;
113  bool Save(wxTextFile * out, bool overwrite) override;
114 #endif
115  // Newfangled XML file I/O
116  bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override;
117  XMLTagHandler *HandleXMLChild(const wxChar *tag) override;
118  void WriteXML(XMLWriter &xmlFile) const /* not override */;
119 
120  void DrawPoints(
121  TrackPanelDrawingContext &context,
122  const wxRect & r, const ZoomInfo &zoomInfo,
123  bool dB, double dBRange,
124  float zoomMin, float zoomMax, bool mirrored) const;
125 
126  // Handling Cut/Copy/Paste events
127  // sampleDur determines when the endpoint of the collapse is near enough
128  // to an endpoint of the domain, that an extra control point is not needed.
129  void CollapseRegion(double t0, double t1, double sampleDur);
130 
131  // Envelope has no notion of rate and control point times are not quantized;
132  // but a tolerance is needed in the Paste routine, and better to inform it
133  // of an appropriate number, than use hidden arbitrary constants.
134  void Paste(double t0, const Envelope *e, double sampleDur);
135 
136  void InsertSpace(double t0, double tlen);
137 
138  // Control
139  void SetOffset(double newOffset);
140  void SetTrackLen( double trackLen, double sampleDur = 0.0 );
141  void RescaleValues(double minValue, double maxValue);
142  void RescaleTimes( double newLength );
143 
144  // Accessors
146  double GetValue( double t, double sampleDur = 0 ) const;
147 
152  void GetValues(double *buffer, int len, double t0, double tstep) const;
153 
157  void GetValues
158  ( double aligned_time, double sampleDur,
159  double *buffer, int bufferLen, int leftOffset,
160  const ZoomInfo &zoomInfo) const;
161 
162  // Guarantee an envelope point at the end of the domain.
163  void Cap( double sampleDur );
164 
165 private:
166  std::pair< int, int > ExpandRegion
167  ( double t0, double tlen, double *pLeftVal, double *pRightVal );
168 
170  ( size_t startAt, bool rightward, bool testNeighbors = true );
171 
172  double GetValueRelative(double t, bool leftLimit = false) const;
173  void GetValuesRelative
174  (double *buffer, int len, double t0, double tstep, bool leftLimit = false)
175  const;
176  // relative time
177  int NumberOfPointsAfter(double t) const;
178  // relative time
179  double NextPointAfter(double t) const;
180 
181 public:
182  double Average( double t0, double t1 ) const;
183  double AverageOfInverse( double t0, double t1 ) const;
184  double Integral( double t0, double t1 ) const;
185  double IntegralOfInverse( double t0, double t1 ) const;
186  double SolveIntegralOfInverse( double t0, double area) const;
187 
188  void print() const;
189  void testMe();
190 
191  bool IsDirty() const;
192 
194  int InsertOrReplace(double when, double value)
195  { return InsertOrReplaceRelative( when - mOffset, value ); }
196 
200  int Reassign(double when, double value);
201 
203  void Delete(int point);
204 
206  void Insert(int point, const EnvPoint &p);
207 
209  size_t GetNumberOfPoints() const;
210 
211 private:
212  int InsertOrReplaceRelative(double when, double value);
213 
214  friend class EnvelopeEditor;
216  const EnvPoint &operator[] (int index) const
217  {
218  return mEnv[index];
219  }
220 
221  std::pair<int, int> EqualRange( double when, double sampleDur ) const;
222 
223 public:
225  void GetPoints(double *bufferWhen,
226  double *bufferValue,
227  int bufferLen) const;
228 
229  // UI-related
230  // The drag point needs to display differently.
231  int GetDragPoint() const { return mDragPoint; }
232  // Choose the drag point.
233  void SetDragPoint(int dragPoint);
234  // Mark or unmark the drag point for deletion.
235  void SetDragPointValid(bool valid);
236  bool GetDragPointValid() const { return mDragPointValid; }
237  // Modify the dragged point and change its value.
238  // But consistency constraints may move it less then you ask for.
239 
240 private:
241  void MoveDragPoint(double newWhen, double value);
242  // May delete the drag point. Restores envelope consistency.
243  void ClearDragPoint();
244  void AddPointAtEnd( double t, double val );
245  void CopyRange(const Envelope &orig, size_t begin, size_t end);
246  // relative time
247  void BinarySearchForTime( int &Lo, int &Hi, double t ) const;
248  void BinarySearchForTime_LeftLimit( int &Lo, int &Hi, double t ) const;
249  double GetInterpolationStartValueAtPoint( int iPoint ) const;
250 
251  // The list of envelope control points.
252  EnvArray mEnv;
253 
255  double mOffset { 0.0 };
258  double mTrackLen { 0.0 };
259 
260  // TODO: mTrackEpsilon based on assumption of 200KHz. Needs review if/when
261  // we support higher sample rates.
264  double mTrackEpsilon { 1.0 / 200000.0 };
265  bool mDB;
268 
269  // UI stuff
270  bool mDragPointValid { false };
271  int mDragPoint { -1 };
272 
273  mutable int mSearchGuess { -2 };
274  friend class GetInfoCommand;
275  friend class SetEnvelopeCommand;
276 };
277 
278 inline void EnvPoint::SetVal( Envelope *pEnvelope, double val )
279 {
280  if ( pEnvelope )
281  val = pEnvelope->ClampValue(val);
282  mVal = val;
283 }
284 
285 // A class that holds state for the duration of dragging
286 // of an envelope point.
288 {
289 public:
290  EnvelopeEditor(Envelope &envelope, bool mirrored);
291  ~EnvelopeEditor();
292 
293  // Event Handlers
294  // Each of these returns true if the envelope needs to be redrawn
295  bool MouseEvent(const wxMouseEvent & event, wxRect & r,
296  const ZoomInfo &zoomInfo, bool dB, double dBRange,
297  float zoomMin = -1.0, float zoomMax = 1.0);
298 
299 private:
300  bool HandleMouseButtonDown(const wxMouseEvent & event, wxRect & r,
301  const ZoomInfo &zoomInfo, bool dB, double dBRange,
302  float zoomMin = -1.0, float zoomMax = 1.0);
303  bool HandleDragging(const wxMouseEvent & event, wxRect & r,
304  const ZoomInfo &zoomInfo, bool dB, double dBRange,
305  float zoomMin = -1.0, float zoomMax = 1.0, float eMin = 0., float eMax = 2.);
306  bool HandleMouseButtonUp();
307 
308 private:
309  float ValueOfPixel(int y, int height, bool upper,
310  bool dB, double dBRange,
311  float zoomMin, float zoomMax);
312  void MoveDragPoint(const wxMouseEvent & event, wxRect & r,
313  const ZoomInfo &zoomInfo, bool dB, double dBRange,
314  float zoomMin, float zoomMax);
315 
317  const bool mMirrored;
318 
321 
322  // double mInitialVal;
323 
324  // int mInitialY;
325  bool mUpper;
326  int mButton;
327  bool mDirty;
328 };
329 
330 #endif
double mMaxValue
Definition: Envelope.h:266
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:317
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:41
EnvPoint(double t, double val)
Definition: Envelope.h:39
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:258
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:264
size_t GetNumberOfPoints() const
Return number of points.
Definition: Envelope.cpp:980
bool mDB
Definition: Envelope.h:265
Command that sets envelope information.
void SetOffset(double newOffset)
Definition: Envelope.cpp:1071
int mSearchGuess
Definition: Envelope.h:273
XMLTagHandler * HandleXMLChild(const wxChar *WXUNUSED(tag)) override
Definition: Envelope.h:63
double GetMinValue() const
Definition: Envelope.h:103
void Initialize(int numPoints)
double mMinValue
Definition: Envelope.h:266
void SetExponential(bool db)
Definition: Envelope.h:99
Envelope(bool exponential, double minValue, double maxValue, double defaultValue)
Definition: Envelope.cpp:48
double mVal
Definition: Envelope.h:70
XMLTagHandler * HandleXMLChild(const wxChar *tag) override
Definition: Envelope.cpp:418
int GetDragPoint() const
Definition: Envelope.h:231
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:77
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:96
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
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:104
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
Definition: Internat.cpp:122
void RescaleTimes(double newLength)
Definition: Envelope.cpp:1098
Envelope & mEnvelope
Definition: Envelope.h:316
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:194
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:320
const EnvPoint & operator[](int index) const
Accessor for points.
Definition: Envelope.h:216
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:70
int mDragPoint
Definition: Envelope.h:271
double mT
Definition: Envelope.h:69
void SetT(double t)
Definition: Envelope.h:42
int min(int a, int b)
std::vector< EnvPoint > EnvArray
Definition: Envelope.h:74
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:255
void SetVal(Envelope *pEnvelope, double val)
Definition: Envelope.h:278
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:107
EnvPoint()
Definition: Envelope.h:38
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:46
double GetVal() const
Definition: Envelope.h:43
bool GetDragPointValid() const
Definition: Envelope.h:236
void SetRange(double minValue, double maxValue)
Definition: Envelope.cpp:221
void Insert(int point, const EnvPoint &p)
insert a point
Definition: Envelope.cpp:653
bool mDragPointValid
Definition: Envelope.h:270
double mDefaultValue
Definition: Envelope.h:267
bool IsDirty() const
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
EnvArray mEnv
Definition: Envelope.h:252
bool GetExponential() const
Definition: Envelope.h:98
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:35
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
Command which outputs a list of available menu commands on the status channel.
EnvelopeEditor(Envelope &envelope, bool mirrored)
Definition: Envelope.cpp:1799
double GetOffset() const
Definition: Envelope.h:95