mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-05 14:18:53 +02:00
Update envelope properly for TimeTrack and WaveTrack editing...
... Formerly this was done correctly only for cut and delete from WaveTrack, paste into WaveTrack, and sync-lock adjustment of WaveTrack (either lengthening or shortening). Now also properly done for TimeTrack cut and paste, and also for: Split cut Split delete Trim
This commit is contained in:
parent
2d84c65c94
commit
aba52bc79e
@ -606,34 +606,60 @@ bool EnvelopeEditor::MouseEvent(const wxMouseEvent & event, wxRect & r,
|
||||
return false;
|
||||
}
|
||||
|
||||
void Envelope::CollapseRegion(double t0, double t1)
|
||||
void Envelope::CollapseRegion( double t0, double t1, double sampleTime )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
// This gets called when somebody clears samples. All of the
|
||||
// control points within the region disappear and the points
|
||||
// to the right get shifted over.
|
||||
// This gets called when somebody clears samples.
|
||||
|
||||
t0 -= mOffset;
|
||||
t1 -= mOffset;
|
||||
// Snip points in the interval (t0, t1), shift values left at times after t1.
|
||||
// For the boundaries of the interval, preserve the left-side limit at the
|
||||
// start and right-side limit at the end.
|
||||
|
||||
t0 = std::max(0.0, std::min(mTrackLen, t0));
|
||||
t1 = std::max(0.0, std::min(mTrackLen, t1));
|
||||
const auto epsilon = sampleTime / 2;
|
||||
t0 = std::max( 0.0, std::min( mTrackLen, t0 - mOffset ) );
|
||||
t1 = std::max( 0.0, std::min( mTrackLen, t1 - mOffset ) );
|
||||
|
||||
int len = mEnv.size();
|
||||
int i;
|
||||
|
||||
// Remove points in deleted region.
|
||||
for (i = 0; i < len - 0; i++)
|
||||
if (mEnv[i].GetT() >= t0 && mEnv[i].GetT() < t1) {
|
||||
Delete(i);
|
||||
len--;
|
||||
i--;
|
||||
// Determine the start of the range of points to remove from the array.
|
||||
auto range0 = EqualRange( t0, 0 );
|
||||
auto begin = range0.first;
|
||||
if ( begin == range0.second ) {
|
||||
if ( t0 > epsilon ) {
|
||||
// There was no point exactly at t0;
|
||||
// insert a point to preserve the value.
|
||||
auto val = GetValueRelative( t0 );
|
||||
InsertOrReplaceRelative( t0, val );
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
else
|
||||
// We will keep the first (or only) point that was at t0.
|
||||
++begin;
|
||||
|
||||
// We want end to be the index one past the range of points to remove from
|
||||
// the array.
|
||||
// At first, find index of the first point after t1:
|
||||
auto range1 = EqualRange( t1, 0 );
|
||||
auto end = range1.second;
|
||||
if ( range1.first == end ) {
|
||||
if ( mTrackLen - t1 > epsilon ) {
|
||||
// There was no point exactly at t1; insert a point to preserve the value.
|
||||
auto val = GetValueRelative( t1 );
|
||||
InsertOrReplaceRelative( t1, val );
|
||||
// end is now the index of this NEW point and that is correct.
|
||||
}
|
||||
}
|
||||
else
|
||||
// We will keep the last (or only) point that was at t1.
|
||||
--end;
|
||||
|
||||
mEnv.erase( mEnv.begin() + begin, mEnv.begin() + end );
|
||||
|
||||
// Shift points left after deleted region.
|
||||
for (i = 0; i < len; i++)
|
||||
if (mEnv[i].GetT() >= t1)
|
||||
mEnv[i].SetT(mEnv[i].GetT() - (t1 - t0));
|
||||
auto len = mEnv.size();
|
||||
for ( size_t i = begin; i < len; ++i ) {
|
||||
auto &point = mEnv[i];
|
||||
point.SetT( point.GetT() - (t1 - t0) );
|
||||
}
|
||||
|
||||
mTrackLen -= ( t1 - t0 );
|
||||
}
|
||||
|
@ -118,8 +118,11 @@ public:
|
||||
float zoomMin, float zoomMax, bool mirrored) const;
|
||||
|
||||
// Handling Cut/Copy/Paste events
|
||||
void CollapseRegion(double t0, double t1);
|
||||
// sampleTime determines when the endpoint of the collapse is near enough
|
||||
// to an endpoint of the domain, that an extra control point is not needed.
|
||||
void CollapseRegion(double t0, double t1, double sampleTime);
|
||||
void Paste(double t0, const Envelope *e);
|
||||
|
||||
void InsertSpace(double t0, double tlen);
|
||||
void RemoveUnneededPoints(double time = -1, double tolerence = 0.001);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "widgets/Ruler.h"
|
||||
#include "Envelope.h"
|
||||
#include "Prefs.h"
|
||||
#include "Project.h"
|
||||
#include "Internat.h"
|
||||
#include "ViewInfo.h"
|
||||
#include "AllThemeResources.h"
|
||||
@ -108,7 +109,8 @@ Track::Holder TimeTrack::Copy( double t0, double t1, bool ) const
|
||||
|
||||
void TimeTrack::Clear(double t0, double t1)
|
||||
{
|
||||
mEnvelope->CollapseRegion(t0, t1);
|
||||
auto sampleTime = 1.0 / GetActiveProject()->GetRate();
|
||||
mEnvelope->CollapseRegion( t0, t1, sampleTime );
|
||||
}
|
||||
|
||||
void TimeTrack::Paste(double t, const Track * src)
|
||||
|
@ -1676,7 +1676,8 @@ void WaveClip::Clear(double t0, double t1)
|
||||
}
|
||||
|
||||
// Collapse envelope
|
||||
GetEnvelope()->CollapseRegion(t0, t1);
|
||||
auto sampleTime = 1.0 / GetRate();
|
||||
GetEnvelope()->CollapseRegion( t0, t1, sampleTime );
|
||||
if (t0 < GetStartTime())
|
||||
Offset(-(GetStartTime() - t0));
|
||||
|
||||
@ -1728,7 +1729,8 @@ void WaveClip::ClearAndAddCutLine(double t0, double t1)
|
||||
GetSequence()->Delete(s0, s1-s0);
|
||||
|
||||
// Collapse envelope
|
||||
GetEnvelope()->CollapseRegion(t0, t1);
|
||||
auto sampleTime = 1.0 / GetRate();
|
||||
GetEnvelope()->CollapseRegion( t0, t1, sampleTime );
|
||||
if (t0 < GetStartTime())
|
||||
Offset(-(GetStartTime() - t0));
|
||||
|
||||
|
@ -1138,26 +1138,7 @@ void WaveTrack::HandleClear(double t0, double t1,
|
||||
clipsToDelete.push_back( clip.get() );
|
||||
auto newClip = make_movable<WaveClip>( *clip, mDirManager, true );
|
||||
|
||||
/* We are going to DELETE part of the clip here. The clip may
|
||||
* have envelope points, and we need to ensure that the envelope
|
||||
* outside of the cleared region is not affected. This means
|
||||
* putting in "glue" points where the clip enters and leaves the
|
||||
* region being cleared. If one of the ends of the clip is inside
|
||||
* the region, then one of the glue points will be redundant. */
|
||||
// clip->Clear keeps points < t0 and >= t1 via Envelope::CollapseRegion
|
||||
if (clip->GetEnvelope()->GetNumberOfPoints() > 0) { // don't insert env pts if none exist
|
||||
double val;
|
||||
if (clip->WithinClip(t0)) {
|
||||
// start of region within clip
|
||||
val = clip->GetEnvelope()->GetValue(t0);
|
||||
newClip->GetEnvelope()->InsertOrReplace(t0 - 1.0 / clip->GetRate(), val);
|
||||
}
|
||||
if (clip->WithinClip(t1))
|
||||
{ // end of region within clip
|
||||
val = clip->GetEnvelope()->GetValue(t1);
|
||||
newClip->GetEnvelope()->InsertOrReplace(t1 , val);
|
||||
}
|
||||
}
|
||||
newClip->Clear(t0,t1);
|
||||
newClip->GetEnvelope()->RemoveUnneededPoints(t0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user