mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-26 00:58:37 +02:00
More envelope fixes, including some for 1643, 1644
This commit is contained in:
commit
85e984de63
182
src/Envelope.cpp
182
src/Envelope.cpp
@ -74,7 +74,7 @@ void Envelope::RescaleValues(double minValue, double maxValue)
|
||||
// rescale all points
|
||||
for( unsigned int i = 0; i < mEnv.size(); i++ ) {
|
||||
factor = (mEnv[i].GetVal() - oldMinValue) / (oldMaxValue - oldMinValue);
|
||||
mEnv[i].SetVal(mMinValue + (mMaxValue - mMinValue) * factor);
|
||||
mEnv[i].SetVal( this, mMinValue + (mMaxValue - mMinValue) * factor );
|
||||
}
|
||||
|
||||
}
|
||||
@ -112,13 +112,13 @@ void Envelope::SetDragPointValid(bool valid)
|
||||
// off screen and at default height.
|
||||
// temporary state when dragging only!
|
||||
mEnv[mDragPoint].SetT(big);
|
||||
mEnv[mDragPoint].SetVal(mDefaultValue);
|
||||
mEnv[mDragPoint].SetVal( this, mDefaultValue );
|
||||
return;
|
||||
}
|
||||
else if ( mDragPoint + 1 == size ) {
|
||||
// Put the point at the height of the last point, but also off screen.
|
||||
mEnv[mDragPoint].SetT(big);
|
||||
mEnv[mDragPoint].SetVal(mEnv[ size - 1 ].GetVal());
|
||||
mEnv[mDragPoint].SetVal( this, mEnv[ size - 1 ].GetVal() );
|
||||
}
|
||||
else {
|
||||
// Place it exactly on its right neighbour.
|
||||
@ -126,7 +126,7 @@ void Envelope::SetDragPointValid(bool valid)
|
||||
// a light dot, as if it were deleted.
|
||||
const auto &neighbor = mEnv[mDragPoint + 1];
|
||||
mEnv[mDragPoint].SetT(neighbor.GetT());
|
||||
mEnv[mDragPoint].SetVal(neighbor.GetVal());
|
||||
mEnv[mDragPoint].SetVal( this, neighbor.GetVal() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -154,7 +154,7 @@ void Envelope::MoveDragPoint(double newWhen, double value)
|
||||
// This might temporary violate the constraint that at most two
|
||||
// points share a time value.
|
||||
dragPoint.SetT(tt);
|
||||
dragPoint.SetVal(value);
|
||||
dragPoint.SetVal( this, value );
|
||||
}
|
||||
|
||||
void Envelope::ClearDragPoint()
|
||||
@ -171,13 +171,26 @@ void Envelope::SetRange(double minValue, double maxValue) {
|
||||
mMaxValue = maxValue;
|
||||
mDefaultValue = ClampValue(mDefaultValue);
|
||||
for( unsigned int i = 0; i < mEnv.size(); i++ )
|
||||
mEnv[i].SetVal(mEnv[i].GetVal()); // this clamps the value to the NEW range
|
||||
mEnv[i].SetVal( this, mEnv[i].GetVal() ); // this clamps the value to the NEW range
|
||||
}
|
||||
|
||||
EnvPoint *Envelope::AddPointAtEnd( double t, double val )
|
||||
// This is used only during construction of an Envelope by complete or partial
|
||||
// copy of another, or when truncating a track.
|
||||
void Envelope::AddPointAtEnd( double t, double val )
|
||||
{
|
||||
mEnv.push_back(EnvPoint(this, t, val));
|
||||
return &mEnv.back();
|
||||
mEnv.push_back( EnvPoint{ t, val } );
|
||||
|
||||
// Assume copied points were stored by nondecreasing time.
|
||||
// Allow no more than two points at exactly the same time.
|
||||
// Maybe that happened, because extra points were inserted at the boundary
|
||||
// of the copied range, which were not in the source envelope.
|
||||
auto nn = mEnv.size() - 1;
|
||||
while ( nn >= 2 && mEnv[ nn - 2 ].GetT() == t ) {
|
||||
// Of three or more points at the same time, erase one in the middle,
|
||||
// not the one newly added.
|
||||
mEnv.erase( mEnv.begin() + nn - 1 );
|
||||
--nn;
|
||||
}
|
||||
}
|
||||
|
||||
Envelope::Envelope(const Envelope &orig, double t0, double t1)
|
||||
@ -342,7 +355,8 @@ XMLTagHandler *Envelope::HandleXMLChild(const wxChar *tag)
|
||||
if (wxStrcmp(tag, wxT("controlpoint")))
|
||||
return NULL;
|
||||
|
||||
return AddPointAtEnd(0,0);
|
||||
mEnv.push_back( EnvPoint{} );
|
||||
return &mEnv.back();
|
||||
}
|
||||
|
||||
void Envelope::WriteXML(XMLWriter &xmlFile) const
|
||||
@ -592,36 +606,62 @@ 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);
|
||||
mTrackLen -= ( t1 - t0 );
|
||||
}
|
||||
|
||||
// This operation is trickier than it looks; the basic rub is that
|
||||
@ -869,17 +909,37 @@ void Envelope::RemoveUnneededPoints(double time, double tolerence)
|
||||
}
|
||||
}
|
||||
|
||||
void Envelope::InsertSpace(double t0, double tlen)
|
||||
void Envelope::InsertSpace( double t0, double tlen )
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
t0 -= mOffset;
|
||||
|
||||
unsigned int len = mEnv.size();
|
||||
unsigned int i;
|
||||
// Preserve the left-side limit at the split.
|
||||
auto val = GetValueRelative( t0 );
|
||||
auto range = EqualRange( t0, 0 );
|
||||
|
||||
size_t index;
|
||||
if ( range.first < range.second )
|
||||
// There is already a control point.
|
||||
index = 1 + range.first;
|
||||
else
|
||||
// Make a control point.
|
||||
index = 1 + InsertOrReplaceRelative( t0, val );
|
||||
|
||||
// Shift points.
|
||||
auto len = mEnv.size();
|
||||
for ( ; index < len; ++index ) {
|
||||
auto &point = mEnv[ index ];
|
||||
point.SetT( point.GetT() + tlen );
|
||||
}
|
||||
|
||||
// Preserve the right-side limit.
|
||||
if ( 1 + range.first < range.second )
|
||||
// There was a control point already.
|
||||
;
|
||||
else
|
||||
InsertOrReplaceRelative( t0 + tlen, val );
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
if (mEnv[i].GetT() > t0)
|
||||
mEnv[i].SetT(mEnv[i].GetT() + tlen);
|
||||
mTrackLen += tlen;
|
||||
}
|
||||
|
||||
@ -898,7 +958,7 @@ int Envelope::Reassign(double when, double value)
|
||||
if (i >= len || when < mEnv[i].GetT())
|
||||
return -1;
|
||||
|
||||
mEnv[i].SetVal(value);
|
||||
mEnv[i].SetVal( this, value );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -978,15 +1038,12 @@ int Envelope::InsertOrReplaceRelative(double when, double value)
|
||||
while (i < len && when > mEnv[i].GetT())
|
||||
i++;
|
||||
|
||||
if(i < len && when == mEnv[i].GetT()) {
|
||||
|
||||
if(i < len && when == mEnv[i].GetT())
|
||||
// modify existing
|
||||
mEnv[i].SetVal(value);
|
||||
|
||||
}
|
||||
mEnv[i].SetVal( this, value );
|
||||
else {
|
||||
// Add NEW
|
||||
EnvPoint e(this, when, value);
|
||||
EnvPoint e{ when, value };
|
||||
if (i < len) {
|
||||
Insert(i, e);
|
||||
} else {
|
||||
@ -1007,12 +1064,12 @@ std::pair<int, int> Envelope::EqualRange( double when, double sampleTime ) const
|
||||
auto end = mEnv.end();
|
||||
auto first = std::lower_bound(
|
||||
begin, end,
|
||||
EnvPoint{ const_cast<Envelope*>( this ), when - tolerance, 0.0 },
|
||||
EnvPoint{ 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 )
|
||||
while ( after != end && after->GetT() <= when + tolerance )
|
||||
++after;
|
||||
return { first - begin, after - begin };
|
||||
}
|
||||
@ -1026,16 +1083,20 @@ void Envelope::SetOffset(double newOffset)
|
||||
}
|
||||
|
||||
void Envelope::SetTrackLen(double trackLen)
|
||||
// NOFAIL-GUARANTEE
|
||||
{
|
||||
mTrackLen = trackLen;
|
||||
// Preserve the right-side limit at trackLen.
|
||||
bool needPoint = ( trackLen < mTrackLen );
|
||||
double value;
|
||||
if ( needPoint )
|
||||
value = GetValueRelative( trackLen );
|
||||
|
||||
int len = mEnv.size();
|
||||
for (int i = 0; i < len; i++)
|
||||
if (mEnv[i].GetT() > mTrackLen) {
|
||||
Delete(i);
|
||||
len--;
|
||||
i--;
|
||||
}
|
||||
mTrackLen = trackLen;
|
||||
int newLen = EqualRange( trackLen, 0 ).second;
|
||||
mEnv.resize( newLen );
|
||||
|
||||
if ( needPoint )
|
||||
AddPointAtEnd( mTrackLen, value );
|
||||
}
|
||||
|
||||
void Envelope::RescaleTimes( double newLength )
|
||||
@ -1063,6 +1124,14 @@ double Envelope::GetValue(double t) const
|
||||
return temp;
|
||||
}
|
||||
|
||||
double Envelope::GetValueRelative(double t) const
|
||||
{
|
||||
double temp;
|
||||
|
||||
GetValuesRelative(&temp, 1, t, 1.0);
|
||||
return temp;
|
||||
}
|
||||
|
||||
// relative time
|
||||
/// @param Lo returns last index at or before this time, maybe -1
|
||||
/// @param Hi returns first index after this time, maybe past the end
|
||||
@ -1129,7 +1198,12 @@ void Envelope::GetValues(double *buffer, int bufferLen,
|
||||
{
|
||||
// Convert t0 from absolute to clip-relative time
|
||||
t0 -= mOffset;
|
||||
GetValuesRelative( buffer, bufferLen, t0, tstep);
|
||||
}
|
||||
|
||||
void Envelope::GetValuesRelative(double *buffer, int bufferLen,
|
||||
double t0, double tstep) const
|
||||
{
|
||||
// JC: If bufferLen ==0 we have probably just allocated a zero sized buffer.
|
||||
// wxASSERT( bufferLen > 0 );
|
||||
|
||||
|
@ -36,12 +36,13 @@ class ZoomInfo;
|
||||
class EnvPoint final : public XMLTagHandler {
|
||||
|
||||
public:
|
||||
inline EnvPoint(Envelope *envelope, double t, double val);
|
||||
EnvPoint() {}
|
||||
inline EnvPoint( double t, double val ) : mT{ t }, mVal{ val } {}
|
||||
|
||||
double GetT() const { return mT; }
|
||||
void SetT(double t) { mT = t; }
|
||||
double GetVal() const { return mVal; }
|
||||
inline void SetVal(double val);
|
||||
inline void SetVal( Envelope *pEnvelope, double val );
|
||||
|
||||
bool HandleXMLTag(const wxChar *tag, const wxChar **attrs) override
|
||||
{
|
||||
@ -52,7 +53,7 @@ public:
|
||||
if (!wxStrcmp(attr, wxT("t")))
|
||||
SetT(Internat::CompatibleToDouble(value));
|
||||
else if (!wxStrcmp(attr, wxT("val")))
|
||||
SetVal(Internat::CompatibleToDouble(value));
|
||||
SetVal( nullptr, Internat::CompatibleToDouble(value) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -66,9 +67,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Envelope *mEnvelope;
|
||||
double mT;
|
||||
double mVal;
|
||||
double mT {};
|
||||
double mVal {};
|
||||
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -145,6 +148,9 @@ public:
|
||||
(double *buffer, int bufferLen, int leftOffset, const ZoomInfo &zoomInfo) const;
|
||||
|
||||
private:
|
||||
double GetValueRelative(double t) const;
|
||||
void GetValuesRelative
|
||||
(double *buffer, int len, double t0, double tstep) const;
|
||||
// relative time
|
||||
int NumberOfPointsAfter(double t) const;
|
||||
// relative time
|
||||
@ -212,7 +218,7 @@ private:
|
||||
void MoveDragPoint(double newWhen, double value);
|
||||
// May delete the drag point. Restores envelope consistency.
|
||||
void ClearDragPoint();
|
||||
EnvPoint * AddPointAtEnd( double t, double val );
|
||||
void AddPointAtEnd( double t, double val );
|
||||
void CopyRange(const Envelope &orig, size_t begin, size_t end);
|
||||
// relative time
|
||||
void BinarySearchForTime( int &Lo, int &Hi, double t ) const;
|
||||
@ -243,16 +249,11 @@ private:
|
||||
mutable int mSearchGuess { -2 };
|
||||
};
|
||||
|
||||
inline EnvPoint::EnvPoint(Envelope *envelope, double t, double val)
|
||||
inline void EnvPoint::SetVal( Envelope *pEnvelope, double val )
|
||||
{
|
||||
mEnvelope = envelope;
|
||||
mT = t;
|
||||
mVal = mEnvelope->ClampValue(val);
|
||||
}
|
||||
|
||||
inline void EnvPoint::SetVal(double val)
|
||||
{
|
||||
mVal = mEnvelope->ClampValue(val);
|
||||
if ( pEnvelope )
|
||||
val = pEnvelope->ClampValue(val);
|
||||
mVal = val;
|
||||
}
|
||||
|
||||
// A class that holds state for the duration of dragging
|
||||
|
@ -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)
|
||||
|
@ -1607,7 +1607,7 @@ void WaveClip::Paste(double t0, const WaveClip* other)
|
||||
mCutLines.push_back(std::move(holder));
|
||||
}
|
||||
|
||||
void WaveClip::InsertSilence(double t, double len)
|
||||
void WaveClip::InsertSilence( double t, double len, double *pEnvelopeValue )
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
sampleCount s0;
|
||||
@ -1619,10 +1619,35 @@ void WaveClip::InsertSilence(double t, double len)
|
||||
|
||||
// use NOFAIL-GUARANTEE
|
||||
OffsetCutLines(t, len);
|
||||
GetEnvelope()->InsertSpace(t, len);
|
||||
|
||||
const auto sampleTime = 1.0 / GetRate();
|
||||
auto pEnvelope = GetEnvelope();
|
||||
if ( pEnvelopeValue ) {
|
||||
|
||||
// Preserve limit value at the end
|
||||
auto oldLen = pEnvelope->GetTrackLen();
|
||||
auto oldT = pEnvelope->GetOffset() + oldLen;
|
||||
auto newLen = oldLen + len;
|
||||
pEnvelope->InsertOrReplace( oldT, pEnvelope->GetValue( oldT ) );
|
||||
|
||||
// Ramp across the silence to the given value
|
||||
pEnvelope->SetTrackLen( newLen );
|
||||
pEnvelope->InsertOrReplace
|
||||
( pEnvelope->GetOffset() + newLen, *pEnvelopeValue );
|
||||
}
|
||||
else
|
||||
pEnvelope->InsertSpace( t, len );
|
||||
|
||||
MarkChanged();
|
||||
}
|
||||
|
||||
void WaveClip::AppendSilence( double len, double envelopeValue )
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
auto t = GetEndTime();
|
||||
InsertSilence( t, len, &envelopeValue );
|
||||
}
|
||||
|
||||
void WaveClip::Clear(double t0, double t1)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
@ -1676,7 +1701,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 +1754,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));
|
||||
|
||||
|
@ -321,7 +321,11 @@ public:
|
||||
|
||||
/** Insert silence - note that this is an efficient operation for large
|
||||
* amounts of silence */
|
||||
void InsertSilence(double t, double len);
|
||||
void InsertSilence( double t, double len, double *pEnvelopeValue = nullptr );
|
||||
|
||||
/** Insert silence at the end, and causes the envelope to ramp
|
||||
linearly to the given value */
|
||||
void AppendSilence( double len, double envelopeValue );
|
||||
|
||||
/// Get access to cut lines list
|
||||
WaveClipHolders &GetCutLines() { return mCutLines; }
|
||||
|
@ -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);
|
||||
|
||||
@ -1583,12 +1564,15 @@ void WaveTrack::Join(double t0, double t1)
|
||||
if (clip->GetOffset() - t > (1.0 / mRate)) {
|
||||
double addedSilence = (clip->GetOffset() - t);
|
||||
//printf("Adding %.6f seconds of silence\n");
|
||||
newClip->InsertSilence(t, addedSilence);
|
||||
auto offset = clip->GetOffset();
|
||||
auto value = clip->GetEnvelope()->GetValue( offset );
|
||||
newClip->AppendSilence( addedSilence, value );
|
||||
t += addedSilence;
|
||||
}
|
||||
|
||||
//printf("Pasting at %.6f\n", t);
|
||||
newClip->Paste(t, clip);
|
||||
|
||||
t = newClip->GetEndTime();
|
||||
|
||||
auto it = FindClip(mClips, clip);
|
||||
@ -2398,12 +2382,6 @@ void WaveTrack::SplitAt(double t)
|
||||
{
|
||||
double val;
|
||||
t = LongSamplesToTime(TimeToLongSamples(t)); // put t on a sample
|
||||
val = c->GetEnvelope()->GetValue(t);
|
||||
//make two envelope points to preserve the value.
|
||||
//handle the case where we split on the 1st sample (without this we hit an assert)
|
||||
if(t - 1.0/c->GetRate() >= c->GetOffset())
|
||||
c->GetEnvelope()->InsertOrReplace(t - 1.0 / c->GetRate(), val); // frame end points
|
||||
c->GetEnvelope()->InsertOrReplace(t, val);
|
||||
auto newClip = make_movable<WaveClip>( *c, mDirManager, true );
|
||||
c->Clear(t, c->GetEndTime());
|
||||
newClip->Clear(c->GetStartTime(), t);
|
||||
|
Loading…
x
Reference in New Issue
Block a user