1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-10-21 14:02:57 +02:00

Better constructors for Envelope

This commit is contained in:
Paul Licameli
2017-05-02 20:55:40 -04:00
parent 3ba1ebc5c0
commit 4be19128c0
5 changed files with 100 additions and 92 deletions

View File

@@ -42,28 +42,12 @@ a draggable point type.
#include "DirManager.h"
#include "TrackArtist.h"
Envelope::Envelope()
Envelope::Envelope(bool exponential, double minValue, double maxValue, double defaultValue)
: mDB(exponential)
, mMinValue(minValue)
, mMaxValue(maxValue)
, mDefaultValue { ClampValue(defaultValue) }
{
mOffset = 0.0;
mTrackLen = 0.0;
// Anything with a sample rate of no more than 200 KHz
// will have samples spaced apart by at least this amount,
// "epsilon". We use this to enforce that there aren't
// allowed to be multiple control points at the same t
// value.
mTrackEpsilon = 1.0 / 200000.0;
mDB = true;
mDefaultValue = 1.0;
mDragPoint = -1;
mMinValue = 1.0e-7;
mMaxValue = 2.0;
mSearchGuess = -1;
mDragPointValid = false;
}
Envelope::~Envelope()
@@ -196,41 +180,51 @@ EnvPoint *Envelope::AddPointAtEnd( double t, double val )
return &mEnv.back();
}
void Envelope::CopyFrom(const Envelope *e, double t0, double t1)
Envelope::Envelope(const Envelope &orig, double t0, double t1)
: mDB(orig.mDB)
, mMinValue(orig.mMinValue)
, mMaxValue(orig.mMaxValue)
, mDefaultValue(orig.mDefaultValue)
{
wxASSERT( t0 <= t1 );
mOffset = wxMax(t0, orig.mOffset);
mTrackLen = wxMin(t1, orig.mOffset + orig.mTrackLen) - mOffset;
mOffset = wxMax(t0, e->mOffset);
mTrackLen = wxMin(t1, e->mOffset + e->mTrackLen) - mOffset;
auto range1 = orig.EqualRange( t0 - orig.mOffset, 0 );
auto range2 = orig.EqualRange( t1 - orig.mOffset, 0 );
CopyRange(orig, range1.first, range2.second);
}
mEnv.clear();
int len = e->mEnv.size();
int i = 0;
Envelope::Envelope(const Envelope &orig)
: mDB(orig.mDB)
, mMinValue(orig.mMinValue)
, mMaxValue(orig.mMaxValue)
, mDefaultValue(orig.mDefaultValue)
{
mOffset = orig.mOffset;
mTrackLen = orig.mTrackLen;
CopyRange(orig, 0, orig.GetNumberOfPoints());
}
// Skip the points that come before the copied region
while ((i < len) && e->mOffset + e->mEnv[i].GetT() <= t0)
i++;
void Envelope::CopyRange(const Envelope &orig, size_t begin, size_t end)
{
int len = orig.mEnv.size();
int i = begin;
// Create the point at 0 if it needs interpolated representation
if (i>0)
AddPointAtEnd( 0, e->GetValue(mOffset) );
if ( i > 0 )
AddPointAtEnd(0, orig.GetValue(mOffset));
// Copy points from inside the copied region
while (i < len) {
const EnvPoint &point = e->mEnv[i];
const double when = e->mOffset + point.GetT() - mOffset;
if (when < mTrackLen) {
AddPointAtEnd(when, point.GetVal());
i++;
}
else
break;
for (; i < end; ++i) {
const EnvPoint &point = orig[i];
const double when = point.GetT() + (orig.mOffset - mOffset);
AddPointAtEnd(when, point.GetVal());
}
// Create the final point if it needs interpolated representation
// If the last point of e was exatly at t1, this effectively copies it too.
if (mTrackLen > 0 && i < len)
AddPointAtEnd( mTrackLen, e->GetValue(mOffset + mTrackLen));
AddPointAtEnd( mTrackLen, orig.GetValue(mOffset + mTrackLen));
}
/// Limit() limits a double value to a range.
@@ -998,6 +992,27 @@ int Envelope::Insert(double when, double value)
return i;
}
std::pair<int, int> Envelope::EqualRange( double when, double sampleTime ) const
{
// Find range of envelope points matching the given time coordinate
// (within an interval of length sampleTime)
// by binary search; if empty, it still indicates where to
// insert.
const auto tolerance = sampleTime / 2;
auto begin = mEnv.begin();
auto end = mEnv.end();
auto first = std::lower_bound(
begin, end,
EnvPoint{ const_cast<Envelope*>( this ), when - tolerance, 0.0 },
[]( const EnvPoint &point1, const EnvPoint &point2 )
{ return point1.GetT() < point2.GetT(); }
);
auto after = first;
while ( after != end && after->GetT() < when + tolerance )
++after;
return { first - begin, after - begin };
}
// Control
void Envelope::SetOffset(double newOffset)