mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-21 14:02:57 +02:00
Change evaluation of envelope near discontinuities...
... So that even if the time is "slightly" (less than 1/2 sample interval) left of the discontinuity, the right-hand limit is always used. Thus this compensates for some roundoff errors when pasting one clip with an envelope into another. This overcomes the objections that were in a comment in Envelope::Paste to making control points with exactly equal times. And therefore Paste can be rewritten to do so, but that has not happened yet. Envelope points at exactly equal time coordinates can already be made by dragging points in the envelope editor.
This commit is contained in:
@@ -992,19 +992,6 @@ void Envelope::Cap( double sampleDur )
|
||||
|
||||
// Private methods
|
||||
|
||||
// We no longer tolerate multiple envelope control points at the exact
|
||||
// same t; the behavior can be well-defined, but it is still incorrect
|
||||
// in that it vastly complicates paste operations behaving as a user
|
||||
// reasonably expects. The most common problem occurs pasting an
|
||||
// envelope into another track; the boundary behavior causes the
|
||||
// t=insert_point envelope level of the insertee to apply to sample 0
|
||||
// of the inserted sample, causing a pop. This most visibly manifests
|
||||
// itself in undo and mixing when a v=1.0 sample magically shows
|
||||
// up at boundaries causing a pop.
|
||||
|
||||
// Although this renders the name a slight misnomer, a duplicate
|
||||
// 'replaces' the current control point.
|
||||
|
||||
/** @brief Add a control point to the envelope
|
||||
*
|
||||
* @param when the time in seconds when the envelope point should be created.
|
||||
@@ -1127,12 +1114,12 @@ void Envelope::RescaleTimes( double newLength )
|
||||
}
|
||||
|
||||
// Accessors
|
||||
double Envelope::GetValue(double t) const
|
||||
double Envelope::GetValue( double t, double sampleDur ) const
|
||||
{
|
||||
// t is absolute time
|
||||
double temp;
|
||||
|
||||
GetValues(&temp, 1, t, 1.0);
|
||||
GetValues( &temp, 1, t, sampleDur );
|
||||
return temp;
|
||||
}
|
||||
|
||||
@@ -1140,7 +1127,7 @@ double Envelope::GetValueRelative(double t) const
|
||||
{
|
||||
double temp;
|
||||
|
||||
GetValuesRelative(&temp, 1, t, 1.0);
|
||||
GetValuesRelative(&temp, 1, t, 0.0);
|
||||
return temp;
|
||||
}
|
||||
|
||||
@@ -1205,8 +1192,8 @@ double Envelope::GetInterpolationStartValueAtPoint( int iPoint ) const
|
||||
return log10(v);
|
||||
}
|
||||
|
||||
void Envelope::GetValues(double *buffer, int bufferLen,
|
||||
double t0, double tstep) const
|
||||
void Envelope::GetValues( double *buffer, int bufferLen,
|
||||
double t0, double tstep ) const
|
||||
{
|
||||
// Convert t0 from absolute to clip-relative time
|
||||
t0 -= mOffset;
|
||||
@@ -1219,9 +1206,14 @@ void Envelope::GetValuesRelative(double *buffer, int bufferLen,
|
||||
// JC: If bufferLen ==0 we have probably just allocated a zero sized buffer.
|
||||
// wxASSERT( bufferLen > 0 );
|
||||
|
||||
const auto epsilon = tstep / 2;
|
||||
int len = mEnv.size();
|
||||
|
||||
double t = t0;
|
||||
double increment = 0;
|
||||
if ( len > 0 && t <= mEnv[0].GetT() && mEnv[0].GetT() == mEnv[1].GetT() )
|
||||
increment = epsilon;
|
||||
|
||||
double tprev, vprev, tnext = 0, vnext, vstep = 0;
|
||||
|
||||
for (int b = 0; b < bufferLen; b++) {
|
||||
@@ -1233,20 +1225,24 @@ void Envelope::GetValuesRelative(double *buffer, int bufferLen,
|
||||
t += tstep;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto tplus = t + increment;
|
||||
|
||||
// IF before envelope THEN first value
|
||||
if (t <= mEnv[0].GetT()) {
|
||||
if ( tplus <= mEnv[0].GetT() ) {
|
||||
buffer[b] = mEnv[0].GetVal();
|
||||
t += tstep;
|
||||
continue;
|
||||
}
|
||||
// IF after envelope THEN last value
|
||||
if (t >= mEnv[len - 1].GetT()) {
|
||||
if ( tplus >= mEnv[len - 1].GetT() ) {
|
||||
buffer[b] = mEnv[len - 1].GetVal();
|
||||
t += tstep;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == 0 || t > tnext) {
|
||||
// Note >= not > , to get the right limit in case epsilon == 0
|
||||
if ( b == 0 || tplus >= tnext ) {
|
||||
|
||||
// We're beyond our tnext, so find the next one.
|
||||
// Don't just increment lo or hi because we might
|
||||
@@ -1254,12 +1250,23 @@ void Envelope::GetValuesRelative(double *buffer, int bufferLen,
|
||||
// points to move over. That's why we binary search.
|
||||
|
||||
int lo,hi;
|
||||
BinarySearchForTime( lo, hi, t );
|
||||
// mEnv[0] is before t because of eliminations above, therefore lo >= 0
|
||||
// mEnv[len - 1] is after t, therefore hi <= len - 1
|
||||
BinarySearchForTime( lo, hi, tplus );
|
||||
// mEnv[0] is before tplus because of eliminations above, therefore lo >= 0
|
||||
// mEnv[len - 1] is after tplus, therefore hi <= len - 1
|
||||
|
||||
tprev = mEnv[lo].GetT();
|
||||
tnext = mEnv[hi].GetT();
|
||||
|
||||
if ( hi + 1 < len && tnext == mEnv[ hi + 1 ].GetT() )
|
||||
// There is a discontinuity after this point-to-point interval.
|
||||
// Will stop evaluating in this interval when time is slightly
|
||||
// before tNext, then use the right limit. This is the right intent
|
||||
// in case small roundoff errors cause a sample time to be a little
|
||||
// before the envelope point time.
|
||||
increment = epsilon;
|
||||
else
|
||||
increment = 0;
|
||||
|
||||
vprev = GetInterpolationStartValueAtPoint( lo );
|
||||
vnext = GetInterpolationStartValueAtPoint( hi );
|
||||
|
||||
|
Reference in New Issue
Block a user