Change lots of code that uses linking to use the new
scheme.
This commit is contained in:
parent
98ca2b474b
commit
e35e019e17
|
@ -90,6 +90,7 @@ LabelTrack::LabelTrack(DirManager * projDirManager):
|
|||
mSelIndex(-1),
|
||||
mMouseOverLabelLeft(-1),
|
||||
mMouseOverLabelRight(-1),
|
||||
mClipLen(0.0),
|
||||
mIsAdjustingLabel(false)
|
||||
{
|
||||
SetDefaultName(_("Label Track"));
|
||||
|
@ -114,6 +115,7 @@ LabelTrack::LabelTrack(const LabelTrack &orig) :
|
|||
mSelIndex(-1),
|
||||
mMouseOverLabelLeft(-1),
|
||||
mMouseOverLabelRight(-1),
|
||||
mClipLen(0.0),
|
||||
mIsAdjustingLabel(false)
|
||||
{
|
||||
int len = orig.mLabels.Count();
|
||||
|
@ -149,7 +151,7 @@ void LabelTrack::SetOffset(double dOffset)
|
|||
}
|
||||
}
|
||||
|
||||
void LabelTrack::ShiftLabelsOnClear(double b, double e)
|
||||
bool LabelTrack::Clear(double b, double e)
|
||||
{
|
||||
for (size_t i=0;i<mLabels.GetCount();i++){
|
||||
if (mLabels[i]->t >= e){//label is after deletion region
|
||||
|
@ -169,10 +171,12 @@ void LabelTrack::ShiftLabelsOnClear(double b, double e)
|
|||
//nothing
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//used when we want to use clear only on the labels
|
||||
void LabelTrack::ChangeLabelsOnClear(double b, double e)
|
||||
bool LabelTrack::SplitDelete(double b, double e)
|
||||
{
|
||||
for (size_t i=0;i<mLabels.GetCount();i++) {
|
||||
if (mLabels[i]->t >= b && mLabels[i]->t1 <= e){//deletion region encloses label
|
||||
|
@ -186,6 +190,8 @@ void LabelTrack::ChangeLabelsOnClear(double b, double e)
|
|||
mLabels[i]->t1 = b;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void LabelTrack::ShiftLabelsOnInsert(double length, double pt)
|
||||
{
|
||||
|
@ -2135,7 +2141,17 @@ bool LabelTrack::Save(wxTextFile * out, bool overwrite)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool LabelTrack::Cut(double t0, double t1, Track ** dest)
|
||||
bool LabelTrack::Cut(double t0, double t1, Track **dest)
|
||||
{
|
||||
if (!SplitCut(t0, t1, dest))
|
||||
return false;
|
||||
if (!Clear(t0, t1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LabelTrack::SplitCut(double t0, double t1, Track ** dest)
|
||||
{
|
||||
*dest = new LabelTrack(GetDirManager());
|
||||
int len = mLabels.Count();
|
||||
|
@ -2182,7 +2198,7 @@ bool LabelTrack::Copy(double t0, double t1, Track ** dest)
|
|||
}
|
||||
|
||||
|
||||
bool LabelTrack::Paste(double t, Track * src)
|
||||
bool LabelTrack::PasteOver(double t, Track * src)
|
||||
{
|
||||
if (src->GetKind() != Track::Label)
|
||||
return false;
|
||||
|
@ -2206,11 +2222,20 @@ bool LabelTrack::Paste(double t, Track * src)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LabelTrack::Paste(double t, Track *src)
|
||||
{
|
||||
if (src->GetKind() != Track::Label)
|
||||
return false;
|
||||
|
||||
LabelTrack *lt = (LabelTrack *)src;
|
||||
|
||||
double shiftAmt = lt->mClipLen > 0.0 ? lt->mClipLen : lt->GetEndTime();
|
||||
|
||||
ShiftLabelsOnInsert(shiftAmt, t);
|
||||
return PasteOver(t, src);
|
||||
}
|
||||
|
||||
// This repeats the labels in a time interval a specified number of times.
|
||||
// Like Paste(), it does not shift existing labels over
|
||||
// - It assumes that you've already called ShiftLabelsOnInsert(), because
|
||||
// sometimes with linking enabled that's hard to avoid.
|
||||
// - It assumes that you inserted the necessary extra time at t1, not t0.
|
||||
bool LabelTrack::Repeat(double t0, double t1, int n)
|
||||
{
|
||||
// Sanity-check the arguments
|
||||
|
@ -2218,6 +2243,9 @@ bool LabelTrack::Repeat(double t0, double t1, int n)
|
|||
|
||||
double tLen = t1 - t0;
|
||||
|
||||
// Insert space for the repetitions
|
||||
ShiftLabelsOnInsert(tLen * n, t1);
|
||||
|
||||
for (unsigned int i = 0; i < mLabels.GetCount(); i++)
|
||||
{
|
||||
if (mLabels[i]->t >= t0 && mLabels[i]->t <= t1 &&
|
||||
|
@ -2254,30 +2282,6 @@ bool LabelTrack::Repeat(double t0, double t1, int n)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LabelTrack::Clear(double t0, double t1)
|
||||
{
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (p && p->IsSticky()){
|
||||
TrackGroupIterator grpIter(p->GetTracks());
|
||||
Track *t = grpIter.First(this);
|
||||
// If this track is part of a group, find a Wave track in the group and do
|
||||
// the clear from there to ensure proper group behavior
|
||||
while (t) {
|
||||
if (t->GetKind() == Track::Wave) {
|
||||
return t->Clear(t0, t1);
|
||||
}
|
||||
t = grpIter.Next();
|
||||
}
|
||||
|
||||
// Fallback: shift labels in this track
|
||||
ShiftLabelsOnClear(t0, t1);
|
||||
}
|
||||
else
|
||||
ChangeLabelsOnClear(t0, t1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LabelTrack::Silence(double t0, double t1)
|
||||
{
|
||||
int len = mLabels.Count();
|
||||
|
|
|
@ -175,8 +175,10 @@ class LabelTrack:public Track {
|
|||
void MayAdjustLabel( int iLabel, int iEdge, bool bAllowSwapping, double fNewTime);
|
||||
void MayMoveLabel( int iLabel, int iEdge, double fNewTime);
|
||||
|
||||
void ShiftLabelsOnClear(double b, double e);
|
||||
void ChangeLabelsOnClear(double b, double e);
|
||||
// This pastes labels without shifting existing ones
|
||||
bool PasteOver(double t, Track *src);
|
||||
bool SplitCut(double b, double e, Track **dest);
|
||||
bool SplitDelete(double b, double e);
|
||||
void ShiftLabelsOnInsert(double length, double pt);
|
||||
void ChangeLabelsOnReverse(double b, double e);
|
||||
void ScaleLabels(double b, double e, double change);
|
||||
|
@ -221,7 +223,7 @@ class LabelTrack:public Track {
|
|||
bool mRightDragging; /// flag to tell if it's a valid dragging
|
||||
bool mDrawCursor; /// flag to tell if drawing the cursor or not
|
||||
|
||||
// Used only for a LabelTrack on the clipboard
|
||||
// Set in copied label tracks
|
||||
double mClipLen;
|
||||
|
||||
void ComputeLayout(const wxRect & r, double h, double pps);
|
||||
|
|
|
@ -2992,7 +2992,7 @@ void AudacityProject::OnRedo()
|
|||
|
||||
void AudacityProject::OnCut()
|
||||
{
|
||||
TrackAndGroupIterator iter(mTracks);
|
||||
TrackListIterator iter(mTracks);
|
||||
Track *n = iter.First();
|
||||
Track *dest;
|
||||
|
||||
|
@ -3042,7 +3042,8 @@ void AudacityProject::OnCut()
|
|||
|
||||
n = iter.First();
|
||||
while (n) {
|
||||
if (n->GetSelected()) {
|
||||
// We clear from selected and synchro-selected tracks
|
||||
if (n->GetSelected() || n->IsSynchroSelected()) {
|
||||
switch (n->GetKind())
|
||||
{
|
||||
#if defined(USE_MIDI)
|
||||
|
@ -3064,12 +3065,7 @@ void AudacityProject::OnCut()
|
|||
break;
|
||||
}
|
||||
}
|
||||
// Selected wave and label tracks may need group iteration
|
||||
if (IsSticky() && n->GetSelected() &&
|
||||
(n->GetKind() == Track::Wave || n->GetKind() == Track::Label))
|
||||
n = iter.NextGroup();
|
||||
else
|
||||
n = iter.Next();
|
||||
n = iter.Next();
|
||||
}
|
||||
|
||||
msClipLen = (mViewInfo.sel1 - mViewInfo.sel0);
|
||||
|
@ -3299,10 +3295,6 @@ void AudacityProject::OnPaste()
|
|||
bool trackTypeMismatch = false;
|
||||
bool advanceClipboard = true;
|
||||
|
||||
// Keeps track of whether n would be the first WaveTrack in its group to
|
||||
// receive data from the paste.
|
||||
bool firstInGroup = true;
|
||||
|
||||
while (n && c) {
|
||||
if (n->GetSelected()) {
|
||||
advanceClipboard = true;
|
||||
|
@ -3329,8 +3321,6 @@ void AudacityProject::OnPaste()
|
|||
c = tmpC;
|
||||
while (n && (c->GetKind() != n->GetKind()) )
|
||||
{
|
||||
if (n && n->GetKind() == Track::Label)
|
||||
firstInGroup = true;
|
||||
n = iter.Next();
|
||||
}
|
||||
if (!n) c = NULL;
|
||||
|
@ -3368,25 +3358,19 @@ void AudacityProject::OnPaste()
|
|||
{
|
||||
// If not the first in group we set useHandlePaste to true
|
||||
pastedSomething = ((WaveTrack*)n)->ClearAndPaste(t0, t1,
|
||||
(WaveTrack*)c, true, true, NULL, false, !firstInGroup);
|
||||
firstInGroup = firstInGroup && !pastedSomething;
|
||||
(WaveTrack*)c, true, true);
|
||||
}
|
||||
else if (c->GetKind() == Track::Label &&
|
||||
n && n->GetKind() == Track::Label)
|
||||
{
|
||||
// AWD: LabelTrack::Paste() doesn't shift future labels (and
|
||||
// WaveTrack::HandleGroupPaste() doesn't adjust selected group
|
||||
// tracks, so some other track's paste hasn't done it either). To
|
||||
// be (sort of) consistent with Clear behavior, we'll only shift
|
||||
// them if linking is on and we have already pasted into a wave
|
||||
// track in this group.
|
||||
if (IsSticky() && !firstInGroup)
|
||||
{
|
||||
((LabelTrack *)n)->ShiftLabelsOnClear(t0, t1);
|
||||
((LabelTrack *)n)->ShiftLabelsOnInsert(msClipLen, t0);
|
||||
}
|
||||
((LabelTrack *)n)->Clear(t0, t1);
|
||||
|
||||
pastedSomething = n->Paste(t0, c);
|
||||
// To be (sort of) consistent with Clear behavior, we'll only shift
|
||||
// them if linking is on
|
||||
if (IsSticky())
|
||||
((LabelTrack *)n)->ShiftLabelsOnInsert(msClipLen, t0);
|
||||
|
||||
pastedSomething = ((LabelTrack *)n)->PasteOver(t0, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3405,17 +3389,7 @@ void AudacityProject::OnPaste()
|
|||
((WaveTrack *) n)->Clear(t0, t1);
|
||||
}
|
||||
|
||||
// firstInGroup should always be false here, unless pasting to
|
||||
// the first channel failed
|
||||
if (firstInGroup)
|
||||
{
|
||||
pastedSomething = ((WaveTrack *)n)->Paste(t0, c);
|
||||
firstInGroup = !pastedSomething;
|
||||
}
|
||||
else
|
||||
{
|
||||
pastedSomething = ((WaveTrack *)n)->HandlePaste(t0, c);
|
||||
}
|
||||
pastedSomething = ((WaveTrack *)n)->Paste(t0, c);
|
||||
}
|
||||
else {
|
||||
n->Clear(t0, t1);
|
||||
|
@ -3430,10 +3404,12 @@ void AudacityProject::OnPaste()
|
|||
prev = c;
|
||||
c = clipIter.Next();
|
||||
}
|
||||
} // if (n->GetSelected())
|
||||
else if (n->IsSynchroSelected())
|
||||
{
|
||||
n->SyncAdjust(t1, t0 + msClipLen);
|
||||
}
|
||||
|
||||
if (n && n->GetKind() == Track::Label)
|
||||
firstInGroup = true;
|
||||
n = iter.Next();
|
||||
}
|
||||
|
||||
|
@ -3450,8 +3426,7 @@ void AudacityProject::OnPaste()
|
|||
if (n->GetSelected() && n->GetKind()==Track::Wave){
|
||||
if (c && c->GetKind() == Track::Wave){
|
||||
pastedSomething = ((WaveTrack *)n)->ClearAndPaste(t0, t1,
|
||||
(WaveTrack *)c, true, true, NULL, false, !firstInGroup);
|
||||
firstInGroup = firstInGroup && !pastedSomething;
|
||||
(WaveTrack *)c, true, true);
|
||||
}else{
|
||||
WaveTrack *tmp;
|
||||
tmp = mTrackFactory->NewWaveTrack( ((WaveTrack*)n)->GetSampleFormat(), ((WaveTrack*)n)->GetRate());
|
||||
|
@ -3459,24 +3434,24 @@ void AudacityProject::OnPaste()
|
|||
tmp->Flush();
|
||||
|
||||
pastedSomething = ((WaveTrack *)n)->ClearAndPaste(t0, t1,
|
||||
tmp, true, true, NULL, false, !firstInGroup);
|
||||
firstInGroup = firstInGroup && !pastedSomething;
|
||||
tmp, true, true);
|
||||
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
else if (n->GetSelected() && n->GetKind() == Track::Label)
|
||||
else if (n->GetKind() == Track::Label && n->GetSelected())
|
||||
{
|
||||
// Make room in label tracks as necessary
|
||||
if (IsSticky() && !firstInGroup)
|
||||
{
|
||||
((LabelTrack *)n)->ShiftLabelsOnClear(t0, t1);
|
||||
((LabelTrack *)n)->Clear(t0, t1);
|
||||
|
||||
// As above, only shift labels if linking is on
|
||||
if (IsSticky())
|
||||
((LabelTrack *)n)->ShiftLabelsOnInsert(msClipLen, t0);
|
||||
}
|
||||
}
|
||||
else if (n->IsSynchroSelected())
|
||||
{
|
||||
n->SyncAdjust(t1, t0 + msClipLen);
|
||||
}
|
||||
|
||||
if (n && n->GetKind() == Track::Label)
|
||||
firstInGroup = true;
|
||||
n = iter.Next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3671,18 +3671,20 @@ void AudacityProject::ClearClipboard()
|
|||
|
||||
void AudacityProject::Clear()
|
||||
{
|
||||
TrackAndGroupIterator iter(mTracks);
|
||||
TrackListIterator iter(mTracks);
|
||||
|
||||
Track *n = iter.First();
|
||||
|
||||
while (n) {
|
||||
if (n->GetSelected()) {
|
||||
n->Clear(mViewInfo.sel0, mViewInfo.sel1);
|
||||
// Wave and Label tracks have group behaviour
|
||||
if (IsSticky() && (n->GetKind() == Track::Wave || n->GetKind() == Track::Label)) n = iter.NextGroup();
|
||||
else n = iter.Next();
|
||||
if (n->GetSelected() || n->IsSynchroSelected()) {
|
||||
// AWD: Preserve traditional label track behavior: only shift time in
|
||||
// linked mode
|
||||
if (n->GetKind() == Track::Label && IsSticky())
|
||||
((LabelTrack *)n)->SplitDelete(mViewInfo.sel0, mViewInfo.sel1);
|
||||
else
|
||||
n->Clear(mViewInfo.sel0, mViewInfo.sel1);
|
||||
}
|
||||
else n = iter.Next();
|
||||
n = iter.Next();
|
||||
}
|
||||
|
||||
double seconds = mViewInfo.sel1 - mViewInfo.sel0;
|
||||
|
@ -3981,10 +3983,11 @@ void AudacityProject::GetRegionsByLabel( Regions ®ions )
|
|||
//Executes the edit function on all selected wave tracks with
|
||||
//regions specified by selected labels
|
||||
//If No tracks selected, function is applied on all tracks
|
||||
//If the function deletes audio, groupIteration should probably be set to true,
|
||||
// so it won't delete too many times.
|
||||
//If the function replaces the selection with audio of a different length
|
||||
// syncTracks should be set true to perform the same action on sync-selected
|
||||
// tracks.
|
||||
void AudacityProject::EditByLabel( WaveTrack::EditFunction action,
|
||||
bool groupIteration )
|
||||
bool syncTracks )
|
||||
{
|
||||
Regions regions;
|
||||
|
||||
|
@ -3992,7 +3995,7 @@ void AudacityProject::EditByLabel( WaveTrack::EditFunction action,
|
|||
if( regions.GetCount() == 0 )
|
||||
return;
|
||||
|
||||
TrackAndGroupIterator iter( mTracks );
|
||||
TrackListIterator iter( mTracks );
|
||||
Track *n;
|
||||
bool allTracks = true;
|
||||
|
||||
|
@ -4011,23 +4014,14 @@ void AudacityProject::EditByLabel( WaveTrack::EditFunction action,
|
|||
n = iter.First();
|
||||
while (n)
|
||||
{
|
||||
if( n->GetKind() == Track::Wave && ( allTracks || n->GetSelected() ) )
|
||||
if( n->GetKind() == Track::Wave && ( allTracks || n->GetSelected() ||
|
||||
(syncTracks && n->IsSynchroSelected()) ) )
|
||||
{
|
||||
WaveTrack *wt = ( WaveTrack* )n;
|
||||
for( int i = ( int )regions.GetCount() - 1; i >= 0; i-- )
|
||||
( wt->*action )( regions.Item( i )->start, regions.Item( i )->end );
|
||||
|
||||
// Tracks operated on may need group iteration
|
||||
if (IsSticky() && groupIteration)
|
||||
n = iter.NextGroup();
|
||||
else
|
||||
n = iter.Next();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tracks not operated on need normal iteration
|
||||
n = iter.Next();
|
||||
}
|
||||
n = iter.Next();
|
||||
}
|
||||
|
||||
//delete label regions
|
||||
|
@ -4440,7 +4434,7 @@ bool AudacityProject::GetSnapTo()
|
|||
bool AudacityProject::IsSticky()
|
||||
{
|
||||
#ifdef EXPERIMENTAL_LINKING
|
||||
return (GetStickyFlag() && (mLastFlags & LabelTracksExistFlag));
|
||||
return GetStickyFlag();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
|
|
@ -280,7 +280,7 @@ class AUDACITY_DLL_API AudacityProject: public wxFrame,
|
|||
void Rewind(bool shift);
|
||||
void SkipEnd(bool shift);
|
||||
void SetStop(bool bStopped);
|
||||
void EditByLabel( WaveTrack::EditFunction action, bool groupIteration );
|
||||
void EditByLabel( WaveTrack::EditFunction action, bool syncTracks );
|
||||
void EditClipboardByLabel( WaveTrack::EditDestFunction action );
|
||||
bool IsSticky();
|
||||
bool GetStickyFlag() { return mStickyFlag; };
|
||||
|
|
|
@ -229,6 +229,34 @@ bool Track::IsSynchroSelected()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Track::SyncAdjust(double oldT1, double newT1)
|
||||
{
|
||||
if (newT1 > oldT1) {
|
||||
// Insert space within the track
|
||||
|
||||
if (oldT1 > GetEndTime())
|
||||
return true;
|
||||
|
||||
Track *tmp;
|
||||
bool ret;
|
||||
|
||||
ret = Cut(oldT1, GetEndTime(), &tmp);
|
||||
if (!ret) return false;
|
||||
|
||||
ret = Paste(newT1, tmp);
|
||||
|
||||
delete tmp;
|
||||
return ret;
|
||||
}
|
||||
else if (newT1 < oldT1) {
|
||||
// Remove from the track
|
||||
return Clear(newT1, oldT1);
|
||||
}
|
||||
|
||||
// fall-through: no change
|
||||
return true;
|
||||
}
|
||||
|
||||
// TrackListIterator
|
||||
TrackListIterator::TrackListIterator(TrackList * val)
|
||||
{
|
||||
|
|
|
@ -162,6 +162,10 @@ class AUDACITY_DLL_API Track: public XMLTagHandler
|
|||
virtual bool Clear(double t0, double t1) {return false;}
|
||||
virtual bool Paste(double t, Track * src) {return false;}
|
||||
|
||||
// This can be used to adjust a synchro-selected track when the selection
|
||||
// is replaced by one of a different length.
|
||||
virtual bool SyncAdjust(double oldT1, double newT1);
|
||||
|
||||
virtual bool Silence(double t0, double t1) {return false;}
|
||||
virtual bool InsertSilence(double t, double len) {return false;}
|
||||
|
||||
|
|
|
@ -270,23 +270,14 @@ bool WaveTrack::IsEmpty(double t0, double t1)
|
|||
}
|
||||
|
||||
bool WaveTrack::Cut(double t0, double t1, Track **dest)
|
||||
{
|
||||
return Cut(t0, t1, dest, true);
|
||||
}
|
||||
|
||||
bool WaveTrack::Cut(double t0, double t1, Track **dest, bool groupCut)
|
||||
{
|
||||
if (t1 < t0)
|
||||
return false;
|
||||
|
||||
// Cut is the same as 'Copy', then 'Delete'
|
||||
if (!Copy(t0, t1, dest))
|
||||
return false;
|
||||
|
||||
if (groupCut)
|
||||
return Clear(t0, t1);
|
||||
else
|
||||
return HandleClear(t0, t1, false, false);
|
||||
return Clear(t0, t1);
|
||||
}
|
||||
|
||||
bool WaveTrack::SplitCut(double t0, double t1, Track **dest)
|
||||
|
@ -325,47 +316,44 @@ bool WaveTrack::Trim (double t0, double t1)
|
|||
|
||||
WaveClipList::compatibility_iterator it;
|
||||
for(it = GetClipIterator(); it; it = it->GetNext())
|
||||
{
|
||||
|
||||
WaveClip * clip = it->GetData();
|
||||
{
|
||||
WaveClip * clip = it->GetData();
|
||||
|
||||
//Find the first clip greater than the offset.
|
||||
//If we end up clipping the entire track, this is useful.
|
||||
if(firstGreaterOffset < 0 &&
|
||||
//Find the first clip greater than the offset.
|
||||
//If we end up clipping the entire track, this is useful.
|
||||
if(firstGreaterOffset < 0 &&
|
||||
clip->GetStartTime() >= t0)
|
||||
firstGreaterOffset = clip->GetStartTime();
|
||||
firstGreaterOffset = clip->GetStartTime();
|
||||
|
||||
if(t1 > clip->GetStartTime() && t1 < clip->GetEndTime())
|
||||
{
|
||||
if (!clip->Clear(t1,clip->GetEndTime()))
|
||||
return false;
|
||||
inside1 = true;
|
||||
}
|
||||
|
||||
if(t0 > clip->GetStartTime() && t0 < clip->GetEndTime())
|
||||
{
|
||||
if (!clip->Clear(clip->GetStartTime(),t0))
|
||||
return false;
|
||||
clip->SetOffset(t0);
|
||||
inside0 = true;
|
||||
}
|
||||
if(t1 > clip->GetStartTime() && t1 < clip->GetEndTime())
|
||||
{
|
||||
if (!clip->Clear(t1,clip->GetEndTime()))
|
||||
return false;
|
||||
inside1 = true;
|
||||
}
|
||||
|
||||
if(t0 > clip->GetStartTime() && t0 < clip->GetEndTime())
|
||||
{
|
||||
if (!clip->Clear(clip->GetStartTime(),t0))
|
||||
return false;
|
||||
clip->SetOffset(t0);
|
||||
inside0 = true;
|
||||
}
|
||||
}
|
||||
|
||||
//if inside0 is false, then the left selector was between
|
||||
//clips, so delete everything to its left.
|
||||
if(false == inside1)
|
||||
{
|
||||
if (!Clear(t1,GetEndTime()))
|
||||
return false;
|
||||
}
|
||||
{
|
||||
if (!Clear(t1,GetEndTime()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(false == inside0)
|
||||
{
|
||||
if (!Clear(0,t0))
|
||||
return false;
|
||||
//Reset the track offset to be at the point of the first remaining clip.
|
||||
SetOffset(firstGreaterOffset );
|
||||
}
|
||||
{
|
||||
if (!SplitDelete(0,t0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -462,45 +450,15 @@ bool WaveTrack::Copy(double t0, double t1, Track **dest)
|
|||
|
||||
return true;
|
||||
}
|
||||
bool WaveTrack::Paste(double t0, Track *src)
|
||||
{
|
||||
return Paste(t0, src, NULL, false);
|
||||
}
|
||||
|
||||
bool WaveTrack::Paste(double t0, Track *src, TrackList* tracks, bool relativeLabels)
|
||||
{
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if( p && p->IsSticky() && GetNode() )
|
||||
return HandleGroupPaste(t0, src, tracks, relativeLabels);
|
||||
else
|
||||
return HandlePaste(t0, src);
|
||||
}
|
||||
|
||||
bool WaveTrack::Clear(double t0, double t1)
|
||||
{
|
||||
return Clear(t0, t1, NULL);
|
||||
}
|
||||
|
||||
bool WaveTrack::Clear(double t0, double t1, TrackList* tracks)
|
||||
{
|
||||
bool addCutLines = false;
|
||||
bool split = false;
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if( p && p->IsSticky() && GetNode() )
|
||||
return HandleGroupClear(t0, t1, addCutLines, split, tracks);
|
||||
else
|
||||
return HandleClear(t0, t1, addCutLines, split);
|
||||
return HandleClear(t0, t1, false, false);
|
||||
}
|
||||
|
||||
bool WaveTrack::ClearAndAddCutLine(double t0, double t1)
|
||||
{
|
||||
bool addCutLines = true;
|
||||
bool split = false;
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if( p && p->IsSticky() )
|
||||
return HandleGroupClear(t0, t1, addCutLines, split);
|
||||
else
|
||||
return HandleClear(t0, t1, addCutLines, split);
|
||||
return HandleClear(t0, t1, true, false);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -522,9 +480,6 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
Track *src, // What to paste
|
||||
bool preserve, // Whether to reinsert splits/cuts
|
||||
bool merge, // Whether to remove 'extra' splits
|
||||
TrackList* tracks, // Used in Paste
|
||||
bool relativeLabels, // Whether to handle labels
|
||||
bool useHandlePaste, // Which pasting method
|
||||
TimeWarper *effectWarper // How does time change
|
||||
)
|
||||
{
|
||||
|
@ -537,10 +492,7 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
|
||||
// If duration is 0, then it's just a plain paste
|
||||
if (dur == 0.0) {
|
||||
if (useHandlePaste)
|
||||
return HandlePaste(t0, src);
|
||||
else
|
||||
return Paste(t0, src, tracks, relativeLabels);
|
||||
return Paste(t0, src);
|
||||
}
|
||||
|
||||
// If provided time warper was NULL, use a default one that does nothing
|
||||
|
@ -601,15 +553,8 @@ bool WaveTrack::ClearAndPaste(double t0, // Start of time to clear
|
|||
// Now, clear the selection
|
||||
if (HandleClear(t0, t1, false, false)) {
|
||||
|
||||
// The pasting method depends on how this method was called
|
||||
bool pasteResult;
|
||||
if (useHandlePaste)
|
||||
pasteResult = HandlePaste(t0, src);
|
||||
else
|
||||
pasteResult = Paste(t0, src, tracks, relativeLabels);
|
||||
|
||||
// And paste in the new data
|
||||
if (pasteResult) {
|
||||
if (Paste(t0, src)) {
|
||||
unsigned int i;
|
||||
|
||||
// First, merge the new clip(s) in with the existing clips
|
||||
|
@ -722,36 +667,6 @@ void WaveTrack::AddClip(WaveClip* clip)
|
|||
mClips.Append(clip);
|
||||
}
|
||||
|
||||
bool WaveTrack::HandleGroupClear(double t0, double t1, bool addCutLines, bool split, TrackList* tracks)
|
||||
{
|
||||
// get tracks
|
||||
AudacityProject *p = GetActiveProject();
|
||||
|
||||
if (p) {
|
||||
if (!tracks) tracks = p->GetTracks();
|
||||
}
|
||||
else return false;
|
||||
|
||||
TrackGroupIterator it(tracks);
|
||||
Track *t = it.First(this);
|
||||
if (t == NULL)
|
||||
// the present track is in a project with groups but doesn't belong to any of them
|
||||
return HandleClear(t0, t1, addCutLines, split);
|
||||
|
||||
for( ; t; t = it.Next() ) {
|
||||
if (t->GetKind() == Track::Wave) {
|
||||
if ( !( ( (WaveTrack *) t)->HandleClear(t0, t1, addCutLines, split) ) )
|
||||
return false;
|
||||
}
|
||||
else if (t->GetKind() == Track::Label) {
|
||||
if (!split)
|
||||
( (LabelTrack *)t )->ShiftLabelsOnClear(t0, t1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaveTrack::HandleClear(double t0, double t1,
|
||||
bool addCutLines, bool split)
|
||||
{
|
||||
|
@ -878,102 +793,57 @@ bool WaveTrack::HandleClear(double t0, double t1,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WaveTrack::HandleGroupPaste(double t0, Track *src, TrackList* tracks, bool relativeLabels)
|
||||
bool WaveTrack::SyncAdjust(double oldT1, double newT1)
|
||||
{
|
||||
// get tracks
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (newT1 > oldT1) {
|
||||
// Insert space within the track
|
||||
|
||||
if (p) {
|
||||
if (!tracks) tracks = p->GetTracks();
|
||||
}
|
||||
else return false;
|
||||
|
||||
double length = src->GetEndTime();
|
||||
ViewInfo *info = &p->mViewInfo;
|
||||
double sel_len = max(info->sel1 - max(info->sel0, t0), 0.0);
|
||||
|
||||
TrackGroupIterator it(tracks);
|
||||
Track *t = it.First(this);
|
||||
if (t == NULL)
|
||||
// the present track is in a project with groups but doesn't belong to any of them
|
||||
return HandlePaste(t0, src);
|
||||
if (oldT1 > GetEndTime())
|
||||
return true;
|
||||
|
||||
// False return from this function causes its changes to not be pushed to
|
||||
// the undo stack. So we paste into this track first, so any failure
|
||||
// (usually from "clips can't move" mode) comes before other changes.
|
||||
// Failures to paste to the group tracks should not cause this function to
|
||||
// return false; the result might be OK with the user, and if not he can
|
||||
// easily undo it
|
||||
if (!HandlePaste(t0, src))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// If track is empty at oldT1 insert whitespace; otherwise, silence
|
||||
if (IsEmpty(oldT1, oldT1))
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
for( ; t; t = it.Next() ) {
|
||||
if (t->GetKind() == Track::Wave) {
|
||||
WaveTrack *wt = (WaveTrack *)t;
|
||||
if (t==this) {
|
||||
// This track has already been pasted; if it's a stereo track skip
|
||||
// over the other channel as well.
|
||||
if (t->GetLinked()) t=it.Next();
|
||||
}
|
||||
else {
|
||||
if (! (t->GetSelected()) ) {
|
||||
if ( sel_len > length )
|
||||
// if selection is bigger than the content to add then we
|
||||
// need to clear the extra length in the group tracks
|
||||
wt->HandleClear(t0+length, t0+sel_len, false, false);
|
||||
else if (sel_len < length) {
|
||||
// if selection is smaller than the content to add then we
|
||||
// need to add extra space in the group tracks. If the track
|
||||
// is empty at this point insert whitespace; otherwise,
|
||||
// silence
|
||||
if (wt->IsEmpty(t0+sel_len, t0+sel_len))
|
||||
{
|
||||
// Have to check if clips can move in this case
|
||||
bool clipsCanMove = true;
|
||||
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &clipsCanMove);
|
||||
if (clipsCanMove)
|
||||
{
|
||||
Track *tmp = NULL;
|
||||
wt->Cut(t0 + sel_len,
|
||||
wt->GetEndTime()+1.0/wt->GetRate(), &tmp, false);
|
||||
wt->HandlePaste(t0 + length, tmp);
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackFactory *factory = p->GetTrackFactory();
|
||||
WaveTrack *tmp = factory->NewWaveTrack( wt->GetSampleFormat(), wt->GetRate());
|
||||
tmp->InsertSilence(0.0, length-sel_len);
|
||||
tmp->Flush();
|
||||
wt->HandlePaste(t0+sel_len, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if clips can move
|
||||
bool clipsCanMove = true;
|
||||
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &clipsCanMove);
|
||||
if (clipsCanMove) {
|
||||
Track *tmp = NULL;
|
||||
ret = Cut (oldT1, GetEndTime() + 1.0/GetRate(), &tmp);
|
||||
if (!ret) return false;
|
||||
|
||||
ret = Paste(newT1, tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
else if (t->GetKind() == Track::Label) {
|
||||
LabelTrack *lt = (LabelTrack *)t;
|
||||
if (!t->GetSelected())
|
||||
{
|
||||
if (relativeLabels && (sel_len != 0.0))
|
||||
lt->ScaleLabels(info->sel0, info->sel1, length/sel_len);
|
||||
else {
|
||||
if ((length - sel_len) > 0.0)
|
||||
lt->ShiftLabelsOnInsert(length-sel_len, t0);
|
||||
else if ((length - sel_len) < 0.0)
|
||||
lt->ShiftLabelsOnClear(info->sel0+length, info->sel1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// AWD: Could just use InsertSilence() on its own here, but it doesn't
|
||||
// follow EditClipCanMove rules (Paste() does it right)
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if (!p) return false;
|
||||
TrackFactory *f = p->GetTrackFactory();
|
||||
if (!f) return false;
|
||||
WaveTrack *tmp = f->NewWaveTrack(GetSampleFormat(), GetRate());
|
||||
|
||||
tmp->InsertSilence(0.0, newT1 - oldT1);
|
||||
tmp->Flush();
|
||||
Paste(oldT1, tmp);
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
else if (newT1 < oldT1) {
|
||||
return Clear(newT1, oldT1);
|
||||
}
|
||||
|
||||
// fall-through: no change
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WaveTrack::HandlePaste(double t0, Track *src)
|
||||
bool WaveTrack::Paste(double t0, Track *src)
|
||||
{
|
||||
bool editClipCanMove = true;
|
||||
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
|
||||
|
@ -1032,8 +902,8 @@ bool WaveTrack::HandlePaste(double t0, Track *src)
|
|||
// move everything to the right, then try to paste again
|
||||
if (!IsEmpty(t0, GetEndTime())) {
|
||||
Track *tmp = NULL;
|
||||
Cut(t0, GetEndTime()+1.0/mRate, &tmp, false);
|
||||
HandlePaste(t0 + insertDuration, tmp);
|
||||
Cut(t0, GetEndTime()+1.0/mRate, &tmp);
|
||||
Paste(t0 + insertDuration, tmp);
|
||||
delete tmp;
|
||||
}
|
||||
} else
|
||||
|
@ -1197,11 +1067,13 @@ bool WaveTrack::InsertSilence(double t, double len)
|
|||
for (WaveClipList::compatibility_iterator it=GetClipIterator(); it; it=it->GetNext())
|
||||
{
|
||||
WaveClip *clip = it->GetData();
|
||||
if (clip->GetStartTime() > t)
|
||||
if (clip->BeforeClip(t))
|
||||
clip->Offset(len);
|
||||
else if (clip->GetEndTime() > t)
|
||||
else if (clip->WithinClip(t))
|
||||
{
|
||||
return clip->InsertSilence(t, len);
|
||||
if (!clip->InsertSilence(t, len)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -133,9 +133,6 @@ class AUDACITY_DLL_API WaveTrack: public Track {
|
|||
Track *src,
|
||||
bool preserve = true,
|
||||
bool merge = true,
|
||||
TrackList* tracks = NULL,
|
||||
bool relativeLabels = false,
|
||||
bool useHandlePaste = false,
|
||||
TimeWarper *effectWarper = NULL);
|
||||
|
||||
virtual bool Silence(double t0, double t1);
|
||||
|
@ -156,15 +153,9 @@ class AUDACITY_DLL_API WaveTrack: public Track {
|
|||
|
||||
virtual bool Trim (double t0, double t1);
|
||||
|
||||
bool Clear(double t0, double t1, TrackList* tracks);
|
||||
bool HandleGroupClear(double t0, double t1, bool addCutLines, bool split, TrackList* tracks = NULL);
|
||||
bool HandleClear(double t0, double t1, bool addCutLines, bool split);
|
||||
|
||||
bool Paste(double t0, Track *src, TrackList* tracks, bool relativeLabels = false);
|
||||
bool HandleGroupPaste(double t0, Track *src, TrackList* tracks, bool relativeLabels);
|
||||
bool HandlePaste(double t0, Track *src);
|
||||
|
||||
bool Cut(double t0, double t1, Track **dest, bool groupCut);
|
||||
virtual bool SyncAdjust(double oldT1, double newT1);
|
||||
|
||||
// Returns true if there are no WaveClips in that region
|
||||
bool IsEmpty(double t0, double t1);
|
||||
|
|
|
@ -89,9 +89,9 @@ bool EffectChangeSpeed::TransferParameters( Shuttle & shuttle )
|
|||
// the region are shifted along according to how the region size changed.
|
||||
bool EffectChangeSpeed::ProcessLabelTrack(Track *t)
|
||||
{
|
||||
SetTimeWarper(new RegionTimeWarper(mCurT0, mCurT1,
|
||||
new LinearTimeWarper(mCurT0, mCurT0,
|
||||
mCurT1, mCurT0 + (mCurT1-mCurT0)*mFactor)));
|
||||
SetTimeWarper(new RegionTimeWarper(mT0, mT1,
|
||||
new LinearTimeWarper(mT0, mT0,
|
||||
mT1, mT0 + (mT1-mT0)*mFactor)));
|
||||
LabelTrack *lt = (LabelTrack*)t;
|
||||
if (lt == NULL) return false;
|
||||
lt->WarpLabels(*GetTimeWarper());
|
||||
|
@ -108,42 +108,28 @@ bool EffectChangeSpeed::Process()
|
|||
bool bGoodResult = true;
|
||||
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
// go to first wavetrack
|
||||
Track* t;
|
||||
for (t = iter.First(); t->GetKind() != Track::Wave; t = iter.Next());
|
||||
if (!t)
|
||||
return false;
|
||||
WaveTrack* pOutWaveTrack = (WaveTrack*)t;
|
||||
mCurTrackNum = 0;
|
||||
m_maxNewLength = 0.0;
|
||||
|
||||
mFactor = 100.0 / (100.0 + m_PercentChange);
|
||||
|
||||
//Get start and end times from track
|
||||
mCurT0 = pOutWaveTrack->GetStartTime();
|
||||
mCurT1 = pOutWaveTrack->GetEndTime();
|
||||
|
||||
//Set the current bounds to whichever left marker is
|
||||
//greater and whichever right marker is less:
|
||||
mCurT0 = wxMax(mT0, mCurT0);
|
||||
mCurT1 = wxMin(mT1, mCurT1);
|
||||
|
||||
// we only do a "group change" in the first selected track of the group.
|
||||
// ClearAndPaste has a call to Paste that does changes to the group tracks
|
||||
bool first = true;
|
||||
|
||||
t = iter.First();
|
||||
while (t != NULL)
|
||||
{
|
||||
if (t->GetKind() == Track::Label) {
|
||||
first = true;
|
||||
if (t->GetSelected() && !ProcessLabelTrack(t))
|
||||
if (t->GetSelected() || t->IsSynchroSelected())
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
if (!ProcessLabelTrack(t)) {
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->GetKind() == Track::Wave && t->GetSelected()) {
|
||||
pOutWaveTrack = (WaveTrack*)t;
|
||||
else if (t->GetKind() == Track::Wave &&
|
||||
(t->GetSelected() || t->IsSynchroSelected()))
|
||||
{
|
||||
WaveTrack *pOutWaveTrack = (WaveTrack*)t;
|
||||
//Get start and end times from track
|
||||
mCurT0 = pOutWaveTrack->GetStartTime();
|
||||
mCurT1 = pOutWaveTrack->GetEndTime();
|
||||
|
@ -160,15 +146,18 @@ bool EffectChangeSpeed::Process()
|
|||
sampleCount end = pOutWaveTrack->TimeToLongSamples(mCurT1);
|
||||
|
||||
//ProcessOne() (implemented below) processes a single track
|
||||
if (!ProcessOne(pOutWaveTrack, start, end, first))
|
||||
if (!ProcessOne(pOutWaveTrack, start, end))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
mCurTrackNum++;
|
||||
}
|
||||
else if (t->IsSynchroSelected() && !t->GetSelected())
|
||||
{
|
||||
t->SyncAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
|
||||
}
|
||||
|
||||
//Iterate to the next track
|
||||
t=iter.Next();
|
||||
|
@ -185,7 +174,7 @@ bool EffectChangeSpeed::Process()
|
|||
// ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
||||
// and calls libsamplerate code on these blocks.
|
||||
bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
||||
sampleCount start, sampleCount end, bool first)
|
||||
sampleCount start, sampleCount end)
|
||||
{
|
||||
if (track == NULL)
|
||||
return false;
|
||||
|
@ -268,8 +257,10 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
|
|||
// sample data
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
if (bLoopSuccess) {
|
||||
SetTimeWarper(new LinearTimeWarper(mCurT0, mCurT0, mCurT1, mCurT0 + newLength ));
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack, true, false, mOutputTracks, true, first, GetTimeWarper());
|
||||
SetTimeWarper(new LinearTimeWarper(
|
||||
mCurT0, mCurT0, mCurT1, mCurT0 + newLength ));
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack, true, false,
|
||||
GetTimeWarper());
|
||||
}
|
||||
|
||||
if (newLength > m_maxNewLength)
|
||||
|
|
|
@ -57,13 +57,13 @@ class EffectChangeSpeed : public Effect {
|
|||
virtual bool Process();
|
||||
|
||||
private:
|
||||
bool ProcessOne(WaveTrack * t, sampleCount start, sampleCount end, bool first);
|
||||
bool ProcessOne(WaveTrack * t, sampleCount start, sampleCount end);
|
||||
bool ProcessLabelTrack(Track *t);
|
||||
|
||||
private:
|
||||
// track related
|
||||
int mCurTrackNum;
|
||||
double m_maxNewLength;
|
||||
double m_maxNewLength;
|
||||
double mCurT0;
|
||||
double mCurT1;
|
||||
|
||||
|
|
|
@ -247,31 +247,12 @@ void Effect::CopyInputTracks(int trackType)
|
|||
TrackListOfKindIterator aIt(trackType, mTracks);
|
||||
t2bHash added;
|
||||
|
||||
//for each track that is selected
|
||||
for (Track *aTrack = aIt.First(); aTrack; aTrack = aIt.Next()) {
|
||||
if (!aTrack->GetSelected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TrackGroupIterator gIt(mTracks);
|
||||
Track *gTrack = gIt.First(aTrack);
|
||||
|
||||
//if the track is part of a group
|
||||
if (trackType == Track::All && gTrack != NULL) {
|
||||
//go to the project tracks and add all the tracks in the same group
|
||||
for( ; gTrack; gTrack = gIt.Next() ) {
|
||||
// only add if the track was not added before
|
||||
if (added.find(gTrack) == added.end()) {
|
||||
added[gTrack]=true;
|
||||
Track *o = gTrack->Duplicate();
|
||||
mOutputTracks->Add(o);
|
||||
mIMap.Add(gTrack);
|
||||
mOMap.Add(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
//otherwise just add the track
|
||||
else {
|
||||
// Include selected tracks, plus sync-selected tracks for Track::All)
|
||||
if (aTrack->GetSelected() ||
|
||||
(trackType == Track::All && aTrack->IsSynchroSelected()))
|
||||
{
|
||||
Track *o = aTrack->Duplicate();
|
||||
mOutputTracks->Add(o);
|
||||
mIMap.Add(aTrack);
|
||||
|
|
|
@ -26,8 +26,7 @@ bool Generator::Process()
|
|||
|
||||
BeforeGenerate();
|
||||
|
||||
// Set up mOutputTracks. This effect needs Track::All because it uses ClearAndPaste
|
||||
// that need to have label tracks.
|
||||
// Set up mOutputTracks. This effect needs Track::All for grouping
|
||||
this->CopyInputTracks(Track::All);
|
||||
|
||||
// Iterate over the tracks
|
||||
|
@ -36,15 +35,9 @@ bool Generator::Process()
|
|||
TrackListIterator iter(mOutputTracks);
|
||||
Track* t = iter.First();
|
||||
|
||||
// we only do a "group change" in the first selected track of the group.
|
||||
// ClearAndPaste has a call to Paste that does changes to the group tracks
|
||||
bool first = true;
|
||||
|
||||
while (t != NULL)
|
||||
{
|
||||
if (t->GetKind() == Track::Label)
|
||||
first = true;
|
||||
else if (t->GetKind() == Track::Wave && t->GetSelected()) {
|
||||
if (t->GetKind() == Track::Wave && t->GetSelected()) {
|
||||
WaveTrack* track = (WaveTrack*)t;
|
||||
|
||||
bool editClipCanMove;
|
||||
|
@ -76,11 +69,7 @@ bool Generator::Process()
|
|||
tmp->Flush();
|
||||
SetTimeWarper(new StepTimeWarper(mT1, mDuration-mT1));
|
||||
bGoodResult = track->ClearAndPaste(mT0, mT1, tmp, true,
|
||||
false, mOutputTracks,
|
||||
false, !first, GetTimeWarper());
|
||||
if (first) {
|
||||
first = false;
|
||||
}
|
||||
false, GetTimeWarper());
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
|
@ -98,6 +87,9 @@ bool Generator::Process()
|
|||
|
||||
ntrack++;
|
||||
}
|
||||
else if (t->IsSynchroSelected()) {
|
||||
t->SyncAdjust(mT1, mT0 + mDuration);
|
||||
}
|
||||
// Move on to the next track
|
||||
t = iter.Next();
|
||||
}
|
||||
|
|
|
@ -110,44 +110,28 @@ bool EffectRepeat::TransferParameters( Shuttle & shuttle )
|
|||
|
||||
bool EffectRepeat::Process()
|
||||
{
|
||||
// Set up mOutputTracks. This effect needs Track::All because it uses Paste that needs to have label tracks.
|
||||
// Set up mOutputTracks. This effect needs Track::All for grouping
|
||||
this->CopyInputTracks(Track::All);
|
||||
|
||||
int nTrack = 0;
|
||||
bool bGoodResult = true;
|
||||
double maxDestLen = 0.0; // used to change selection to generated bit
|
||||
|
||||
// Is linking enabled?
|
||||
AudacityProject *p = GetActiveProject();
|
||||
bool isSticky = ( p && p->IsSticky());
|
||||
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
|
||||
// we only do a "group change" in the first selected track of the group.
|
||||
// Paste call does changes to the group tracks
|
||||
bool first = true;
|
||||
|
||||
for (Track *t = iter.First(); t && bGoodResult; t = iter.Next()) {
|
||||
if (t->GetKind() == Track::Label)
|
||||
{
|
||||
// We repeat labels if linking is enabled and a WaveTrack before this
|
||||
// has been repeated, or if the label track is selected
|
||||
if (t->GetSelected() || (isSticky && !first))
|
||||
if (t->GetSelected() || t->IsSynchroSelected())
|
||||
{
|
||||
LabelTrack* track = (LabelTrack*)t;
|
||||
|
||||
// If this track isn't selected, ShiftLabelsOnInsert() has
|
||||
// already been called
|
||||
if (t->GetSelected())
|
||||
track->ShiftLabelsOnInsert((mT1 - mT0) * repeatCount, mT1);
|
||||
|
||||
if (!track->Repeat(mT0, mT1, repeatCount))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
first = true;
|
||||
}
|
||||
else if (t->GetKind() == Track::Wave && t->GetSelected())
|
||||
{
|
||||
|
@ -166,30 +150,23 @@ bool EffectRepeat::Process()
|
|||
track->Copy(mT0, mT1, &dest);
|
||||
for(int j=0; j<repeatCount; j++)
|
||||
{
|
||||
if (first) {
|
||||
if (!track->Paste(tc, dest, mOutputTracks) ||
|
||||
TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!track->HandlePaste(tc, dest) ||
|
||||
TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
if (!track->Paste(tc, dest) ||
|
||||
TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
tc += tLen;
|
||||
}
|
||||
first = false;
|
||||
if (tc > maxDestLen)
|
||||
maxDestLen = tc;
|
||||
delete dest;
|
||||
nTrack++;
|
||||
}
|
||||
else if (t->IsSynchroSelected())
|
||||
{
|
||||
t->SyncAdjust(mT1, mT1 + (mT1 - mT0) * repeatCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (bGoodResult)
|
||||
|
|
|
@ -36,41 +36,33 @@ bool EffectReverse::Process()
|
|||
//Track::All is needed because Reverse should move the labels too
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
bool bGoodResult = true;
|
||||
Track *lastGroup = NULL; // First track of group of last acted-on WaveTrack
|
||||
TrackGroupIterator gIt(mOutputTracks);
|
||||
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
Track *t = iter.First();
|
||||
int count = 0;
|
||||
while (t) {
|
||||
if (t->GetKind() == Track::Wave) {
|
||||
if (t->GetKind() == Track::Wave &&
|
||||
(t->GetSelected() || t->IsSynchroSelected()))
|
||||
{
|
||||
WaveTrack *track = (WaveTrack*)t;
|
||||
|
||||
if (track->GetSelected()) {
|
||||
if (mT1 > mT0) {
|
||||
sampleCount start = track->TimeToLongSamples(mT0);
|
||||
sampleCount end = track->TimeToLongSamples(mT1);
|
||||
sampleCount len = (sampleCount)(end - start);
|
||||
|
||||
if (!ProcessOneWave(count, track, start, len))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
if (mT1 > mT0) {
|
||||
sampleCount start = track->TimeToLongSamples(mT0);
|
||||
sampleCount end = track->TimeToLongSamples(mT1);
|
||||
sampleCount len = (sampleCount)(end - start);
|
||||
|
||||
if (!ProcessOneWave(count, track, start, len))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Update grouping variables
|
||||
lastGroup = gIt.First(t);
|
||||
}
|
||||
}
|
||||
else if (t->GetKind() == Track::Label) {
|
||||
AudacityProject *p = GetActiveProject();
|
||||
if ((p && p->IsSticky() && gIt.First(t) == lastGroup) ||
|
||||
t->GetSelected())
|
||||
{
|
||||
LabelTrack *track = (LabelTrack*)t;
|
||||
track->ChangeLabelsOnReverse(mT0, mT1);
|
||||
}
|
||||
else if (t->GetKind() == Track::Label &&
|
||||
(t->GetSelected() || t->IsSynchroSelected()))
|
||||
{
|
||||
LabelTrack *track = (LabelTrack*)t;
|
||||
track->ChangeLabelsOnReverse(mT0, mT1);
|
||||
}
|
||||
t = iter.Next();
|
||||
count++;
|
||||
|
|
|
@ -156,14 +156,14 @@ bool EffectSBSMS::ProcessLabelTrack(Track *t)
|
|||
TimeWarper *warper = NULL;
|
||||
if (rateStart == rateEnd)
|
||||
{
|
||||
warper = new LinearTimeWarper(mCurT0, mCurT0,
|
||||
mCurT1, mCurT0+(mCurT1-mCurT0)*mTotalStretch);
|
||||
warper = new LinearTimeWarper(mT0, mT0,
|
||||
mT1, mT0+(mT1-mT0)*mTotalStretch);
|
||||
} else
|
||||
{
|
||||
warper = new LogarithmicTimeWarper(mCurT0, mCurT1,
|
||||
warper = new LogarithmicTimeWarper(mT0, mT1,
|
||||
rateStart, rateEnd);
|
||||
}
|
||||
SetTimeWarper(new RegionTimeWarper(mCurT0, mCurT1, warper));
|
||||
SetTimeWarper(new RegionTimeWarper(mT0, mT1, warper));
|
||||
LabelTrack *lt = (LabelTrack*)t;
|
||||
if (lt == NULL) return false;
|
||||
lt->WarpLabels(*GetTimeWarper());
|
||||
|
@ -183,11 +183,7 @@ bool EffectSBSMS::Process()
|
|||
//Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
// go to first wavetrack
|
||||
Track* t;
|
||||
for (t = iter.First(); t->GetKind() != Track::Wave; t = iter.Next());
|
||||
if (!t)
|
||||
return false;
|
||||
mCurTrackNum = 0;
|
||||
|
||||
double maxDuration = 0.0;
|
||||
|
@ -197,21 +193,25 @@ bool EffectSBSMS::Process()
|
|||
else
|
||||
mTotalStretch = 1.0/(rateEnd-rateStart)*log(rateEnd/rateStart);
|
||||
|
||||
// Must sync if selection length will change
|
||||
bool mustSync = (mTotalStretch != 1.0);
|
||||
|
||||
// we only do a "group change" in the first selected track of the group.
|
||||
// ClearAndPaste has a call to Paste that does changes to the group tracks
|
||||
bool first = true;
|
||||
|
||||
t = iter.First();
|
||||
while (t != NULL) {
|
||||
if (t->GetKind() == Track::Label) {
|
||||
first = true;
|
||||
if (t->GetSelected() && !ProcessLabelTrack(t))
|
||||
if (t->GetKind() == Track::Label &&
|
||||
(t->GetSelected() || (mustSync && t->IsSynchroSelected())) )
|
||||
{
|
||||
if (t->GetSelected() || t->IsSynchroSelected())
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
if (!ProcessLabelTrack(t)) {
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t->GetKind() == Track::Wave && t->GetSelected()) {
|
||||
else if (t->GetKind() == Track::Wave &&
|
||||
(t->GetSelected() || (mustSync && t->IsSynchroSelected())) )
|
||||
{
|
||||
WaveTrack* leftTrack = (WaveTrack*)t;
|
||||
|
||||
//Get start and end times from track
|
||||
|
@ -396,16 +396,20 @@ bool EffectSBSMS::Process()
|
|||
if(rightTrack)
|
||||
rb.outputRightTrack->Flush();
|
||||
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack, true, false, NULL, true, first, GetTimeWarper());
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack,
|
||||
true, false, GetTimeWarper());
|
||||
|
||||
if(rightTrack) {
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack, true, false, NULL, true, false, GetTimeWarper());
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack,
|
||||
true, false, GetTimeWarper());
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
mCurTrackNum++;
|
||||
}
|
||||
else if (mustSync && t->IsSynchroSelected())
|
||||
{
|
||||
t->SyncAdjust(mCurT1, mCurT0 + (mCurT1 - mCurT0) * mTotalStretch);
|
||||
}
|
||||
//Iterate to the next track
|
||||
t = iter.Next();
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ effect that uses SoundTouch to do its processing (ChangeTempo
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#include "SoundTouchEffect.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../Project.h"
|
||||
#include "SoundTouchEffect.h"
|
||||
#include "TimeWarper.h"
|
||||
|
||||
bool EffectSoundTouch::ProcessLabelTrack(Track *track)
|
||||
|
@ -37,37 +37,40 @@ bool EffectSoundTouch::ProcessLabelTrack(Track *track)
|
|||
bool EffectSoundTouch::Process()
|
||||
{
|
||||
// Assumes that mSoundTouch has already been initialized
|
||||
// by the subclass for subclass-specific parameters.
|
||||
// by the subclass for subclass-specific parameters. The
|
||||
// time warper should also be set.
|
||||
|
||||
// Check if this effect will alter the selection length; if so, we need
|
||||
// to operate on sync-selected tracks
|
||||
bool mustSync = true;
|
||||
if (mT1 == GetTimeWarper()->Warp(mT1)) {
|
||||
mustSync = false;
|
||||
}
|
||||
|
||||
//Iterate over each track
|
||||
//Track::All is needed because this effect needs to introduce silence in the group tracks to keep sync
|
||||
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
|
||||
//Track::All is needed for group behavior
|
||||
this->CopyInputTracks(Track::All);
|
||||
bool bGoodResult = true;
|
||||
|
||||
TrackListIterator iter(mOutputTracks);
|
||||
// go to first wavetrack
|
||||
Track* t;
|
||||
for (t = iter.First(); t->GetKind() != Track::Wave; t = iter.Next());
|
||||
if (!t)
|
||||
return false;
|
||||
WaveTrack* leftTrack = (WaveTrack*)t;
|
||||
mCurTrackNum = 0;
|
||||
m_maxNewLength = 0.0;
|
||||
|
||||
// we only do a "group change" in the first selected track of the group.
|
||||
// ClearAndPaste has a call to Paste that does changes to the group tracks
|
||||
bool first = true;
|
||||
m_maxNewLength = 0.0;
|
||||
|
||||
t = iter.First();
|
||||
while (t != NULL) {
|
||||
if (t->GetKind() == Track::Label) {
|
||||
first = true;
|
||||
if (t->GetSelected() && !ProcessLabelTrack(t))
|
||||
if (t->GetKind() == Track::Label &&
|
||||
(t->GetSelected() || (mustSync && t->IsSynchroSelected())) )
|
||||
{
|
||||
if (!ProcessLabelTrack(t))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (t->GetKind() == Track::Wave && t->GetSelected()) {
|
||||
else if (t->GetKind() == Track::Wave &&
|
||||
(t->GetSelected() || (mustSync && t->IsSynchroSelected())) )
|
||||
{
|
||||
WaveTrack* leftTrack = (WaveTrack*)t;
|
||||
//Get start and end times from track
|
||||
mCurT0 = leftTrack->GetStartTime();
|
||||
|
@ -102,7 +105,7 @@ bool EffectSoundTouch::Process()
|
|||
mSoundTouch->setChannels(2);
|
||||
|
||||
//ProcessStereo() (implemented below) processes a stereo track
|
||||
if (!ProcessStereo(leftTrack, rightTrack, start, end, first))
|
||||
if (!ProcessStereo(leftTrack, rightTrack, start, end))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
|
@ -117,16 +120,19 @@ bool EffectSoundTouch::Process()
|
|||
mSoundTouch->setChannels(1);
|
||||
|
||||
//ProcessOne() (implemented below) processes a single track
|
||||
if (!ProcessOne(leftTrack, start, end, first))
|
||||
if (!ProcessOne(leftTrack, start, end))
|
||||
{
|
||||
bGoodResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
mCurTrackNum++;
|
||||
}
|
||||
else if (mustSync && t->IsSynchroSelected()) {
|
||||
t->SyncAdjust(mT1, GetTimeWarper()->Warp(mT1));
|
||||
}
|
||||
|
||||
//Iterate to the next track
|
||||
t = iter.Next();
|
||||
}
|
||||
|
@ -146,7 +152,7 @@ bool EffectSoundTouch::Process()
|
|||
//ProcessOne() takes a track, transforms it to bunch of buffer-blocks,
|
||||
//and executes ProcessSoundTouch on these blocks
|
||||
bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
||||
sampleCount start, sampleCount end, bool first)
|
||||
sampleCount start, sampleCount end)
|
||||
{
|
||||
WaveTrack *outputTrack;
|
||||
sampleCount s;
|
||||
|
@ -217,7 +223,7 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
|||
|
||||
// Take the output track and insert it in place of the original
|
||||
// sample data
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack, true, false, NULL, true, first, GetTimeWarper());
|
||||
track->ClearAndPaste(mCurT0, mCurT1, outputTrack, true, false, GetTimeWarper());
|
||||
|
||||
double newLength = outputTrack->GetEndTime();
|
||||
m_maxNewLength = wxMax(m_maxNewLength, newLength);
|
||||
|
@ -230,7 +236,7 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
|
|||
}
|
||||
|
||||
bool EffectSoundTouch::ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end, bool first)
|
||||
sampleCount start, sampleCount end)
|
||||
{
|
||||
mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate()+0.5));
|
||||
|
||||
|
@ -321,8 +327,8 @@ bool EffectSoundTouch::ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack
|
|||
|
||||
// Take the output tracks and insert in place of the original
|
||||
// sample data.
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, outputLeftTrack, true, false, NULL, true, first, GetTimeWarper());
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, outputRightTrack, true, false, NULL, true, false, GetTimeWarper());
|
||||
leftTrack->ClearAndPaste(mCurT0, mCurT1, outputLeftTrack, true, false, GetTimeWarper());
|
||||
rightTrack->ClearAndPaste(mCurT0, mCurT1, outputRightTrack, true, false, GetTimeWarper());
|
||||
|
||||
// Track the longest result length
|
||||
double newLength = outputLeftTrack->GetEndTime();
|
||||
|
|
|
@ -44,17 +44,16 @@ class EffectSoundTouch:public Effect {
|
|||
|
||||
private:
|
||||
bool ProcessLabelTrack(Track *track);
|
||||
bool ProcessOne(WaveTrack * t,
|
||||
sampleCount start, sampleCount end, bool first);
|
||||
bool ProcessOne(WaveTrack * t, sampleCount start, sampleCount end);
|
||||
bool ProcessStereo(WaveTrack* leftTrack, WaveTrack* rightTrack,
|
||||
sampleCount start, sampleCount end, bool first);
|
||||
sampleCount start, sampleCount end);
|
||||
bool ProcessStereoResults(const unsigned int outputCount,
|
||||
WaveTrack* outputLeftTrack,
|
||||
WaveTrack* outputRightTrack);
|
||||
|
||||
int mCurTrackNum;
|
||||
|
||||
double m_maxNewLength;
|
||||
double m_maxNewLength;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -96,7 +96,7 @@ bool EffectStereoToMono::ProcessOne(int count)
|
|||
double minStart = wxMin(mLeftTrack->GetStartTime(), mRightTrack->GetStartTime());
|
||||
mLeftTrack->Clear(mLeftTrack->GetStartTime(), mLeftTrack->GetEndTime());
|
||||
mOutTrack->Flush();
|
||||
mLeftTrack->HandlePaste(minStart, mOutTrack);
|
||||
mLeftTrack->Paste(minStart, mOutTrack);
|
||||
mLeftTrack->SetLinked(false);
|
||||
mRightTrack->SetLinked(false);
|
||||
mLeftTrack->SetChannel(Track::MonoChannel);
|
||||
|
|
|
@ -421,13 +421,10 @@ bool EffectTruncSilence::Process()
|
|||
// Remove stale data at end of output tracks.
|
||||
if (!cancelled && (outTrackOffset < end)) {
|
||||
t = (WaveTrack *) iterOut.First();
|
||||
if( p->IsSticky() )
|
||||
t->Clear(outTrackOffset / rate, t1, mOutputTracks);
|
||||
else
|
||||
while(t) {
|
||||
t->Clear(outTrackOffset / rate, t1, mOutputTracks);
|
||||
t = (WaveTrack *) iterOut.Next();
|
||||
}
|
||||
while(t) {
|
||||
t->Clear(outTrackOffset / rate, t1);
|
||||
t = (WaveTrack *) iterOut.Next();
|
||||
}
|
||||
|
||||
t1 = outTrackOffset / rate;
|
||||
}
|
||||
|
|
|
@ -508,6 +508,8 @@ bool EffectNyquist::Process()
|
|||
mDebugOutput = "";
|
||||
|
||||
// Keep track of whether the current track is first selected in its group
|
||||
// (we have no idea what the length of the returned audio will be, so we have
|
||||
// to handle group behavior the "old" way).
|
||||
mFirstInGroup = true;
|
||||
Track *gtLast = NULL;
|
||||
|
||||
|
@ -775,9 +777,19 @@ bool EffectNyquist::ProcessOne()
|
|||
out = mOutputTrack[0];
|
||||
}
|
||||
|
||||
// If this track is not first in its group we set useHandlePaste
|
||||
mCurTrack[i]->ClearAndPaste(mT0, mT1, out, false, false,
|
||||
NULL, false, !mFirstInGroup);
|
||||
mCurTrack[i]->ClearAndPaste(mT0, mT1, out, false, false);
|
||||
// If we were first in the group adjust non-selected group tracks
|
||||
if (mFirstInGroup) {
|
||||
TrackGroupIterator git(mOutputTracks);
|
||||
Track *t;
|
||||
for (t = git.First(mCurTrack[i]); t; t = git.Next())
|
||||
{
|
||||
if (!t->GetSelected() && t->IsSynchroSelected()) {
|
||||
t->SyncAdjust(mT1, mT0 + out->GetEndTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only the first channel can be first in its group
|
||||
mFirstInGroup = false;
|
||||
}
|
||||
|
|
|
@ -1000,10 +1000,6 @@ void ControlToolBar::SetupCutPreviewTracks(double playStart, double cutStart,
|
|||
|
||||
if (track1)
|
||||
{
|
||||
// Temporarily disable sticky track handling
|
||||
bool sticky = p->GetStickyFlag();
|
||||
p->SetStickyFlag(false);
|
||||
|
||||
// Duplicate and change tracks
|
||||
track1 = track1->Duplicate();
|
||||
track1->Clear(cutStart, cutEnd);
|
||||
|
@ -1017,9 +1013,6 @@ void ControlToolBar::SetupCutPreviewTracks(double playStart, double cutStart,
|
|||
mCutPreviewTracks->Add(track1);
|
||||
if (track2)
|
||||
mCutPreviewTracks->Add(track2);
|
||||
|
||||
// Reinstate sticky track handling
|
||||
p->SetStickyFlag(sticky);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user