Audacity  2.2.2
Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
Envelope Class Referencefinal

Draggable curve used in TrackPanel for varying amplification. More...

#include <Envelope.h>

Inheritance diagram for Envelope:
XMLTagHandler

Public Member Functions

 Envelope (bool exponential, double minValue, double maxValue, double defaultValue)
 
 Envelope (const Envelope &orig)
 
 Envelope (const Envelope &orig, double t0, double t1)
 
void Initialize (int numPoints)
 
virtual ~Envelope ()
 
bool ConsistencyCheck ()
 
double GetOffset () const
 
double GetTrackLen () const
 
bool GetExponential () const
 
void SetExponential (bool db)
 
void Flatten (double value)
 
double GetMinValue () const
 
double GetMaxValue () const
 
void SetRange (double minValue, double maxValue)
 
double ClampValue (double value)
 
bool HandleXMLTag (const wxChar *tag, const wxChar **attrs) override
 
XMLTagHandlerHandleXMLChild (const wxChar *tag) override
 
void WriteXML (XMLWriter &xmlFile) const
 
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. More...
 
void CollapseRegion (double t0, double t1, double sampleDur)
 
void Paste (double t0, const Envelope *e, double sampleDur)
 
void InsertSpace (double t0, double tlen)
 
void SetOffset (double newOffset)
 
void SetTrackLen (double trackLen, double sampleDur=0.0)
 
void RescaleValues (double minValue, double maxValue)
 
void RescaleTimes (double newLength)
 
double GetValue (double t, double sampleDur=0) const
 Get envelope value at time t. More...
 
void GetValues (double *buffer, int len, double t0, double tstep) const
 Get many envelope points at once. More...
 
void GetValues (double aligned_time, double sampleDur, double *buffer, int bufferLen, int leftOffset, const ZoomInfo &zoomInfo) const
 Get many envelope points for pixel columns at once, but don't assume uniform time per pixel. More...
 
void Cap (double sampleDur)
 
double Average (double t0, double t1) const
 
double AverageOfInverse (double t0, double t1) const
 
double Integral (double t0, double t1) const
 
double IntegralOfInverse (double t0, double t1) const
 
double SolveIntegralOfInverse (double t0, double area) const
 
void print () const
 
void testMe ()
 
bool IsDirty () const
 
int InsertOrReplace (double when, double value)
 Add a point at a particular absolute time coordinate. More...
 
int Reassign (double when, double value)
 Move a point at when to value. More...
 
void Delete (int point)
 DELETE a point by its position in array. More...
 
void Insert (int point, const EnvPoint &p)
 insert a point More...
 
size_t GetNumberOfPoints () const
 Return number of points. More...
 
void GetPoints (double *bufferWhen, double *bufferValue, int bufferLen) const
 Returns the sets of when and value pairs. More...
 
int GetDragPoint () const
 
void SetDragPoint (int dragPoint)
 
void SetDragPointValid (bool valid)
 
bool GetDragPointValid () const
 
- Public Member Functions inherited from XMLTagHandler
 XMLTagHandler ()
 
virtual ~XMLTagHandler ()
 
virtual void HandleXMLEndTag (const wxChar *WXUNUSED(tag))
 
virtual void HandleXMLContent (const wxString &WXUNUSED(content))
 
bool ReadXMLTag (const char *tag, const char **attrs)
 
void ReadXMLEndTag (const char *tag)
 
void ReadXMLContent (const char *s, int len)
 
XMLTagHandlerReadXMLChild (const char *tag)
 

Private Member Functions

std::pair< int, int > ExpandRegion (double t0, double tlen, double *pLeftVal, double *pRightVal)
 
void RemoveUnneededPoints (size_t startAt, bool rightward, bool testNeighbors=true)
 
double GetValueRelative (double t, bool leftLimit=false) const
 
void GetValuesRelative (double *buffer, int len, double t0, double tstep, bool leftLimit=false) const
 
int NumberOfPointsAfter (double t) const
 
double NextPointAfter (double t) const
 
int InsertOrReplaceRelative (double when, double value)
 Add a control point to the envelope. More...
 
const EnvPointoperator[] (int index) const
 Accessor for points. More...
 
std::pair< int, int > EqualRange (double when, double sampleDur) const
 
void MoveDragPoint (double newWhen, double value)
 
void ClearDragPoint ()
 
void AddPointAtEnd (double t, double val)
 
void CopyRange (const Envelope &orig, size_t begin, size_t end)
 
void BinarySearchForTime (int &Lo, int &Hi, double t) const
 
void BinarySearchForTime_LeftLimit (int &Lo, int &Hi, double t) const
 
double GetInterpolationStartValueAtPoint (int iPoint) const
 

Private Attributes

EnvArray mEnv
 
double mOffset { 0.0 }
 The time at which the envelope starts, i.e. the start offset. More...
 
double mTrackLen { 0.0 }
 The length of the envelope, which is the same as the length of the underlying track (normally) More...
 
double mTrackEpsilon { 1.0 / 200000.0 }
 The shortest distance appart that points on an envelope can be before being considered the same point. More...
 
bool mDB
 
double mMinValue
 
double mMaxValue
 
double mDefaultValue
 
bool mDragPointValid { false }
 
int mDragPoint { -1 }
 
int mSearchGuess { -2 }
 

Friends

class EnvelopeEditor
 
class GetInfoCommand
 
class SetEnvelopeCommand
 

Detailed Description

Draggable curve used in TrackPanel for varying amplification.

This class manages an envelope - i.e. a piecewise linear funtion that the user can edit by dragging control points around. The envelope is most commonly used to control the amplitude of a waveform, but it is also used to shape the Equalization curve.

Definition at line 77 of file Envelope.h.

Constructor & Destructor Documentation

Envelope::Envelope ( bool  exponential,
double  minValue,
double  maxValue,
double  defaultValue 
)

Definition at line 48 of file Envelope.cpp.

References ClampValue().

49  : mDB(exponential)
50  , mMinValue(minValue)
51  , mMaxValue(maxValue)
52  , mDefaultValue { ClampValue(defaultValue) }
53 {
54 }
double mMaxValue
Definition: Envelope.h:266
bool mDB
Definition: Envelope.h:265
double mMinValue
Definition: Envelope.h:266
double ClampValue(double value)
Definition: Envelope.h:107
double mDefaultValue
Definition: Envelope.h:267
Envelope::Envelope ( const Envelope orig)

Definition at line 262 of file Envelope.cpp.

References CopyRange(), GetNumberOfPoints(), mOffset, and mTrackLen.

263  : mDB(orig.mDB)
264  , mMinValue(orig.mMinValue)
265  , mMaxValue(orig.mMaxValue)
267 {
268  mOffset = orig.mOffset;
269  mTrackLen = orig.mTrackLen;
270  CopyRange(orig, 0, orig.GetNumberOfPoints());
271 }
double mMaxValue
Definition: Envelope.h:266
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
size_t GetNumberOfPoints() const
Return number of points.
Definition: Envelope.cpp:980
bool mDB
Definition: Envelope.h:265
double mMinValue
Definition: Envelope.h:266
void CopyRange(const Envelope &orig, size_t begin, size_t end)
Definition: Envelope.cpp:273
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
double mDefaultValue
Definition: Envelope.h:267
Envelope::Envelope ( const Envelope orig,
double  t0,
double  t1 
)

Definition at line 248 of file Envelope.cpp.

References CopyRange(), EqualRange(), mOffset, and mTrackLen.

249  : mDB(orig.mDB)
250  , mMinValue(orig.mMinValue)
251  , mMaxValue(orig.mMaxValue)
253 {
254  mOffset = wxMax(t0, orig.mOffset);
255  mTrackLen = wxMin(t1, orig.mOffset + orig.mTrackLen) - mOffset;
256 
257  auto range1 = orig.EqualRange( t0 - orig.mOffset, 0 );
258  auto range2 = orig.EqualRange( t1 - orig.mOffset, 0 );
259  CopyRange(orig, range1.first, range2.second);
260 }
double mMaxValue
Definition: Envelope.h:266
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
bool mDB
Definition: Envelope.h:265
double mMinValue
Definition: Envelope.h:266
void CopyRange(const Envelope &orig, size_t begin, size_t end)
Definition: Envelope.cpp:273
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
double mDefaultValue
Definition: Envelope.h:267
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
Envelope::~Envelope ( )
virtual

Definition at line 56 of file Envelope.cpp.

57 {
58 }

Member Function Documentation

void Envelope::AddPointAtEnd ( double  t,
double  val 
)
private

Definition at line 231 of file Envelope.cpp.

References mEnv.

Referenced by CopyRange(), and SetTrackLen().

232 {
233  mEnv.push_back( EnvPoint{ t, val } );
234 
235  // Assume copied points were stored by nondecreasing time.
236  // Allow no more than two points at exactly the same time.
237  // Maybe that happened, because extra points were inserted at the boundary
238  // of the copied range, which were not in the source envelope.
239  auto nn = mEnv.size() - 1;
240  while ( nn >= 2 && mEnv[ nn - 2 ].GetT() == t ) {
241  // Of three or more points at the same time, erase one in the middle,
242  // not the one newly added.
243  mEnv.erase( mEnv.begin() + nn - 1 );
244  --nn;
245  }
246 }
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
double Envelope::Average ( double  t0,
double  t1 
) const

Definition at line 1400 of file Envelope.cpp.

References GetValue(), and Integral().

1401 {
1402  if( t0 == t1 )
1403  return GetValue( t0 );
1404  else
1405  return Integral( t0, t1 ) / (t1 - t0);
1406 }
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:1114
double Integral(double t0, double t1) const
Definition: Envelope.cpp:1499
double Envelope::AverageOfInverse ( double  t0,
double  t1 
) const

Definition at line 1408 of file Envelope.cpp.

References GetValue(), and IntegralOfInverse().

Referenced by TimeTrack::ComputeWarpFactor().

1409 {
1410  if( t0 == t1 )
1411  return 1.0 / GetValue( t0 );
1412  else
1413  return IntegralOfInverse( t0, t1 ) / (t1 - t0);
1414 }
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1562
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:1114
void Envelope::BinarySearchForTime ( int &  Lo,
int &  Hi,
double  t 
) const
private
Parameters
Loreturns last index at or before this time, maybe -1
Hireturns first index after this time, maybe past the end

Definition at line 1134 of file Envelope.cpp.

References mEnv, and mSearchGuess.

Referenced by Integral(), IntegralOfInverse(), NextPointAfter(), NumberOfPointsAfter(), and SolveIntegralOfInverse().

1135 {
1136  // Optimizations for the usual pattern of repeated calls with
1137  // small increases of t.
1138  {
1139  if (mSearchGuess >= 0 && mSearchGuess < (int)mEnv.size()) {
1140  if (t >= mEnv[mSearchGuess].GetT() &&
1141  (1 + mSearchGuess == (int)mEnv.size() ||
1142  t < mEnv[1 + mSearchGuess].GetT())) {
1143  Lo = mSearchGuess;
1144  Hi = 1 + mSearchGuess;
1145  return;
1146  }
1147  }
1148 
1149  ++mSearchGuess;
1150  if (mSearchGuess >= 0 && mSearchGuess < (int)mEnv.size()) {
1151  if (t >= mEnv[mSearchGuess].GetT() &&
1152  (1 + mSearchGuess == (int)mEnv.size() ||
1153  t < mEnv[1 + mSearchGuess].GetT())) {
1154  Lo = mSearchGuess;
1155  Hi = 1 + mSearchGuess;
1156  return;
1157  }
1158  }
1159  }
1160 
1161  Lo = -1;
1162  Hi = mEnv.size();
1163 
1164  // Invariants: Lo is not less than -1, Hi not more than size
1165  while (Hi > (Lo + 1)) {
1166  int mid = (Lo + Hi) / 2;
1167  // mid must be strictly between Lo and Hi, therefore a valid index
1168  if (t < mEnv[mid].GetT())
1169  Hi = mid;
1170  else
1171  Lo = mid;
1172  }
1173  wxASSERT( Hi == ( Lo+1 ));
1174 
1175  mSearchGuess = Lo;
1176 }
int mSearchGuess
Definition: Envelope.h:273
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::BinarySearchForTime_LeftLimit ( int &  Lo,
int &  Hi,
double  t 
) const
private
Parameters
Loreturns last index before this time, maybe -1
Hireturns first index at or after this time, maybe past the end

Definition at line 1181 of file Envelope.cpp.

References mEnv, and mSearchGuess.

1182 {
1183  Lo = -1;
1184  Hi = mEnv.size();
1185 
1186  // Invariants: Lo is not less than -1, Hi not more than size
1187  while (Hi > (Lo + 1)) {
1188  int mid = (Lo + Hi) / 2;
1189  // mid must be strictly between Lo and Hi, therefore a valid index
1190  if (t <= mEnv[mid].GetT())
1191  Hi = mid;
1192  else
1193  Lo = mid;
1194  }
1195  wxASSERT( Hi == ( Lo+1 ));
1196 
1197  mSearchGuess = Lo;
1198 }
int mSearchGuess
Definition: Envelope.h:273
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::Cap ( double  sampleDur)

Definition at line 999 of file Envelope.cpp.

References EqualRange(), GetValueRelative(), InsertOrReplaceRelative(), and mTrackLen.

1000 {
1001  auto range = EqualRange( mTrackLen, sampleDur );
1002  if ( range.first == range.second )
1004 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
int InsertOrReplaceRelative(double when, double value)
Add a control point to the envelope.
Definition: Envelope.cpp:1014
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
double Envelope::ClampValue ( double  value)
inline

Definition at line 107 of file Envelope.h.

References min(), mMaxValue, and mMinValue.

Referenced by Envelope(), Flatten(), RescaleValues(), SetRange(), EnvPoint::SetVal(), and EnvelopeEditor::ValueOfPixel().

107 { return std::max(mMinValue, std::min(mMaxValue, value)); }
double mMaxValue
Definition: Envelope.h:266
double mMinValue
Definition: Envelope.h:266
int min(int a, int b)
void Envelope::ClearDragPoint ( )
private

Definition at line 212 of file Envelope.cpp.

References Delete(), mDragPoint, and mDragPointValid.

Referenced by EnvelopeEditor::HandleMouseButtonUp().

213 {
214  if (!mDragPointValid && mDragPoint >= 0)
216 
217  mDragPoint = -1;
218  mDragPointValid = false;
219 }
void Delete(int point)
DELETE a point by its position in array.
Definition: Envelope.cpp:648
int mDragPoint
Definition: Envelope.h:271
bool mDragPointValid
Definition: Envelope.h:270
void Envelope::CollapseRegion ( double  t0,
double  t1,
double  sampleDur 
)

Definition at line 674 of file Envelope.cpp.

References EqualRange(), GetValueRelative(), InsertOrReplaceRelative(), mEnv, min(), mOffset, mTrackLen, and RemoveUnneededPoints().

676 {
677  if ( t1 <= t0 )
678  return;
679 
680  // This gets called when somebody clears samples.
681 
682  // Snip points in the interval (t0, t1), shift values left at times after t1.
683  // For the boundaries of the interval, preserve the left-side limit at the
684  // start and right-side limit at the end.
685 
686  const auto epsilon = sampleDur / 2;
687  t0 = std::max( 0.0, std::min( mTrackLen, t0 - mOffset ) );
688  t1 = std::max( 0.0, std::min( mTrackLen, t1 - mOffset ) );
689  bool leftPoint = true, rightPoint = true;
690 
691  // Determine the start of the range of points to remove from the array.
692  auto range0 = EqualRange( t0, 0 );
693  auto begin = range0.first;
694  if ( begin == range0.second ) {
695  if ( t0 > epsilon ) {
696  // There was no point exactly at t0;
697  // insert a point to preserve the value.
698  auto val = GetValueRelative( t0 );
699  InsertOrReplaceRelative( t0, val );
700  ++begin;
701  }
702  else
703  leftPoint = false;
704  }
705  else
706  // We will keep the first (or only) point that was at t0.
707  ++begin;
708 
709  // We want end to be the index one past the range of points to remove from
710  // the array.
711  // At first, find index of the first point after t1:
712  auto range1 = EqualRange( t1, 0 );
713  auto end = range1.second;
714  if ( range1.first == end ) {
715  if ( mTrackLen - t1 > epsilon ) {
716  // There was no point exactly at t1; insert a point to preserve the value.
717  auto val = GetValueRelative( t1 );
718  InsertOrReplaceRelative( t1, val );
719  // end is now the index of this NEW point and that is correct.
720  }
721  else
722  rightPoint = false;
723  }
724  else
725  // We will keep the last (or only) point that was at t1.
726  --end;
727 
728  mEnv.erase( mEnv.begin() + begin, mEnv.begin() + end );
729 
730  // Shift points left after deleted region.
731  auto len = mEnv.size();
732  for ( size_t i = begin; i < len; ++i ) {
733  auto &point = mEnv[i];
734  if (rightPoint && (int)i == begin)
735  // Avoid roundoff error.
736  // Make exactly equal times of neighboring points so that we have
737  // a real discontinuity.
738  point.SetT( t0 );
739  else
740  point.SetT( point.GetT() - (t1 - t0) );
741  }
742 
743  // See if the discontinuity is removable.
744  if ( rightPoint )
745  RemoveUnneededPoints( begin, true );
746  if ( leftPoint )
747  RemoveUnneededPoints( begin - 1, false );
748 
749  mTrackLen -= ( t1 - t0 );
750 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
void RemoveUnneededPoints(size_t startAt, bool rightward, bool testNeighbors=true)
Definition: Envelope.cpp:834
int InsertOrReplaceRelative(double when, double value)
Add a control point to the envelope.
Definition: Envelope.cpp:1014
int min(int a, int b)
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
EnvArray mEnv
Definition: Envelope.h:252
bool Envelope::ConsistencyCheck ( )

Definition at line 60 of file Envelope.cpp.

References Delete(), EnvPoint::GetT(), mDragPoint, and mEnv.

Referenced by Paste().

61 {
62  bool consistent = true;
63 
64  bool disorder;
65  do {
66  disorder = false;
67  for ( size_t ii = 0, count = mEnv.size(); ii < count; ) {
68  // Find range of points with equal T
69  const double thisT = mEnv[ii].GetT();
70  double nextT = 0.0f;
71  auto nextI = ii + 1;
72  while ( nextI < count && thisT == ( nextT = mEnv[nextI].GetT() ) )
73  ++nextI;
74 
75  if ( nextI < count && nextT < thisT )
76  disorder = true;
77 
78  while ( nextI - ii > 2 ) {
79  // too many coincident time values
80  if ((int)ii == mDragPoint || (int)nextI - 1 == mDragPoint)
81  // forgivable
82  ;
83  else {
84  consistent = false;
85  // repair it
86  Delete( nextI - 2 );
87  if (mDragPoint >= (int)nextI - 2)
88  --mDragPoint;
89  --nextI, --count;
90  // wxLogError
91  }
92  }
93 
94  ii = nextI;
95  }
96 
97  if (disorder) {
98  consistent = false;
99  // repair it
100  std::stable_sort( mEnv.begin(), mEnv.end(),
101  []( const EnvPoint &a, const EnvPoint &b )
102  { return a.GetT() < b.GetT(); } );
103  }
104  } while ( disorder );
105 
106  return consistent;
107 }
double GetT() const
Definition: Envelope.h:41
void Delete(int point)
DELETE a point by its position in array.
Definition: Envelope.cpp:648
int mDragPoint
Definition: Envelope.h:271
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
void Envelope::CopyRange ( const Envelope orig,
size_t  begin,
size_t  end 
)
private

Definition at line 273 of file Envelope.cpp.

References AddPointAtEnd(), EnvPoint::GetT(), EnvPoint::GetVal(), GetValue(), mEnv, mOffset, and mTrackLen.

Referenced by Envelope().

274 {
275  size_t len = orig.mEnv.size();
276  size_t i = begin;
277 
278  // Create the point at 0 if it needs interpolated representation
279  if ( i > 0 )
280  AddPointAtEnd(0, orig.GetValue(mOffset));
281 
282  // Copy points from inside the copied region
283  for (; i < end; ++i) {
284  const EnvPoint &point = orig[i];
285  const double when = point.GetT() + (orig.mOffset - mOffset);
286  AddPointAtEnd(when, point.GetVal());
287  }
288 
289  // Create the final point if it needs interpolated representation
290  // If the last point of e was exatly at t1, this effectively copies it too.
291  if (mTrackLen > 0 && i < len)
293 }
double GetT() const
Definition: Envelope.h:41
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
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 AddPointAtEnd(double t, double val)
Definition: Envelope.cpp:231
double GetVal() const
Definition: Envelope.h:43
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
void Envelope::Delete ( int  point)

DELETE a point by its position in array.

Definition at line 648 of file Envelope.cpp.

References mEnv.

Referenced by ClearDragPoint(), and ConsistencyCheck().

649 {
650  mEnv.erase(mEnv.begin() + point);
651 }
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::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 at line 322 of file Envelope.cpp.

References TrackPanelDrawingContext::dc, DrawPoint(), AColor::envelopeBrush, AColor::envelopePen, EnvelopeHandle::GetEnvelope(), GetWaveYPos(), TrackPanelDrawingContext::target, ZoomInfo::TimeToPosition(), and AColor::uglyPen.

Referenced by TrackArtist::DrawClipWaveform(), TrackArtist::DrawTimeTrack(), and EqualizationPanel::OnPaint().

325 {
326  auto &dc = context.dc;
327  bool highlight = false;
328 #ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
329  auto target = dynamic_cast<EnvelopeHandle*>(context.target.get());
330  highlight = target && target->GetEnvelope() == this;
331 #endif
332  wxPen &pen = highlight ? AColor::uglyPen : AColor::envelopePen;
333  dc.SetPen( pen );
334  dc.SetBrush(*wxWHITE_BRUSH);
335 
336  for (int i = 0; i < (int)mEnv.size(); i++) {
337  const double time = mEnv[i].GetT() + mOffset;
338  const wxInt64 position = zoomInfo.TimeToPosition(time);
339  if (position >= 0 && position < r.width) {
340  // Change colour if this is the draggable point...
341  if (i == mDragPoint) {
342  dc.SetPen( pen );
343  dc.SetBrush(AColor::envelopeBrush);
344  }
345 
346  double v = mEnv[i].GetVal();
347  int x = (int)(position);
348  int y, y2;
349 
350  y = GetWaveYPos(v, zoomMin, zoomMax, r.height, dB,
351  true, dBRange, false);
352  if (!mirrored) {
353  DrawPoint(dc, r, x, y, true);
354  }
355  else {
356  y2 = GetWaveYPos(-v-.000000001, zoomMin, zoomMax, r.height, dB,
357  true, dBRange, false);
358 
359  // This follows the same logic as the envelop drawing in
360  // TrackArtist::DrawEnvelope().
361  // TODO: make this calculation into a reusable function.
362  if (y2 - y < 9) {
363  int value = (int)((zoomMax / (zoomMax - zoomMin)) * r.height);
364  y = value - 4;
365  y2 = value + 4;
366  }
367 
368  DrawPoint(dc, r, x, y, true);
369  DrawPoint(dc, r, x, y2, false);
370 
371  // Contour
372  y = GetWaveYPos(v, zoomMin, zoomMax, r.height, dB,
373  false, dBRange, false);
374  y2 = GetWaveYPos(-v-.000000001, zoomMin, zoomMax, r.height, dB,
375  false, dBRange, false);
376  if (y <= y2) {
377  DrawPoint(dc, r, x, y, true);
378  DrawPoint(dc, r, x, y2, false);
379  }
380  }
381 
382  // Change colour back again if was the draggable point.
383  if (i == mDragPoint) {
384  dc.SetPen( pen );
385  dc.SetBrush(*wxWHITE_BRUSH);
386  }
387  }
388  }
389 }
static wxPen uglyPen
Definition: AColor.h:147
static wxPen envelopePen
Definition: AColor.h:122
int mDragPoint
Definition: Envelope.h:271
wxInt64 TimeToPosition(double time, wxInt64 origin=0, bool ignoreFisheye=false) const
STM: Converts a project time to screen x position.
Definition: ViewInfo.cpp:59
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
static wxBrush envelopeBrush
Definition: AColor.h:124
Envelope * GetEnvelope() const
int GetWaveYPos(float value, float min, float max, int height, bool dB, bool outer, float dBr, bool clip)
EnvArray mEnv
Definition: Envelope.h:252
static void DrawPoint(wxDC &dc, const wxRect &r, int x, int y, bool top)
TODO: This should probably move to track artist.
Definition: Envelope.cpp:309
std::pair< int, int > Envelope::EqualRange ( double  when,
double  sampleDur 
) const
private

Definition at line 1048 of file Envelope.cpp.

References EnvPoint::GetT(), and mEnv.

Referenced by Cap(), CollapseRegion(), Envelope(), InsertOrReplaceRelative(), Paste(), and SetTrackLen().

1049 {
1050  // Find range of envelope points matching the given time coordinate
1051  // (within an interval of length sampleDur)
1052  // by binary search; if empty, it still indicates where to
1053  // insert.
1054  const auto tolerance = sampleDur / 2;
1055  auto begin = mEnv.begin();
1056  auto end = mEnv.end();
1057  auto first = std::lower_bound(
1058  begin, end,
1059  EnvPoint{ when - tolerance, 0.0 },
1060  []( const EnvPoint &point1, const EnvPoint &point2 )
1061  { return point1.GetT() < point2.GetT(); }
1062  );
1063  auto after = first;
1064  while ( after != end && after->GetT() <= when + tolerance )
1065  ++after;
1066  return { first - begin, after - begin };
1067 }
double GetT() const
Definition: Envelope.h:41
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
std::pair< int, int > Envelope::ExpandRegion ( double  t0,
double  tlen,
double *  pLeftVal,
double *  pRightVal 
)
private

Definition at line 900 of file Envelope.cpp.

Referenced by InsertSpace(), and Paste().

902 {
903  // t0 is relative time
904 
905  double val = GetValueRelative( t0 );
906  const auto range = EqualRange( t0, 0 );
907 
908  // Preserve the left-side limit.
909  int index = 1 + range.first;
910  if ( index <= range.second )
911  // There is already a control point.
912  ;
913  else {
914  // Make a control point.
915  Insert( range.first, EnvPoint{ t0, val } );
916  }
917 
918  // Shift points.
919  auto len = mEnv.size();
920  for ( unsigned int ii = index; ii < len; ++ii ) {
921  auto &point = mEnv[ ii ];
922  point.SetT( point.GetT() + tlen );
923  }
924 
925  mTrackLen += tlen;
926 
927  // Preserve the right-side limit.
928  if ( index < range.second )
929  // There was a control point already.
930  ;
931  else
932  // Make a control point.
933  Insert( index, EnvPoint{ t0 + tlen, val } );
934 
935  // Make discontinuities at ends, maybe:
936 
937  if ( pLeftVal )
938  // Make a discontinuity at the left side of the expansion
939  Insert( index++, EnvPoint{ t0, *pLeftVal } );
940 
941  if ( pRightVal )
942  // Make a discontinuity at the right side of the expansion
943  Insert( index++, EnvPoint{ t0 + tlen, *pRightVal } );
944 
945  // Return the range of indices that includes the inside limiting points,
946  // none, one, or two
947  return { 1 + range.first, index };
948 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
void Insert(int point, const EnvPoint &p)
insert a point
Definition: Envelope.cpp:653
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
void Envelope::Flatten ( double  value)

Flatten removes all points from the envelope to make it horizontal at a chosen y-value. - the y-value for the flat envelope.

Definition at line 137 of file Envelope.cpp.

References ClampValue(), mDefaultValue, and mEnv.

Referenced by EffectEqualization::GraphicEQ(), EffectEqualization::setCurve(), TimeTrack::testMe(), and testMe().

138 {
139  mEnv.clear();
140  mDefaultValue = ClampValue(value);
141 }
double ClampValue(double value)
Definition: Envelope.h:107
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
int Envelope::GetDragPoint ( ) const
inline

Definition at line 231 of file Envelope.h.

References mDragPoint.

Referenced by EnvelopeEditor::MouseEvent().

231 { return mDragPoint; }
int mDragPoint
Definition: Envelope.h:271
bool Envelope::GetDragPointValid ( ) const
inline

Definition at line 236 of file Envelope.h.

References mDragPointValid.

Referenced by EnvelopeEditor::HandleDragging().

236 { return mDragPointValid; }
bool mDragPointValid
Definition: Envelope.h:270
bool Envelope::GetExponential ( ) const
inline

Definition at line 98 of file Envelope.h.

References mDB.

98 { return mDB; }
bool mDB
Definition: Envelope.h:265
double Envelope::GetInterpolationStartValueAtPoint ( int  iPoint) const
private

GetInterpolationStartValueAtPoint() is used to select either the envelope value or its log depending on whether we are doing linear or log interpolation.

Parameters
iPointindex in env array to look at.
Returns
value there, or its (safe) log10.

Definition at line 1205 of file Envelope.cpp.

References mDB, and mEnv.

1206 {
1207  double v = mEnv[ iPoint ].GetVal();
1208  if( !mDB )
1209  return v;
1210  else
1211  return log10(v);
1212 }
bool mDB
Definition: Envelope.h:265
EnvArray mEnv
Definition: Envelope.h:252
double Envelope::GetMaxValue ( ) const
inline

Definition at line 104 of file Envelope.h.

References mMaxValue.

104 { return mMaxValue; }
double mMaxValue
Definition: Envelope.h:266
double Envelope::GetMinValue ( ) const
inline

Definition at line 103 of file Envelope.h.

References mMinValue.

103 { return mMinValue; }
double mMinValue
Definition: Envelope.h:266
size_t Envelope::GetNumberOfPoints ( ) const

Return number of points.

Definition at line 980 of file Envelope.cpp.

References mEnv.

Referenced by Envelope(), EffectEqualization::EnvelopeUpdated(), and EnvelopeEditor::HandleMouseButtonDown().

981 {
982  return mEnv.size();
983 }
EnvArray mEnv
Definition: Envelope.h:252
double Envelope::GetOffset ( ) const
inline

Definition at line 95 of file Envelope.h.

References mOffset.

Referenced by EnvelopeEditor::HandleMouseButtonDown(), and EnvelopeEditor::MoveDragPoint().

95 { return mOffset; }
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
void Envelope::GetPoints ( double *  bufferWhen,
double *  bufferValue,
int  bufferLen 
) const

Returns the sets of when and value pairs.

Definition at line 985 of file Envelope.cpp.

References mEnv, and mOffset.

Referenced by EffectEqualization::EnvelopeUpdated().

988 {
989  int n = mEnv.size();
990  if (n > bufferLen)
991  n = bufferLen;
992  int i;
993  for (i = 0; i < n; i++) {
994  bufferWhen[i] = mEnv[i].GetT() - mOffset;
995  bufferValue[i] = mEnv[i].GetVal();
996  }
997 }
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
EnvArray mEnv
Definition: Envelope.h:252
double Envelope::GetTrackLen ( ) const
inline

Definition at line 96 of file Envelope.h.

References mTrackLen.

96 { return mTrackLen; }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
double Envelope::GetValue ( double  t,
double  sampleDur = 0 
) const

Get envelope value at time t.

Definition at line 1114 of file Envelope.cpp.

References GetValues().

Referenced by Average(), AverageOfInverse(), CopyRange(), TrackArtist::DrawIndividualSamples(), SampleHandle::FindSampleEditingLevel(), EnvelopeEditor::HandleMouseButtonDown(), EnvelopeHandle::HitEnvelope(), SampleHandle::HitTest(), WaveTrack::Join(), and Paste().

1115 {
1116  // t is absolute time
1117  double temp;
1118 
1119  GetValues( &temp, 1, t, sampleDur );
1120  return temp;
1121 }
void GetValues(double *buffer, int len, double t0, double tstep) const
Get many envelope points at once.
Definition: Envelope.cpp:1214
double Envelope::GetValueRelative ( double  t,
bool  leftLimit = false 
) const
private

Definition at line 1123 of file Envelope.cpp.

References GetValuesRelative().

Referenced by Cap(), CollapseRegion(), Paste(), and SetTrackLen().

1124 {
1125  double temp;
1126 
1127  GetValuesRelative(&temp, 1, t, 0.0, leftLimit);
1128  return temp;
1129 }
void GetValuesRelative(double *buffer, int len, double t0, double tstep, bool leftLimit=false) const
Definition: Envelope.cpp:1223
void Envelope::GetValues ( double *  buffer,
int  len,
double  t0,
double  tstep 
) const

Get many envelope points at once.

This is much faster than calling GetValue() multiple times if you need more than one value in a row.

Definition at line 1214 of file Envelope.cpp.

References GetValuesRelative(), and mOffset.

Referenced by TrackArtist::DrawClipWaveform(), WaveTrack::GetEnvelopeValues(), GetValue(), and EqualizationPanel::OnPaint().

1216 {
1217  // Convert t0 from absolute to clip-relative time
1218  t0 -= mOffset;
1219  GetValuesRelative( buffer, bufferLen, t0, tstep);
1220 }
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
void GetValuesRelative(double *buffer, int len, double t0, double tstep, bool leftLimit=false) const
Definition: Envelope.cpp:1223
void Envelope::GetValues ( double  aligned_time,
double  sampleDur,
double *  buffer,
int  bufferLen,
int  leftOffset,
const ZoomInfo zoomInfo 
) const

Get many envelope points for pixel columns at once, but don't assume uniform time per pixel.

Definition at line 1339 of file Envelope.cpp.

References ZoomInfo::PositionToTime().

1343 {
1344  // Getting many envelope values, corresponding to pixel columns, which may
1345  // not be uniformly spaced in time when there is a fisheye.
1346 
1347  double prevDiscreteTime=0.0, prevSampleVal=0.0, nextSampleVal=0.0;
1348  for ( int xx = 0; xx < bufferLen; ++xx ) {
1349  auto time = zoomInfo.PositionToTime( xx, -leftOffset );
1350  if ( sampleDur <= 0 )
1351  // Sample interval not defined (as for time track)
1352  buffer[xx] = GetValue( time );
1353  else {
1354  // The level of zoom-in may resolve individual samples.
1355  // If so, then instead of evaluating the envelope directly,
1356  // we draw a piecewise curve with knees at each sample time.
1357  // This actually makes clearer what happens as you drag envelope
1358  // points and make discontinuities.
1359  auto leftDiscreteTime = alignedTime +
1360  sampleDur * floor( ( time - alignedTime ) / sampleDur );
1361  if ( xx == 0 || leftDiscreteTime != prevDiscreteTime ) {
1362  prevDiscreteTime = leftDiscreteTime;
1363  prevSampleVal =
1364  GetValue( prevDiscreteTime, sampleDur );
1365  nextSampleVal =
1366  GetValue( prevDiscreteTime + sampleDur, sampleDur );
1367  }
1368  auto ratio = ( time - leftDiscreteTime ) / sampleDur;
1369  if ( GetExponential() )
1370  buffer[ xx ] = exp(
1371  ( 1.0 - ratio ) * log( prevSampleVal )
1372  + ratio * log( nextSampleVal ) );
1373  else
1374  buffer[ xx ] =
1375  ( 1.0 - ratio ) * prevSampleVal + ratio * nextSampleVal;
1376  }
1377  }
1378 }
double PositionToTime(wxInt64 position, wxInt64 origin=0, bool ignoreFisheye=false) const
Definition: ViewInfo.cpp:49
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:1114
bool GetExponential() const
Definition: Envelope.h:98
void Envelope::GetValuesRelative ( double *  buffer,
int  len,
double  t0,
double  tstep,
bool  leftLimit = false 
) const
private

Definition at line 1223 of file Envelope.cpp.

Referenced by GetValueRelative(), and GetValues().

1225 {
1226  // JC: If bufferLen ==0 we have probably just allocated a zero sized buffer.
1227  // wxASSERT( bufferLen > 0 );
1228 
1229  const auto epsilon = tstep / 2;
1230  int len = mEnv.size();
1231 
1232  double t = t0;
1233  double increment = 0;
1234  if ( len > 1 && t <= mEnv[0].GetT() && mEnv[0].GetT() == mEnv[1].GetT() )
1235  increment = leftLimit ? -epsilon : epsilon;
1236 
1237  double tprev, vprev, tnext = 0, vnext, vstep = 0;
1238 
1239  for (int b = 0; b < bufferLen; b++) {
1240 
1241  // Get easiest cases out the way first...
1242  // IF empty envelope THEN default value
1243  if (len <= 0) {
1244  buffer[b] = mDefaultValue;
1245  t += tstep;
1246  continue;
1247  }
1248 
1249  auto tplus = t + increment;
1250 
1251  // IF before envelope THEN first value
1252  if ( leftLimit ? tplus <= mEnv[0].GetT() : tplus < mEnv[0].GetT() ) {
1253  buffer[b] = mEnv[0].GetVal();
1254  t += tstep;
1255  continue;
1256  }
1257  // IF after envelope THEN last value
1258  if ( leftLimit
1259  ? tplus > mEnv[len - 1].GetT() : tplus >= mEnv[len - 1].GetT() ) {
1260  buffer[b] = mEnv[len - 1].GetVal();
1261  t += tstep;
1262  continue;
1263  }
1264 
1265  // be careful to get the correct limit even in case epsilon == 0
1266  if ( b == 0 ||
1267  ( leftLimit ? tplus > tnext : tplus >= tnext ) ) {
1268 
1269  // We're beyond our tnext, so find the next one.
1270  // Don't just increment lo or hi because we might
1271  // be zoomed far out and that could be a large number of
1272  // points to move over. That's why we binary search.
1273 
1274  int lo,hi;
1275  if ( leftLimit )
1276  BinarySearchForTime_LeftLimit( lo, hi, tplus );
1277  else
1278  BinarySearchForTime( lo, hi, tplus );
1279 
1280  // mEnv[0] is before tplus because of eliminations above, therefore lo >= 0
1281  // mEnv[len - 1] is after tplus, therefore hi <= len - 1
1282  wxASSERT( lo >= 0 && hi <= len - 1 );
1283 
1284  tprev = mEnv[lo].GetT();
1285  tnext = mEnv[hi].GetT();
1286 
1287  if ( hi + 1 < len && tnext == mEnv[ hi + 1 ].GetT() )
1288  // There is a discontinuity after this point-to-point interval.
1289  // Usually will stop evaluating in this interval when time is slightly
1290  // before tNext, then use the right limit.
1291  // This is the right intent
1292  // in case small roundoff errors cause a sample time to be a little
1293  // before the envelope point time.
1294  // Less commonly we want a left limit, so we continue evaluating in
1295  // this interval until shortly after the discontinuity.
1296  increment = leftLimit ? -epsilon : epsilon;
1297  else
1298  increment = 0;
1299 
1300  vprev = GetInterpolationStartValueAtPoint( lo );
1301  vnext = GetInterpolationStartValueAtPoint( hi );
1302 
1303  // Interpolate, either linear or log depending on mDB.
1304  double dt = (tnext - tprev);
1305  double to = t - tprev;
1306  double v;
1307  if (dt > 0.0)
1308  {
1309  v = (vprev * (dt - to) + vnext * to) / dt;
1310  vstep = (vnext - vprev) * tstep / dt;
1311  }
1312  else
1313  {
1314  v = vnext;
1315  vstep = 0.0;
1316  }
1317 
1318  // An adjustment if logarithmic scale.
1319  if( mDB )
1320  {
1321  v = pow(10.0, v);
1322  vstep = pow( 10.0, vstep );
1323  }
1324 
1325  buffer[b] = v;
1326  } else {
1327  if (mDB){
1328  buffer[b] = buffer[b - 1] * vstep;
1329  }else{
1330  buffer[b] = buffer[b - 1] + vstep;
1331  }
1332  }
1333 
1334  t += tstep;
1335  }
1336 }
bool mDB
Definition: Envelope.h:265
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
void BinarySearchForTime_LeftLimit(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1181
double mDefaultValue
Definition: Envelope.h:267
double GetInterpolationStartValueAtPoint(int iPoint) const
Definition: Envelope.cpp:1205
EnvArray mEnv
Definition: Envelope.h:252
XMLTagHandler * Envelope::HandleXMLChild ( const wxChar *  tag)
overridevirtual

Implements XMLTagHandler.

Definition at line 418 of file Envelope.cpp.

References mEnv.

419 {
420  if (wxStrcmp(tag, wxT("controlpoint")))
421  return NULL;
422 
423  mEnv.push_back( EnvPoint{} );
424  return &mEnv.back();
425 }
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
bool Envelope::HandleXMLTag ( const wxChar *  tag,
const wxChar **  attrs 
)
overridevirtual

Implements XMLTagHandler.

Definition at line 391 of file Envelope.cpp.

References XMLValueChecker::IsGoodInt(), and mEnv.

392 {
393  // Return unless it's the envelope tag.
394  if (wxStrcmp(tag, wxT("envelope")))
395  return false;
396 
397  int numPoints = 0;
398  long nValue = -1;
399 
400  while (*attrs) {
401  const wxChar *attr = *attrs++;
402  const wxChar *value = *attrs++;
403  if (!value)
404  break;
405  const wxString strValue = value;
406  if( !wxStrcmp(attr, wxT("numpoints")) &&
407  XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue))
408  numPoints = nValue;
409  }
410  if (numPoints < 0)
411  return false;
412 
413  mEnv.clear();
414  mEnv.reserve(numPoints);
415  return true;
416 }
static bool IsGoodInt(const wxString &strInt)
Check that the supplied string can be converted to a long (32bit) integer.
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::Initialize ( int  numPoints)
void Envelope::Insert ( int  point,
const EnvPoint p 
)

insert a point

Definition at line 653 of file Envelope.cpp.

References mEnv.

Referenced by InsertOrReplaceRelative().

654 {
655  mEnv.insert(mEnv.begin() + point, p);
656 }
EnvArray mEnv
Definition: Envelope.h:252
int Envelope::InsertOrReplace ( double  when,
double  value 
)
inline

Add a point at a particular absolute time coordinate.

Definition at line 194 of file Envelope.h.

References InsertOrReplaceRelative(), and mOffset.

Referenced by SetEnvelopeCommand::ApplyInner(), EffectEqualization::GraphicEQ(), EnvelopeEditor::HandleMouseButtonDown(), EffectEqualization::setCurve(), and TimeTrack::testMe().

195  { return InsertOrReplaceRelative( when - mOffset, value ); }
int InsertOrReplaceRelative(double when, double value)
Add a control point to the envelope.
Definition: Envelope.cpp:1014
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
int Envelope::InsertOrReplaceRelative ( double  when,
double  value 
)
private

Add a control point to the envelope.

Parameters
whenthe time in seconds when the envelope point should be created.
valuethe envelope value to use at the given point.
Returns
the index of the NEW envelope point within array of envelope points.

Definition at line 1014 of file Envelope.cpp.

References EqualRange(), Insert(), mEnv, min(), and mTrackLen.

Referenced by Cap(), CollapseRegion(), InsertOrReplace(), and testMe().

1015 {
1016 #if defined(__WXDEBUG__)
1017  // in debug builds, do a spot of argument checking
1018  if(when > mTrackLen + 0.0000001)
1019  {
1020  wxString msg;
1021  msg = wxString::Format(wxT("when %.20f mTrackLen %.20f diff %.20f"), when, mTrackLen, when-mTrackLen);
1022  wxASSERT_MSG(when <= (mTrackLen), msg);
1023  }
1024  if(when < 0)
1025  {
1026  wxString msg;
1027  msg = wxString::Format(wxT("when %.20f mTrackLen %.20f"), when, mTrackLen);
1028  wxASSERT_MSG(when >= 0, msg);
1029  }
1030 #endif
1031 
1032  when = std::max( 0.0, std::min( mTrackLen, when ) );
1033 
1034  auto range = EqualRange( when, 0 );
1035  int index = range.first;
1036 
1037  if ( index < range.second )
1038  // modify existing
1039  // In case of a discontinuity, ALWAYS CHANGING LEFT LIMIT ONLY!
1040  mEnv[ index ].SetVal( this, value );
1041  else
1042  // Add NEW
1043  Insert( index, EnvPoint { when, value } );
1044 
1045  return index;
1046 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
int min(int a, int b)
void Insert(int point, const EnvPoint &p)
insert a point
Definition: Envelope.cpp:653
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
void Envelope::InsertSpace ( double  t0,
double  tlen 
)

Definition at line 950 of file Envelope.cpp.

References ExpandRegion(), mOffset, and RemoveUnneededPoints().

952 {
953  auto range = ExpandRegion( t0 - mOffset, tlen, nullptr, nullptr );
954 
955  // Simplify the boundaries if possible
956  RemoveUnneededPoints( range.second, true );
957  RemoveUnneededPoints( range.first - 1, false );
958 }
void RemoveUnneededPoints(size_t startAt, bool rightward, bool testNeighbors=true)
Definition: Envelope.cpp:834
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
std::pair< int, int > ExpandRegion(double t0, double tlen, double *pLeftVal, double *pRightVal)
Definition: Envelope.cpp:900
double Envelope::Integral ( double  t0,
double  t1 
) const

Definition at line 1499 of file Envelope.cpp.

References BinarySearchForTime(), IntegrateInterpolated(), InterpolatePoints(), mDB, mDefaultValue, mEnv, and mOffset.

Referenced by Average(), TimeTrack::testMe(), and testMe().

1500 {
1501  if(t0 == t1)
1502  return 0.0;
1503  if(t0 > t1)
1504  {
1505  return -Integral(t1, t0); // this makes more sense than returning the default value
1506  }
1507 
1508  unsigned int count = mEnv.size();
1509  if(count == 0) // 'empty' envelope
1510  return (t1 - t0) * mDefaultValue;
1511 
1512  t0 -= mOffset;
1513  t1 -= mOffset;
1514 
1515  double total = 0.0, lastT, lastVal;
1516  unsigned int i; // this is the next point to check
1517  if(t0 < mEnv[0].GetT()) // t0 preceding the first point
1518  {
1519  if(t1 <= mEnv[0].GetT())
1520  return (t1 - t0) * mEnv[0].GetVal();
1521  i = 1;
1522  lastT = mEnv[0].GetT();
1523  lastVal = mEnv[0].GetVal();
1524  total += (lastT - t0) * lastVal;
1525  }
1526  else if(t0 >= mEnv[count - 1].GetT()) // t0 at or following the last point
1527  {
1528  return (t1 - t0) * mEnv[count - 1].GetVal();
1529  }
1530  else // t0 enclosed by points
1531  {
1532  // Skip any points that come before t0 using binary search
1533  int lo, hi;
1534  BinarySearchForTime(lo, hi, t0);
1535  lastVal = InterpolatePoints(mEnv[lo].GetVal(), mEnv[hi].GetVal(), (t0 - mEnv[lo].GetT()) / (mEnv[hi].GetT() - mEnv[lo].GetT()), mDB);
1536  lastT = t0;
1537  i = hi; // the point immediately after t0.
1538  }
1539 
1540  // loop through the rest of the envelope points until we get to t1
1541  while (1)
1542  {
1543  if(i >= count) // the requested range extends beyond the last point
1544  {
1545  return total + (t1 - lastT) * lastVal;
1546  }
1547  else if(mEnv[i].GetT() >= t1) // this point follows the end of the range
1548  {
1549  double thisVal = InterpolatePoints(mEnv[i - 1].GetVal(), mEnv[i].GetVal(), (t1 - mEnv[i - 1].GetT()) / (mEnv[i].GetT() - mEnv[i - 1].GetT()), mDB);
1550  return total + IntegrateInterpolated(lastVal, thisVal, t1 - lastT, mDB);
1551  }
1552  else // this point precedes the end of the range
1553  {
1554  total += IntegrateInterpolated(lastVal, mEnv[i].GetVal(), mEnv[i].GetT() - lastT, mDB);
1555  lastT = mEnv[i].GetT();
1556  lastVal = mEnv[i].GetVal();
1557  i++;
1558  }
1559  }
1560 }
bool mDB
Definition: Envelope.h:265
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
static double IntegrateInterpolated(double y1, double y2, double time, bool logarithmic)
Definition: Envelope.cpp:1434
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
static double InterpolatePoints(double y1, double y2, double factor, bool logarithmic)
Definition: Envelope.cpp:1426
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
double Integral(double t0, double t1) const
Definition: Envelope.cpp:1499
double Envelope::IntegralOfInverse ( double  t0,
double  t1 
) const

Definition at line 1562 of file Envelope.cpp.

References BinarySearchForTime(), IntegrateInverseInterpolated(), InterpolatePoints(), mDB, mDefaultValue, mEnv, and mOffset.

Referenced by AverageOfInverse(), TimeTrack::ComputeWarpedLength(), and TimeTrack::testMe().

1563 {
1564  if(t0 == t1)
1565  return 0.0;
1566  if(t0 > t1)
1567  {
1568  return -IntegralOfInverse(t1, t0); // this makes more sense than returning the default value
1569  }
1570 
1571  unsigned int count = mEnv.size();
1572  if(count == 0) // 'empty' envelope
1573  return (t1 - t0) / mDefaultValue;
1574 
1575  t0 -= mOffset;
1576  t1 -= mOffset;
1577 
1578  double total = 0.0, lastT, lastVal;
1579  unsigned int i; // this is the next point to check
1580  if(t0 < mEnv[0].GetT()) // t0 preceding the first point
1581  {
1582  if(t1 <= mEnv[0].GetT())
1583  return (t1 - t0) / mEnv[0].GetVal();
1584  i = 1;
1585  lastT = mEnv[0].GetT();
1586  lastVal = mEnv[0].GetVal();
1587  total += (lastT - t0) / lastVal;
1588  }
1589  else if(t0 >= mEnv[count - 1].GetT()) // t0 at or following the last point
1590  {
1591  return (t1 - t0) / mEnv[count - 1].GetVal();
1592  }
1593  else // t0 enclosed by points
1594  {
1595  // Skip any points that come before t0 using binary search
1596  int lo, hi;
1597  BinarySearchForTime(lo, hi, t0);
1598  lastVal = InterpolatePoints(mEnv[lo].GetVal(), mEnv[hi].GetVal(), (t0 - mEnv[lo].GetT()) / (mEnv[hi].GetT() - mEnv[lo].GetT()), mDB);
1599  lastT = t0;
1600  i = hi; // the point immediately after t0.
1601  }
1602 
1603  // loop through the rest of the envelope points until we get to t1
1604  while (1)
1605  {
1606  if(i >= count) // the requested range extends beyond the last point
1607  {
1608  return total + (t1 - lastT) / lastVal;
1609  }
1610  else if(mEnv[i].GetT() >= t1) // this point follows the end of the range
1611  {
1612  double thisVal = InterpolatePoints(mEnv[i - 1].GetVal(), mEnv[i].GetVal(), (t1 - mEnv[i - 1].GetT()) / (mEnv[i].GetT() - mEnv[i - 1].GetT()), mDB);
1613  return total + IntegrateInverseInterpolated(lastVal, thisVal, t1 - lastT, mDB);
1614  }
1615  else // this point precedes the end of the range
1616  {
1617  total += IntegrateInverseInterpolated(lastVal, mEnv[i].GetVal(), mEnv[i].GetT() - lastT, mDB);
1618  lastT = mEnv[i].GetT();
1619  lastVal = mEnv[i].GetVal();
1620  i++;
1621  }
1622  }
1623 }
bool mDB
Definition: Envelope.h:265
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
static double IntegrateInverseInterpolated(double y1, double y2, double time, bool logarithmic)
Definition: Envelope.cpp:1455
double IntegralOfInverse(double t0, double t1) const
Definition: Envelope.cpp:1562
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
static double InterpolatePoints(double y1, double y2, double factor, bool logarithmic)
Definition: Envelope.cpp:1426
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
bool Envelope::IsDirty ( ) const
void Envelope::MoveDragPoint ( double  newWhen,
double  value 
)
private

Definition at line 186 of file Envelope.cpp.

References mDragPoint, mDragPointValid, mEnv, min(), mTrackLen, SetDragPointValid(), EnvPoint::SetT(), and EnvPoint::SetVal().

Referenced by EnvelopeEditor::MoveDragPoint().

187 {
188  SetDragPointValid(true);
189  if (!mDragPointValid)
190  return;
191 
192  // We'll limit the drag point time to be between those of the preceding
193  // and next envelope point.
194  double limitLo = 0.0;
195  double limitHi = mTrackLen;
196 
197  if (mDragPoint > 0)
198  limitLo = std::max(limitLo, mEnv[mDragPoint - 1].GetT());
199  if (mDragPoint + 1 < (int)mEnv.size())
200  limitHi = std::min(limitHi, mEnv[mDragPoint + 1].GetT());
201 
202  EnvPoint &dragPoint = mEnv[mDragPoint];
203  const double tt =
204  std::max(limitLo, std::min(limitHi, newWhen));
205 
206  // This might temporary violate the constraint that at most two
207  // points share a time value.
208  dragPoint.SetT(tt);
209  dragPoint.SetVal( this, value );
210 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
void SetDragPointValid(bool valid)
Definition: Envelope.cpp:149
int mDragPoint
Definition: Envelope.h:271
void SetT(double t)
Definition: Envelope.h:42
int min(int a, int b)
void SetVal(Envelope *pEnvelope, double val)
Definition: Envelope.h:278
bool mDragPointValid
Definition: Envelope.h:270
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
double Envelope::NextPointAfter ( double  t) const
private

Definition at line 1390 of file Envelope.cpp.

References BinarySearchForTime(), and mEnv.

Referenced by testMe().

1391 {
1392  int lo,hi;
1393  BinarySearchForTime( lo, hi, t );
1394  if (hi >= (int)mEnv.size())
1395  return t;
1396  else
1397  return mEnv[hi].GetT();
1398 }
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
EnvArray mEnv
Definition: Envelope.h:252
int Envelope::NumberOfPointsAfter ( double  t) const
private

Definition at line 1381 of file Envelope.cpp.

References BinarySearchForTime(), and mEnv.

Referenced by testMe().

1382 {
1383  int lo,hi;
1384  BinarySearchForTime( lo, hi, t );
1385 
1386  return mEnv.size() - hi;
1387 }
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
EnvArray mEnv
Definition: Envelope.h:252
const EnvPoint& Envelope::operator[] ( int  index) const
inlineprivate

Accessor for points.

Definition at line 216 of file Envelope.h.

References mEnv.

217  {
218  return mEnv[index];
219  }
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::Paste ( double  t0,
const Envelope e,
double  sampleDur 
)

Definition at line 757 of file Envelope.cpp.

References ConsistencyCheck(), EqualRange(), ExpandRegion(), GetValue(), GetValueRelative(), mDefaultValue, mEnv, min(), mOffset, mTrackLen, and RemoveUnneededPoints().

759 {
760  const bool wasEmpty = (this->mEnv.size() == 0);
761  auto otherSize = e->mEnv.size();
762  const double otherDur = e->mTrackLen;
763  const auto otherOffset = e->mOffset;
764  const auto deltat = otherOffset + otherDur;
765 
766  if ( otherSize == 0 && wasEmpty && e->mDefaultValue == this->mDefaultValue )
767  {
768  // msmeyer: The envelope is empty and has the same default value, so
769  // there is nothing that must be inserted, just return. This avoids
770  // the creation of unnecessary duplicate control points
771  // MJS: but the envelope does get longer
772  // PRL: Assuming t0 is in the domain of the envelope
773  mTrackLen += deltat;
774  return;
775  }
776 
777  // Make t0 relative and trim it to the domain of this
778  t0 = std::min( mTrackLen, std::max( 0.0, t0 - mOffset ) );
779 
780  // Adjust if the insertion point rounds off near a discontinuity in this
781  if ( true )
782  {
783  double newT0;
784  auto range = EqualRange( t0, sampleDur );
785  auto index = range.first;
786  if ( index + 2 == range.second &&
787  ( newT0 = mEnv[ index ].GetT() ) == mEnv[ 1 + index ].GetT() )
788  t0 = newT0;
789  }
790 
791  // Open up a space
792  double leftVal = e->GetValue( 0 );
793  double rightVal = e->GetValueRelative( otherDur );
794  // This range includes the right-side limit of the left end of the space,
795  // and the left-side limit of the right end:
796  const auto range = ExpandRegion( t0, deltat, &leftVal, &rightVal );
797  // Where to put the copied points from e -- after the first of the
798  // two points in range:
799  auto insertAt = range.first + 1;
800 
801  // Copy points from e -- maybe skipping those at the extremes
802  auto end = e->mEnv.end();
803  if ( otherSize != 0 && e->mEnv[ otherSize - 1 ].GetT() == otherDur )
804  // ExpandRegion already made an equivalent limit point
805  --end, --otherSize;
806  auto begin = e->mEnv.begin();
807  if ( otherSize != 0 && otherOffset == 0.0 && e->mEnv[ 0 ].GetT() == 0.0 )
808  ++begin, --otherSize;
809  mEnv.insert( mEnv.begin() + insertAt, begin, end );
810 
811  // Adjust their times
812  for ( size_t index = insertAt, last = insertAt + otherSize;
813  index < last; ++index ) {
814  auto &point = mEnv[ index ];
815  point.SetT( point.GetT() + otherOffset + t0 );
816  }
817 
818  // Treat removable discontinuities
819  // Right edge outward:
820  RemoveUnneededPoints( insertAt + otherSize + 1, true );
821  // Right edge inward:
822  RemoveUnneededPoints( insertAt + otherSize, false, false );
823 
824  // Left edge inward:
825  RemoveUnneededPoints( range.first, true, false );
826  // Left edge outward:
827  RemoveUnneededPoints( range.first - 1, false );
828 
829  // Guarantee monotonicity of times, against little round-off mistakes perhaps
831 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
bool ConsistencyCheck()
Definition: Envelope.cpp:60
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
void RemoveUnneededPoints(size_t startAt, bool rightward, bool testNeighbors=true)
Definition: Envelope.cpp:834
int min(int a, int b)
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
std::pair< int, int > ExpandRegion(double t0, double tlen, double *pLeftVal, double *pRightVal)
Definition: Envelope.cpp:900
double mDefaultValue
Definition: Envelope.h:267
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::print ( ) const

Definition at line 1728 of file Envelope.cpp.

References mEnv.

1729 {
1730  for( unsigned int i = 0; i < mEnv.size(); i++ )
1731  wxPrintf( "(%.2f, %.2f)\n", mEnv[i].GetT(), mEnv[i].GetVal() );
1732 }
EnvArray mEnv
Definition: Envelope.h:252
int Envelope::Reassign ( double  when,
double  value 
)

Move a point at when to value.

Returns 0 if point moved, -1 if not found.

Definition at line 960 of file Envelope.cpp.

References mEnv, and mOffset.

Referenced by EffectEqualization::GraphicEQ().

961 {
962  when -= mOffset;
963 
964  int len = mEnv.size();
965  if (len == 0)
966  return -1;
967 
968  int i = 0;
969  while (i < len && when > mEnv[i].GetT())
970  i++;
971 
972  if (i >= len || when < mEnv[i].GetT())
973  return -1;
974 
975  mEnv[i].SetVal( this, value );
976  return 0;
977 }
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::RemoveUnneededPoints ( size_t  startAt,
bool  rightward,
bool  testNeighbors = true 
)
private

Definition at line 834 of file Envelope.cpp.

References EnvPoint::GetT(), EnvPoint::GetVal(), and VALUE_TOLERANCE.

Referenced by CollapseRegion(), InsertSpace(), and Paste().

836 {
837  // startAt is the index of a recently inserted point which might make no
838  // difference in envelope evaluation, or else might cause nearby points to
839  // make no difference.
840 
841  auto isDiscontinuity = [this]( size_t index ) {
842  // Assume array accesses are in-bounds
843  const EnvPoint &point1 = mEnv[ index ];
844  const EnvPoint &point2 = mEnv[ index + 1 ];
845  return point1.GetT() == point2.GetT() &&
846  fabs( point1.GetVal() - point2.GetVal() ) > VALUE_TOLERANCE;
847  };
848 
849  auto remove = [this]( size_t index, bool leftLimit ) {
850  // Assume array accesses are in-bounds
851  const auto &point = mEnv[ index ];
852  auto when = point.GetT();
853  auto val = point.GetVal();
854  Delete( index ); // try it to see if it's doing anything
855  auto val1 = GetValueRelative ( when, leftLimit );
856  if( fabs( val - val1 ) > VALUE_TOLERANCE ) {
857  // put it back, we needed it
858  Insert( index, EnvPoint{ when, val } );
859  return false;
860  }
861  else
862  return true;
863  };
864 
865  auto len = mEnv.size();
866 
867  bool leftLimit =
868  !rightward && startAt + 1 < len && isDiscontinuity( startAt );
869 
870  bool removed = remove( startAt, leftLimit );
871 
872  if ( removed )
873  // The given point was removable. Done!
874  return;
875 
876  if ( !testNeighbors )
877  return;
878 
879  // The given point was not removable. But did its insertion make nearby
880  // points removable?
881 
882  int index = startAt + ( rightward ? 1 : -1 );
883  while ( index >= 0 && index < (int)len ) {
884  // Stop at any discontinuity
885  if ( index > 0 && isDiscontinuity( index - 1 ) )
886  break;
887  if ( (index + 1) < (int)len && isDiscontinuity( index ) )
888  break;
889 
890  if ( ! remove( index, false ) )
891  break;
892 
893  --len;
894  if ( ! rightward )
895  --index;
896  }
897 }
double GetT() const
Definition: Envelope.h:41
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
void Delete(int point)
DELETE a point by its position in array.
Definition: Envelope.cpp:648
static const double VALUE_TOLERANCE
Definition: Envelope.cpp:46
double GetVal() const
Definition: Envelope.h:43
void Insert(int point, const EnvPoint &p)
insert a point
Definition: Envelope.cpp:653
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35
void Envelope::RescaleTimes ( double  newLength)

Definition at line 1098 of file Envelope.cpp.

References mEnv, and mTrackLen.

1100 {
1101  if ( mTrackLen == 0 ) {
1102  for ( auto &point : mEnv )
1103  point.SetT( 0 );
1104  }
1105  else {
1106  auto ratio = newLength / mTrackLen;
1107  for ( auto &point : mEnv )
1108  point.SetT( point.GetT() * ratio );
1109  }
1110  mTrackLen = newLength;
1111 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::RescaleValues ( double  minValue,
double  maxValue 
)

Rescale function for time tracks (could also be used for other tracks though). This is used to load old time track project files where the envelope used a 0 to 1 range instead of storing the actual time track values. This function will change the range of the envelope and rescale all envelope points accordingly (unlike SetRange, which clamps the envelope points to the NEW range). - the NEW minimum value - the NEW maximum value

Definition at line 115 of file Envelope.cpp.

References ClampValue(), mDefaultValue, mEnv, mMaxValue, and mMinValue.

116 {
117  double oldMinValue = mMinValue;
118  double oldMaxValue = mMaxValue;
119  mMinValue = minValue;
120  mMaxValue = maxValue;
121 
122  // rescale the default value
123  double factor = (mDefaultValue - oldMinValue) / (oldMaxValue - oldMinValue);
125 
126  // rescale all points
127  for( unsigned int i = 0; i < mEnv.size(); i++ ) {
128  factor = (mEnv[i].GetVal() - oldMinValue) / (oldMaxValue - oldMinValue);
129  mEnv[i].SetVal( this, mMinValue + (mMaxValue - mMinValue) * factor );
130  }
131 
132 }
double mMaxValue
Definition: Envelope.h:266
double mMinValue
Definition: Envelope.h:266
double ClampValue(double value)
Definition: Envelope.h:107
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::SetDragPoint ( int  dragPoint)

Definition at line 143 of file Envelope.cpp.

References mDragPoint, mDragPointValid, mEnv, and min().

Referenced by EnvelopeEditor::HandleMouseButtonDown().

144 {
145  mDragPoint = std::max(-1, std::min(int(mEnv.size() - 1), dragPoint));
146  mDragPointValid = (mDragPoint >= 0);
147 }
int mDragPoint
Definition: Envelope.h:271
int min(int a, int b)
bool mDragPointValid
Definition: Envelope.h:270
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::SetDragPointValid ( bool  valid)

Definition at line 149 of file Envelope.cpp.

References mDefaultValue, mDragPoint, mDragPointValid, and mEnv.

Referenced by EnvelopeEditor::HandleDragging(), and MoveDragPoint().

150 {
151  mDragPointValid = (valid && mDragPoint >= 0);
152  if (mDragPoint >= 0 && !valid) {
153  // We're going to be deleting the point; On
154  // screen we show this by having the envelope move to
155  // the position it will have after deletion of the point.
156  // Without deleting the point we move it left or right
157  // to the same position as the previous or next point.
158 
159  static const double big = std::numeric_limits<double>::max();
160  auto size = mEnv.size();
161 
162  if( size <= 1) {
163  // There is only one point - just move it
164  // off screen and at default height.
165  // temporary state when dragging only!
166  mEnv[mDragPoint].SetT(big);
167  mEnv[mDragPoint].SetVal( this, mDefaultValue );
168  return;
169  }
170  else if ( mDragPoint + 1 == (int)size ) {
171  // Put the point at the height of the last point, but also off screen.
172  mEnv[mDragPoint].SetT(big);
173  mEnv[mDragPoint].SetVal( this, mEnv[ size - 1 ].GetVal() );
174  }
175  else {
176  // Place it exactly on its right neighbour.
177  // That way the drawing code will overpaint the dark dot with
178  // a light dot, as if it were deleted.
179  const auto &neighbor = mEnv[mDragPoint + 1];
180  mEnv[mDragPoint].SetT(neighbor.GetT());
181  mEnv[mDragPoint].SetVal( this, neighbor.GetVal() );
182  }
183  }
184 }
int mDragPoint
Definition: Envelope.h:271
bool mDragPointValid
Definition: Envelope.h:270
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::SetExponential ( bool  db)
inline

Definition at line 99 of file Envelope.h.

References mDB.

Referenced by testMe().

99 { mDB = db; }
bool mDB
Definition: Envelope.h:265
void Envelope::SetOffset ( double  newOffset)

Definition at line 1071 of file Envelope.cpp.

References mOffset.

1073 {
1074  mOffset = newOffset;
1075 }
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
void Envelope::SetRange ( double  minValue,
double  maxValue 
)

Definition at line 221 of file Envelope.cpp.

References ClampValue(), mDefaultValue, mEnv, mMaxValue, and mMinValue.

221  {
222  mMinValue = minValue;
223  mMaxValue = maxValue;
225  for( unsigned int i = 0; i < mEnv.size(); i++ )
226  mEnv[i].SetVal( this, mEnv[i].GetVal() ); // this clamps the value to the NEW range
227 }
double mMaxValue
Definition: Envelope.h:266
double mMinValue
Definition: Envelope.h:266
double ClampValue(double value)
Definition: Envelope.h:107
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::SetTrackLen ( double  trackLen,
double  sampleDur = 0.0 
)

Definition at line 1077 of file Envelope.cpp.

References AddPointAtEnd(), EqualRange(), GetValueRelative(), mEnv, min(), and mTrackLen.

Referenced by EffectEqualization::GraphicEQ(), and EffectEqualization::setCurve().

1079 {
1080  // Preserve the left-side limit at trackLen.
1081  auto range = EqualRange( trackLen, sampleDur );
1082  bool needPoint = ( range.first == range.second && trackLen < mTrackLen );
1083  double value=0.0;
1084  if ( needPoint )
1085  value = GetValueRelative( trackLen );
1086 
1087  mTrackLen = trackLen;
1088 
1089  // Shrink the array.
1090  // If more than one point already at the end, keep only the first of them.
1091  int newLen = std::min( 1 + range.first, range.second );
1092  mEnv.resize( newLen );
1093 
1094  if ( needPoint )
1095  AddPointAtEnd( mTrackLen, value );
1096 }
double mTrackLen
The length of the envelope, which is the same as the length of the underlying track (normally) ...
Definition: Envelope.h:258
double GetValueRelative(double t, bool leftLimit=false) const
Definition: Envelope.cpp:1123
int min(int a, int b)
void AddPointAtEnd(double t, double val)
Definition: Envelope.cpp:231
std::pair< int, int > EqualRange(double when, double sampleDur) const
Definition: Envelope.cpp:1048
EnvArray mEnv
Definition: Envelope.h:252
double Envelope::SolveIntegralOfInverse ( double  t0,
double  area 
) const

Definition at line 1625 of file Envelope.cpp.

References BinarySearchForTime(), IntegrateInverseInterpolated(), InterpolatePoints(), mDB, mDefaultValue, mEnv, mOffset, and SolveIntegrateInverseInterpolated().

Referenced by TimeTrack::SolveWarpedLength().

1626 {
1627  if(area == 0.0)
1628  return t0;
1629 
1630  const auto count = mEnv.size();
1631  if(count == 0) // 'empty' envelope
1632  return t0 + area * mDefaultValue;
1633 
1634  // Correct for offset!
1635  t0 -= mOffset;
1636  return mOffset + [&] {
1637  // Now we can safely assume t0 is relative time!
1638  double lastT, lastVal;
1639  int i; // this is the next point to check
1640  if(t0 < mEnv[0].GetT()) // t0 preceding the first point
1641  {
1642  if (area < 0) {
1643  return t0 + area * mEnv[0].GetVal();
1644  }
1645  else {
1646  i = 1;
1647  lastT = mEnv[0].GetT();
1648  lastVal = mEnv[0].GetVal();
1649  double added = (lastT - t0) / lastVal;
1650  if(added >= area)
1651  return t0 + area * mEnv[0].GetVal();
1652  area -= added;
1653  }
1654  }
1655  else if(t0 >= mEnv[count - 1].GetT()) // t0 at or following the last point
1656  {
1657  if (area < 0) {
1658  i = (int)count - 2;
1659  lastT = mEnv[count - 1].GetT();
1660  lastVal = mEnv[count - 1].GetVal();
1661  double added = (lastT - t0) / lastVal; // negative
1662  if(added <= area)
1663  return t0 + area * mEnv[count - 1].GetVal();
1664  area -= added;
1665  }
1666  else {
1667  return t0 + area * mEnv[count - 1].GetVal();
1668  }
1669  }
1670  else // t0 enclosed by points
1671  {
1672  // Skip any points that come before t0 using binary search
1673  int lo, hi;
1674  BinarySearchForTime(lo, hi, t0);
1675  lastVal = InterpolatePoints(mEnv[lo].GetVal(), mEnv[hi].GetVal(), (t0 - mEnv[lo].GetT()) / (mEnv[hi].GetT() - mEnv[lo].GetT()), mDB);
1676  lastT = t0;
1677  if (area < 0)
1678  i = lo;
1679  else
1680  i = hi; // the point immediately after t0.
1681  }
1682 
1683  if (area < 0) {
1684  // loop BACKWARDS through the rest of the envelope points until we get to t1
1685  // (which is less than t0)
1686  while (1)
1687  {
1688  if(i < 0) // the requested range extends beyond the leftmost point
1689  {
1690  return lastT + area * lastVal;
1691  }
1692  else
1693  {
1694  double added =
1695  -IntegrateInverseInterpolated(mEnv[i].GetVal(), lastVal, lastT - mEnv[i].GetT(), mDB);
1696  if(added <= area)
1697  return lastT - SolveIntegrateInverseInterpolated(lastVal, mEnv[i].GetVal(), lastT - mEnv[i].GetT(), -area, mDB);
1698  area -= added;
1699  lastT = mEnv[i].GetT();
1700  lastVal = mEnv[i].GetVal();
1701  --i;
1702  }
1703  }
1704  }
1705  else {
1706  // loop through the rest of the envelope points until we get to t1
1707  while (1)
1708  {
1709  if(i >= (int)count) // the requested range extends beyond the last point
1710  {
1711  return lastT + area * lastVal;
1712  }
1713  else
1714  {
1715  double added = IntegrateInverseInterpolated(lastVal, mEnv[i].GetVal(), mEnv[i].GetT() - lastT, mDB);
1716  if(added >= area)
1717  return lastT + SolveIntegrateInverseInterpolated(lastVal, mEnv[i].GetVal(), mEnv[i].GetT() - lastT, area, mDB);
1718  area -= added;
1719  lastT = mEnv[i].GetT();
1720  lastVal = mEnv[i].GetVal();
1721  i++;
1722  }
1723  }
1724  }
1725  }();
1726 }
bool mDB
Definition: Envelope.h:265
void BinarySearchForTime(int &Lo, int &Hi, double t) const
Definition: Envelope.cpp:1134
static double IntegrateInverseInterpolated(double y1, double y2, double time, bool logarithmic)
Definition: Envelope.cpp:1455
static double SolveIntegrateInverseInterpolated(double y1, double y2, double time, double area, bool logarithmic)
Definition: Envelope.cpp:1472
double mOffset
The time at which the envelope starts, i.e. the start offset.
Definition: Envelope.h:255
static double InterpolatePoints(double y1, double y2, double factor, bool logarithmic)
Definition: Envelope.cpp:1426
double mDefaultValue
Definition: Envelope.h:267
EnvArray mEnv
Definition: Envelope.h:252
void Envelope::testMe ( )

Definition at line 1743 of file Envelope.cpp.

References checkResult(), Flatten(), InsertOrReplaceRelative(), Integral(), mEnv, NextPointAfter(), NumberOfPointsAfter(), and SetExponential().

1744 {
1745  double t0=0, t1=0;
1746 
1747  SetExponential(false);
1748 
1749  Flatten(0.5);
1750  checkResult( 1, Integral(0.0,100.0), 50);
1751  checkResult( 2, Integral(-10.0,10.0), 10);
1752 
1753  Flatten(0.5);
1754  checkResult( 3, Integral(0.0,100.0), 50);
1755  checkResult( 4, Integral(-10.0,10.0), 10);
1756  checkResult( 5, Integral(-20.0,-10.0), 5);
1757 
1758  Flatten(0.5);
1759  InsertOrReplaceRelative( 5.0, 0.5 );
1760  checkResult( 6, Integral(0.0,100.0), 50);
1761  checkResult( 7, Integral(-10.0,10.0), 10);
1762 
1763  Flatten(0.0);
1764  InsertOrReplaceRelative( 0.0, 0.0 );
1765  InsertOrReplaceRelative( 5.0, 1.0 );
1766  InsertOrReplaceRelative( 10.0, 0.0 );
1767  t0 = 10.0 - .1;
1768  t1 = 10.0 + .1;
1769  double result = Integral(0.0,t1);
1770  double resulta = Integral(0.0,t0);
1771  double resultb = Integral(t0,t1);
1772  // Integrals should be additive
1773  checkResult( 8, result - resulta - resultb, 0);
1774 
1775  Flatten(0.0);
1776  InsertOrReplaceRelative( 0.0, 0.0 );
1777  InsertOrReplaceRelative( 5.0, 1.0 );
1778  InsertOrReplaceRelative( 10.0, 0.0 );
1779  t0 = 10.0 - .1;
1780  t1 = 10.0 + .1;
1781  checkResult( 9, Integral(0.0,t1), 5);
1782  checkResult( 10, Integral(0.0,t0), 4.999);
1783  checkResult( 11, Integral(t0,t1), .001);
1784 
1785  mEnv.clear();
1786  InsertOrReplaceRelative( 0.0, 0.0 );
1787  InsertOrReplaceRelative( 5.0, 1.0 );
1788  InsertOrReplaceRelative( 10.0, 0.0 );
1789  checkResult( 12, NumberOfPointsAfter( -1 ), 3 );
1790  checkResult( 13, NumberOfPointsAfter( 0 ), 2 );
1791  checkResult( 14, NumberOfPointsAfter( 1 ), 2 );
1792  checkResult( 15, NumberOfPointsAfter( 5 ), 1 );
1793  checkResult( 16, NumberOfPointsAfter( 7 ), 1 );
1794  checkResult( 17, NumberOfPointsAfter( 10 ), 0 );
1795  checkResult( 18, NextPointAfter( 0 ), 5 );
1796  checkResult( 19, NextPointAfter( 5 ), 10 );
1797 }
void Flatten(double value)
Definition: Envelope.cpp:137
static void checkResult(int n, double a, double b)
Definition: Envelope.cpp:1734
void SetExponential(bool db)
Definition: Envelope.h:99
double NextPointAfter(double t) const
Definition: Envelope.cpp:1390
int InsertOrReplaceRelative(double when, double value)
Add a control point to the envelope.
Definition: Envelope.cpp:1014
int NumberOfPointsAfter(double t) const
Definition: Envelope.cpp:1381
EnvArray mEnv
Definition: Envelope.h:252
double Integral(double t0, double t1) const
Definition: Envelope.cpp:1499
void Envelope::WriteXML ( XMLWriter xmlFile) const

Definition at line 427 of file Envelope.cpp.

References EnvPoint::GetT(), and EnvPoint::GetVal().

429 {
430  unsigned int ctrlPt;
431 
432  xmlFile.StartTag(wxT("envelope"));
433  xmlFile.WriteAttr(wxT("numpoints"), mEnv.size());
434 
435  for (ctrlPt = 0; ctrlPt < mEnv.size(); ctrlPt++) {
436  const EnvPoint &point = mEnv[ctrlPt];
437  xmlFile.StartTag(wxT("controlpoint"));
438  xmlFile.WriteAttr(wxT("t"), point.GetT(), 12);
439  xmlFile.WriteAttr(wxT("val"), point.GetVal(), 12);
440  xmlFile.EndTag(wxT("controlpoint"));
441  }
442 
443  xmlFile.EndTag(wxT("envelope"));
444 }
double GetT() const
Definition: Envelope.h:41
virtual void StartTag(const wxString &name)
Definition: XMLWriter.cpp:78
virtual void WriteAttr(const wxString &name, const wxString &value)
Definition: XMLWriter.cpp:131
virtual void EndTag(const wxString &name)
Definition: XMLWriter.cpp:101
double GetVal() const
Definition: Envelope.h:43
EnvArray mEnv
Definition: Envelope.h:252
EnvPoint, derived from XMLTagHandler, provides Envelope with a draggable point type.
Definition: Envelope.h:35

Friends And Related Function Documentation

friend class EnvelopeEditor
friend

Definition at line 214 of file Envelope.h.

friend class GetInfoCommand
friend

Definition at line 274 of file Envelope.h.

friend class SetEnvelopeCommand
friend

Definition at line 275 of file Envelope.h.

Member Data Documentation

bool Envelope::mDB
private
double Envelope::mDefaultValue
private
int Envelope::mDragPoint { -1 }
private
bool Envelope::mDragPointValid { false }
private
EnvArray Envelope::mEnv
private
double Envelope::mMaxValue
private

Definition at line 266 of file Envelope.h.

Referenced by ClampValue(), GetMaxValue(), RescaleValues(), and SetRange().

double Envelope::mMinValue
private

Definition at line 266 of file Envelope.h.

Referenced by ClampValue(), GetMinValue(), RescaleValues(), and SetRange().

double Envelope::mOffset { 0.0 }
private
int Envelope::mSearchGuess { -2 }
mutableprivate

Definition at line 273 of file Envelope.h.

Referenced by BinarySearchForTime(), and BinarySearchForTime_LeftLimit().

double Envelope::mTrackEpsilon { 1.0 / 200000.0 }
private

The shortest distance appart that points on an envelope can be before being considered the same point.

Definition at line 264 of file Envelope.h.

double Envelope::mTrackLen { 0.0 }
private

The length of the envelope, which is the same as the length of the underlying track (normally)

Definition at line 258 of file Envelope.h.

Referenced by Cap(), CollapseRegion(), CopyRange(), Envelope(), GetTrackLen(), InsertOrReplaceRelative(), MoveDragPoint(), Paste(), RescaleTimes(), and SetTrackLen().


The documentation for this class was generated from the following files: