Better constructors for Envelope
This commit is contained in:
parent
3ba1ebc5c0
commit
4be19128c0
101
src/Envelope.cpp
101
src/Envelope.cpp
|
@ -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)
|
||||
|
|
|
@ -75,8 +75,15 @@ private:
|
|||
typedef std::vector<EnvPoint> EnvArray;
|
||||
|
||||
class Envelope final : public XMLTagHandler {
|
||||
public:
|
||||
Envelope();
|
||||
public:
|
||||
// Envelope can define a piecewise linear function, or piecewise exponential.
|
||||
Envelope(bool exponential, double minValue, double maxValue, double defaultValue);
|
||||
|
||||
Envelope(const Envelope &orig);
|
||||
|
||||
// Create from a subrange of another envelope.
|
||||
Envelope(const Envelope &orig, double t0, double t1);
|
||||
|
||||
void Initialize(int numPoints);
|
||||
|
||||
virtual ~ Envelope();
|
||||
|
@ -113,8 +120,6 @@ class Envelope final : public XMLTagHandler {
|
|||
|
||||
// Handling Cut/Copy/Paste events
|
||||
void CollapseRegion(double t0, double t1);
|
||||
// Takes absolute times, NOT offset-relative:
|
||||
void CopyFrom(const Envelope * e, double t0, double t1);
|
||||
void Paste(double t0, const Envelope *e);
|
||||
void InsertSpace(double t0, double tlen);
|
||||
void RemoveUnneededPoints(double time = -1, double tolerence = 0.001);
|
||||
|
@ -172,11 +177,13 @@ class Envelope final : public XMLTagHandler {
|
|||
private:
|
||||
friend class EnvelopeEditor;
|
||||
/** \brief Accessor for points */
|
||||
EnvPoint &operator[] (int index)
|
||||
const EnvPoint &operator[] (int index) const
|
||||
{
|
||||
return mEnv[index];
|
||||
}
|
||||
|
||||
std::pair<int, int> EqualRange( double when, double sampleTime ) const;
|
||||
|
||||
public:
|
||||
/** \brief Returns the sets of when and value pairs */
|
||||
void GetPoints(double *bufferWhen,
|
||||
|
@ -199,6 +206,7 @@ public:
|
|||
|
||||
private:
|
||||
EnvPoint * 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;
|
||||
double GetInterpolationStartValueAtPoint( int iPoint ) const;
|
||||
|
||||
|
@ -206,25 +214,25 @@ private:
|
|||
EnvArray mEnv;
|
||||
|
||||
/** \brief The time at which the envelope starts, i.e. the start offset */
|
||||
double mOffset;
|
||||
double mOffset { 0.0 };
|
||||
/** \brief The length of the envelope, which is the same as the length of the
|
||||
* underlying track (normally) */
|
||||
double mTrackLen;
|
||||
double mTrackLen { 0.0 };
|
||||
|
||||
// TODO: mTrackEpsilon based on assumption of 200KHz. Needs review if/when
|
||||
// we support higher sample rates.
|
||||
/** \brief The shortest distance appart that points on an envelope can be
|
||||
* before being considered the same point */
|
||||
double mTrackEpsilon;
|
||||
double mDefaultValue;
|
||||
double mTrackEpsilon { 1.0 / 200000.0 };
|
||||
bool mDB;
|
||||
double mMinValue, mMaxValue;
|
||||
double mDefaultValue;
|
||||
|
||||
// UI stuff
|
||||
bool mDragPointValid;
|
||||
int mDragPoint;
|
||||
bool mDragPointValid { false };
|
||||
int mDragPoint { -1 };
|
||||
|
||||
mutable int mSearchGuess;
|
||||
mutable int mSearchGuess { -2 };
|
||||
};
|
||||
|
||||
inline EnvPoint::EnvPoint(Envelope *envelope, double t, double val)
|
||||
|
|
|
@ -45,12 +45,9 @@ TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const Zo
|
|||
mRangeUpper = 1.1;
|
||||
mDisplayLog = false;
|
||||
|
||||
mEnvelope = std::make_unique<Envelope>();
|
||||
mEnvelope = std::make_unique<Envelope>(true, TIMETRACK_MIN, TIMETRACK_MAX, 1.0);
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
mEnvelope->SetInterpolateDB(true);
|
||||
mEnvelope->Flatten(1.0);
|
||||
mEnvelope->SetOffset(0);
|
||||
mEnvelope->SetRange(TIMETRACK_MIN, TIMETRACK_MAX);
|
||||
|
||||
SetDefaultName(_("Time Track"));
|
||||
SetName(GetDefaultName());
|
||||
|
@ -67,18 +64,12 @@ TimeTrack::TimeTrack(const TimeTrack &orig, double *pT0, double *pT1)
|
|||
{
|
||||
Init(orig); // this copies the TimeTrack metadata (name, range, etc)
|
||||
|
||||
///@TODO: Give Envelope:: a copy-constructor instead of this?
|
||||
mEnvelope = std::make_unique<Envelope>();
|
||||
mEnvelope->Flatten(1.0);
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
SetInterpolateLog(orig.GetInterpolateLog()); // this calls Envelope::SetInterpolateDB
|
||||
mEnvelope->SetOffset(0);
|
||||
mEnvelope->SetRange(orig.mEnvelope->GetMinValue(), orig.mEnvelope->GetMaxValue());
|
||||
if ( pT0 && pT1 )
|
||||
// restricted copy
|
||||
mEnvelope->CopyFrom(orig.mEnvelope.get(), *pT0, *pT1);
|
||||
if (pT0 && pT1)
|
||||
mEnvelope = std::make_unique<Envelope>( *orig.mEnvelope, *pT0, *pT1 );
|
||||
else
|
||||
mEnvelope->Paste(0.0, orig.mEnvelope.get());
|
||||
mEnvelope = std::make_unique<Envelope>( *orig.mEnvelope );
|
||||
mEnvelope->SetTrackLen(DBL_MAX);
|
||||
mEnvelope->SetOffset(0);
|
||||
|
||||
///@TODO: Give Ruler:: a copy-constructor instead of this?
|
||||
mRuler = std::make_unique<Ruler>();
|
||||
|
|
|
@ -309,7 +309,7 @@ WaveClip::WaveClip(const std::shared_ptr<DirManager> &projDirManager,
|
|||
mRate = rate;
|
||||
mSequence = std::make_unique<Sequence>(projDirManager, format);
|
||||
|
||||
mEnvelope = std::make_unique<Envelope>();
|
||||
mEnvelope = std::make_unique<Envelope>(true, 1e-7, 2.0, 1.0);
|
||||
|
||||
mWaveCache = std::make_unique<WaveCache>();
|
||||
mSpecCache = std::make_unique<SpecCache>();
|
||||
|
@ -328,10 +328,7 @@ WaveClip::WaveClip(const WaveClip& orig,
|
|||
mRate = orig.mRate;
|
||||
mSequence = std::make_unique<Sequence>(*orig.mSequence, projDirManager);
|
||||
|
||||
mEnvelope = std::make_unique<Envelope>();
|
||||
mEnvelope->Paste(0.0, orig.mEnvelope.get());
|
||||
mEnvelope->SetOffset(orig.GetOffset());
|
||||
mEnvelope->SetTrackLen((orig.mSequence->GetNumSamples().as_double()) / orig.mRate);
|
||||
mEnvelope = std::make_unique<Envelope>(*orig.mEnvelope);
|
||||
|
||||
mWaveCache = std::make_unique<WaveCache>();
|
||||
mSpecCache = std::make_unique<SpecCache>();
|
||||
|
@ -345,7 +342,6 @@ WaveClip::WaveClip(const WaveClip& orig,
|
|||
mIsPlaceholder = orig.GetIsPlaceholder();
|
||||
}
|
||||
|
||||
// to do
|
||||
WaveClip::WaveClip(const WaveClip& orig,
|
||||
const std::shared_ptr<DirManager> &projDirManager,
|
||||
bool copyCutlines,
|
||||
|
@ -369,10 +365,11 @@ WaveClip::WaveClip(const WaveClip& orig,
|
|||
|
||||
mSequence = orig.mSequence->Copy(s0, s1);
|
||||
|
||||
mEnvelope = std::make_unique<Envelope>();
|
||||
mEnvelope->CopyFrom(orig.mEnvelope.get(),
|
||||
mOffset + s0.as_double()/mRate,
|
||||
mOffset + s1.as_double()/mRate);
|
||||
mEnvelope = std::make_unique<Envelope>(
|
||||
*orig.mEnvelope,
|
||||
mOffset + s0.as_double()/mRate,
|
||||
mOffset + s1.as_double()/mRate
|
||||
);
|
||||
|
||||
if ( copyCutlines )
|
||||
// Copy cutline clips that fall in the range
|
||||
|
|
|
@ -239,13 +239,15 @@ EffectEqualization::EffectEqualization()
|
|||
mInterpolations.Add(wxGetTranslation(kInterpStrings[i]));
|
||||
}
|
||||
|
||||
mLogEnvelope = std::make_unique<Envelope>();
|
||||
mLogEnvelope->SetInterpolateDB(false);
|
||||
mLogEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range
|
||||
mLogEnvelope = std::make_unique<Envelope>
|
||||
(false,
|
||||
MIN_dBMin, MAX_dBMax, // MB: this is the highest possible range
|
||||
1.0);
|
||||
|
||||
mLinEnvelope = std::make_unique<Envelope>();
|
||||
mLinEnvelope->SetInterpolateDB(false);
|
||||
mLinEnvelope->SetRange(MIN_dBMin, MAX_dBMax); // MB: this is the highest possible range
|
||||
mLinEnvelope = std::make_unique<Envelope>
|
||||
(false,
|
||||
MIN_dBMin, MAX_dBMax, // MB: this is the highest possible range
|
||||
1.0);
|
||||
|
||||
mEnvelope = (mLin ? mLinEnvelope : mLogEnvelope).get();
|
||||
|
||||
|
@ -2308,12 +2310,7 @@ void EffectEqualization::ErrMin(void)
|
|||
double correction = 1.6;
|
||||
bool flag;
|
||||
size_t j=0;
|
||||
Envelope testEnvelope;
|
||||
testEnvelope.SetInterpolateDB(false);
|
||||
testEnvelope.SetRange(-120.0, 60.0);
|
||||
testEnvelope.Flatten(0.);
|
||||
testEnvelope.SetTrackLen(1.0);
|
||||
testEnvelope.CopyFrom(mLogEnvelope.get(), 0.0, 1.0);
|
||||
Envelope testEnvelope{ *mLogEnvelope };
|
||||
|
||||
for(size_t i = 0; i < NUM_PTS; i++)
|
||||
vals[i] = testEnvelope.GetValue(mWhens[i]);
|
||||
|
|
Loading…
Reference in New Issue