1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Use TrackIterRange::Visit

This commit is contained in:
Paul Licameli 2017-04-11 17:55:19 -04:00
parent 17089d03bf
commit 1be3187b99
11 changed files with 414 additions and 525 deletions

View File

@ -2289,13 +2289,12 @@ CommandFlag MenuCommandHandler::GetUpdateFlags
if (!selectedRegion.isPoint())
flags |= TimeSelectedFlag;
TrackListIterator iter(project.GetTracks());
Track *t = iter.First();
while (t) {
auto tracks = project.GetTracks();
auto trackRange = tracks->Any();
if ( trackRange )
flags |= TracksExistFlag;
if (t->GetKind() == Track::Label) {
LabelTrack *lt = (LabelTrack *) t;
trackRange.Visit(
[&](LabelTrack *lt) {
flags |= LabelTracksExistFlag;
if (lt->GetSelected()) {
@ -2313,8 +2312,8 @@ CommandFlag MenuCommandHandler::GetUpdateFlags
if (lt->IsTextSelected()) {
flags |= CutCopyAvailableFlag;
}
}
else if (t->GetKind() == Track::Wave) {
},
[&](WaveTrack *t) {
flags |= WaveTracksExistFlag;
flags |= PlayableTracksExistFlag;
if (t->GetSelected()) {
@ -2331,9 +2330,8 @@ CommandFlag MenuCommandHandler::GetUpdateFlags
flags |= HasWaveDataFlag;
}
#if defined(USE_MIDI)
else if (t->GetKind() == Track::Note) {
NoteTrack *nt = (NoteTrack *) t;
,
[&](NoteTrack *nt) {
flags |= NoteTracksExistFlag;
#ifdef EXPERIMENTAL_MIDI_OUT
flags |= PlayableTracksExistFlag;
@ -2346,8 +2344,7 @@ CommandFlag MenuCommandHandler::GetUpdateFlags
}
}
#endif
t = iter.Next();
}
);
if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
flags |= ClipboardFlag;
@ -5589,24 +5586,21 @@ void MenuCommandHandler::OnCut(const CommandContext &context)
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
n = iter.First();
while (n) {
if (n->GetSelected()) {
Track::Holder dest;
tracks->Selected().Visit(
#if defined(USE_MIDI)
if (n->GetKind() == Track::Note)
// Since portsmf has a built-in cut operator, we use that instead
dest = n->Cut(selectedRegion.t0(),
selectedRegion.t1());
else
[&](NoteTrack *n) {
// Since portsmf has a built-in cut operator, we use that instead
auto dest = n->Cut(selectedRegion.t0(),
selectedRegion.t1());
FinishCopy(n, std::move(dest), newClipboard);
},
#endif
dest = n->Copy(selectedRegion.t0(),
selectedRegion.t1());
[&](Track *n) {
auto dest = n->Copy(selectedRegion.t0(),
selectedRegion.t1());
FinishCopy(n, std::move(dest), newClipboard);
}
n = iter.Next();
}
);
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
@ -5614,35 +5608,28 @@ void MenuCommandHandler::OnCut(const CommandContext &context)
// Proceed to change the project. If this throws, the project will be
// rolled back by the top level handler.
n = iter.First();
while (n) {
// We clear from selected and sync-lock selected tracks.
if (n->GetSelected() || n->IsSyncLockSelected()) {
switch (n->GetKind())
{
(tracks->Any() + &Track::IsSelectedOrSyncLockSelected).Visit(
#if defined(USE_MIDI)
case Track::Note:
//if NoteTrack, it was cut, so do not clear anything
break;
[](NoteTrack*) {
//if NoteTrack, it was cut, so do not clear anything
// PRL: But what if it was sync lock selected only, not selected?
},
#endif
case Track::Wave:
if (gPrefs->Read(wxT("/GUI/EnableCutLines"), (long)0)) {
((WaveTrack*)n)->ClearAndAddCutLine(
selectedRegion.t0(),
selectedRegion.t1());
break;
}
// Fall through
default:
n->Clear(selectedRegion.t0(),
selectedRegion.t1());
break;
[&](WaveTrack *wt, const Track::Fallthrough &fallthrough) {
if (gPrefs->Read(wxT("/GUI/EnableCutLines"), (long)0)) {
wt->ClearAndAddCutLine(
selectedRegion.t0(),
selectedRegion.t1());
}
else
fallthrough();
},
[&](Track *n) {
n->Clear(selectedRegion.t0(),
selectedRegion.t1());
}
n = iter.Next();
}
);
AudacityProject::msClipT0 = selectedRegion.t0();
AudacityProject::msClipT1 = selectedRegion.t1();
@ -5670,35 +5657,30 @@ void MenuCommandHandler::OnSplitCut(const CommandContext &context)
auto &selectedRegion = project.GetViewInfo().selectedRegion;
auto historyWindow = project.GetHistoryWindow();
TrackListIterator iter(tracks);
Track *n = iter.First();
AudacityProject::ClearClipboard();
auto pNewClipboard = TrackList::Create();
auto &newClipboard = *pNewClipboard;
while (n) {
if (n->GetSelected()) {
Track::Holder dest;
if (n->GetKind() == Track::Wave)
{
dest = ((WaveTrack*)n)->SplitCut(
selectedRegion.t0(),
selectedRegion.t1());
}
else
{
dest = n->Copy(selectedRegion.t0(),
Track::Holder dest;
tracks->Selected().Visit(
[&](WaveTrack *n) {
dest = n->SplitCut(
selectedRegion.t0(),
selectedRegion.t1());
if (dest)
FinishCopy(n, std::move(dest), newClipboard);
},
[&](Track *n) {
dest = n->Copy(selectedRegion.t0(),
selectedRegion.t1());
n->Silence(selectedRegion.t0(),
selectedRegion.t1());
n->Silence(selectedRegion.t0(),
selectedRegion.t1());
}
if (dest)
FinishCopy(n, std::move(dest), newClipboard);
}
n = iter.Next();
}
);
// Survived possibility of exceptions. Commit changes to the clipboard now.
newClipboard.Swap(*AudacityProject::msClipboard);
@ -6255,32 +6237,19 @@ void MenuCommandHandler::OnTrim(const CommandContext &context)
if (selectedRegion.isPoint())
return;
TrackListIterator iter(tracks);
Track *n = iter.First();
while (n) {
if (n->GetSelected()) {
switch (n->GetKind())
{
#if defined(USE_MIDI)
case Track::Note:
((NoteTrack*)n)->Trim(selectedRegion.t0(),
selectedRegion.t1());
break;
tracks->Selected().Visit(
#ifdef USE_MIDI
[&](NoteTrack *nt) {
nt->Trim(selectedRegion.t0(),
selectedRegion.t1());
},
#endif
case Track::Wave:
//Delete the section before the left selector
((WaveTrack*)n)->Trim(selectedRegion.t0(),
selectedRegion.t1());
break;
default:
break;
}
[&](WaveTrack *wt) {
//Delete the section before the left selector
wt->Trim(selectedRegion.t0(),
selectedRegion.t1());
}
n = iter.Next();
}
);
project.PushState(
wxString::Format(
@ -6303,24 +6272,16 @@ void MenuCommandHandler::OnSplitDelete(const CommandContext &context)
auto tracks = project.GetTracks();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
TrackListIterator iter(tracks);
Track *n = iter.First();
while (n) {
if (n->GetSelected()) {
if (n->GetKind() == Track::Wave)
{
((WaveTrack*)n)->SplitDelete(selectedRegion.t0(),
selectedRegion.t1());
}
else {
n->Silence(selectedRegion.t0(),
selectedRegion.t1());
}
tracks->Selected().Visit(
[&](WaveTrack *wt) {
wt->SplitDelete(selectedRegion.t0(),
selectedRegion.t1());
},
[&](Track *n) {
n->Silence(selectedRegion.t0(),
selectedRegion.t1());
}
n = iter.Next();
}
);
project.PushState(
wxString::Format(_("Split-deleted %.2f seconds at t=%.2f"),
@ -6713,39 +6674,43 @@ void MenuCommandHandler::OnSplitNew(const CommandContext &context)
auto tracks = project.GetTracks();
auto &selectedRegion = project.GetViewInfo().selectedRegion;
TrackListIterator iter(tracks);
Track *l = iter.Last();
Track::Holder dest;
for (Track *n = iter.First(); n; n = iter.Next()) {
if (n->GetSelected()) {
Track::Holder dest;
double newt0 = 0, newt1 = 0;
double offset = n->GetOffset();
if (n->GetKind() == Track::Wave) {
const auto wt = static_cast<WaveTrack*>(n);
// This iteration is unusual because we add to the list inside the loop
auto range = tracks->Selected();
auto last = *range.rbegin();
for (auto track : range) {
track->TypeSwitch(
[&](WaveTrack *wt) {
// Clips must be aligned to sample positions or the NEW clip will not fit in the gap where it came from
double offset = wt->GetOffset();
offset = wt->LongSamplesToTime(wt->TimeToLongSamples(offset));
newt0 = wt->LongSamplesToTime(wt->TimeToLongSamples(selectedRegion.t0()));
newt1 = wt->LongSamplesToTime(wt->TimeToLongSamples(selectedRegion.t1()));
double newt0 = wt->LongSamplesToTime(wt->TimeToLongSamples(
selectedRegion.t0()));
double newt1 = wt->LongSamplesToTime(wt->TimeToLongSamples(
selectedRegion.t1()));
dest = wt->SplitCut(newt0, newt1);
if (dest) {
dest->SetOffset(wxMax(newt0, offset));
FinishCopy(wt, std::move(dest), *tracks);
}
}
#if 0
,
// LL: For now, just skip all non-wave tracks since the other do not
// yet support proper splitting.
else {
dest = n->Cut(selectedRegion.t0(),
selectedRegion.t1());
[&](Track *n) {
dest = n->Cut(viewInfo.selectedRegion.t0(),
viewInfo.selectedRegion.t1());
if (dest) {
dest->SetOffset(wxMax(0, n->GetOffset()));
FinishCopy(n, std::move(dest), *tracks);
}
}
#endif
if (dest) {
dest->SetOffset(wxMax(newt0, offset));
FinishCopy(n, std::move(dest), *tracks);
}
}
if (n == l) {
);
if (track == last)
break;
}
}
project.PushState(_("Split to new track"), _("Split New"));
@ -8928,29 +8893,25 @@ void MenuCommandHandler::OnScoreAlign(const CommandContext &context)
auto tracks = project.GetTracks();
const auto rate = project.GetRate();
TrackListIterator iter(tracks);
Track *t = iter.First();
int numWaveTracksSelected = 0;
int numNoteTracksSelected = 0;
int numOtherTracksSelected = 0;
NoteTrack *nt;
double endTime = 0.0;
// Iterate through once to make sure that there is exactly
// one WaveTrack and one NoteTrack selected.
while (t) {
if (t->GetSelected()) {
if (t->GetKind() == Track::Wave) {
numWaveTracksSelected++;
WaveTrack *wt = (WaveTrack *) t;
endTime = endTime > wt->GetEndTime() ? endTime : wt->GetEndTime();
} else if(t->GetKind() == Track::Note) {
numNoteTracksSelected++;
nt = (NoteTrack *) t;
} else numOtherTracksSelected++;
GetTracks()->Selected().Visit(
[&](WaveTrack *wt) {
numWaveTracksSelected++;
endTime = endTime > wt->GetEndTime() ? endTime : wt->GetEndTime();
},
[&](NoteTrack *) {
numNoteTracksSelected++;
},
[&](Track*) {
numOtherTracksSelected++;
}
t = iter.Next();
}
);
if(numWaveTracksSelected == 0 ||
numNoteTracksSelected != 1 ||

View File

@ -3821,55 +3821,45 @@ void AudacityProject::WriteXML(XMLWriter &xmlFile, bool bWantSaveCopy)
mTags->WriteXML(xmlFile);
const Track *t;
WaveTrack* pWaveTrack;
TrackListConstIterator iter(GetTracks());
t = iter.First();
unsigned int ndx = 0;
while (t) {
if ((t->GetKind() == Track::Wave) && bWantSaveCopy)
{
auto wt = static_cast<const WaveTrack *>(t);
GetTracks()->Any().Visit(
[&](WaveTrack *pWaveTrack) {
if (bWantSaveCopy) {
if (!pWaveTrack->IsLeader())
return;
//vvv This should probably be a method, WaveTrack::WriteCompressedTrackXML().
xmlFile.StartTag(wxT("import"));
xmlFile.WriteAttr(wxT("filename"), mStrOtherNamesArray[ndx]); // Assumes mTracks order hasn't changed!
//vvv This should probably be a method, WaveTrack::WriteCompressedTrackXML().
xmlFile.StartTag(wxT("import"));
xmlFile.WriteAttr(wxT("filename"), mStrOtherNamesArray[ndx]); // Assumes mTracks order hasn't changed!
// Don't store "channel" and "linked" tags because the importer can figure that out,
// e.g., from stereo Ogg files.
// xmlFile.WriteAttr(wxT("channel"), t->GetChannel());
// xmlFile.WriteAttr(wxT("linked"), t->GetLinked());
// Don't store "channel" and "linked" tags because the importer can figure that out,
// e.g., from stereo Ogg files.
// xmlFile.WriteAttr(wxT("channel"), t->GetChannel());
// xmlFile.WriteAttr(wxT("linked"), t->GetLinked());
xmlFile.WriteAttr(wxT("offset"), t->GetOffset(), 8);
xmlFile.WriteAttr(wxT("mute"), wt->GetMute());
xmlFile.WriteAttr(wxT("solo"), wt->GetSolo());
xmlFile.WriteAttr(wxT("height"), t->GetActualHeight());
xmlFile.WriteAttr(wxT("minimized"), t->GetMinimized());
xmlFile.WriteAttr(wxT("offset"), pWaveTrack->GetOffset(), 8);
xmlFile.WriteAttr(wxT("mute"), pWaveTrack->GetMute());
xmlFile.WriteAttr(wxT("solo"), pWaveTrack->GetSolo());
xmlFile.WriteAttr(wxT("height"), pWaveTrack->GetActualHeight());
xmlFile.WriteAttr(wxT("minimized"), pWaveTrack->GetMinimized());
pWaveTrack = (WaveTrack*)t;
// Don't store "rate" tag because the importer can figure that out.
// xmlFile.WriteAttr(wxT("rate"), pWaveTrack->GetRate());
xmlFile.WriteAttr(wxT("gain"), (double)pWaveTrack->GetGain());
xmlFile.WriteAttr(wxT("pan"), (double)pWaveTrack->GetPan());
xmlFile.EndTag(wxT("import"));
// Don't store "rate" tag because the importer can figure that out.
// xmlFile.WriteAttr(wxT("rate"), pWaveTrack->GetRate());
xmlFile.WriteAttr(wxT("gain"), (double)pWaveTrack->GetGain());
xmlFile.WriteAttr(wxT("pan"), (double)pWaveTrack->GetPan());
xmlFile.EndTag(wxT("import"));
ndx++;
if (t->GetLinked())
t = iter.Next();
}
else if (t->GetKind() == Track::Wave)
{
pWaveTrack = (WaveTrack*)t;
pWaveTrack->SetAutoSaveIdent(mAutoSaving ? ++ndx : 0);
ndx++;
}
else {
pWaveTrack->SetAutoSaveIdent(mAutoSaving ? ++ndx : 0);
pWaveTrack->WriteXML(xmlFile);
}
},
[&](Track *t) {
t->WriteXML(xmlFile);
}
else
{
t->WriteXML(xmlFile);
}
t = iter.Next();
}
);
if (!mAutoSaving)
{

View File

@ -16,6 +16,7 @@
#include "Project.h"
#include "LabelTrack.h"
#include "NoteTrack.h"
#include "WaveTrack.h"
inline bool operator < (SnapPoint s1, SnapPoint s2)
@ -100,19 +101,14 @@ void SnapManager::Reinit()
// Add a SnapPoint at t=0
mSnapPoints.push_back(SnapPoint{});
TrackListConstIterator iter(mTracks);
for (const Track *track = iter.First(); track; track = iter.Next())
{
if (mTrackExclusions &&
mTrackExclusions->end() !=
std::find(mTrackExclusions->begin(), mTrackExclusions->end(), track))
{
continue;
}
if (track->GetKind() == Track::Label)
{
LabelTrack *labelTrack = (LabelTrack *)track;
auto trackRange =
mTracks->Any()
- [&](const Track *pTrack){
return mTrackExclusions &&
make_iterator_range( *mTrackExclusions ).contains( pTrack );
};
trackRange.Visit(
[&](const LabelTrack *labelTrack) {
for (int i = 0, cnt = labelTrack->GetNumLabels(); i < cnt; ++i)
{
const LabelStruct *label = labelTrack->GetLabel(i);
@ -124,10 +120,8 @@ void SnapManager::Reinit()
CondListAdd(t1, labelTrack);
}
}
}
else if (track->GetKind() == Track::Wave)
{
auto waveTrack = static_cast<const WaveTrack *>(track);
},
[&](const WaveTrack *waveTrack) {
for (const auto &clip: waveTrack->GetClips())
{
if (mClipExclusions)
@ -144,9 +138,7 @@ void SnapManager::Reinit()
}
if (skip)
{
continue;
}
}
CondListAdd(clip->GetStartTime(), waveTrack);
@ -154,13 +146,13 @@ void SnapManager::Reinit()
}
}
#ifdef USE_MIDI
else if (track->GetKind() == Track::Note)
{
,
[&](const NoteTrack *track) {
CondListAdd(track->GetStartTime(), track);
CondListAdd(track->GetEndTime(), track);
}
#endif
}
);
// Sort all by time
std::sort(mSnapPoints.begin(), mSnapPoints.end());

View File

@ -229,28 +229,23 @@ bool EffectChangeSpeed::Process()
CopyInputTracks(Track::All); // Set up mOutputTracks.
bool bGoodResult = true;
TrackListIterator iter(mOutputTracks.get());
Track* t;
mCurTrackNum = 0;
mMaxNewLength = 0.0;
mFactor = 100.0 / (100.0 + m_PercentChange);
t = iter.First();
while (t != NULL)
{
if (t->GetKind() == Track::Label) {
if (t->GetSelected() || t->IsSyncLockSelected())
mOutputTracks->Any().VisitWhile( bGoodResult,
[&](LabelTrack *lt) {
if (lt->GetSelected() || lt->IsSyncLockSelected())
{
if (!ProcessLabelTrack(static_cast<LabelTrack*>(t))) {
if (!ProcessLabelTrack(lt))
bGoodResult = false;
break;
}
}
}
else if (t->GetKind() == Track::Wave && t->GetSelected())
{
WaveTrack *pOutWaveTrack = (WaveTrack*)t;
},
[&](WaveTrack *pOutWaveTrack, const Track::Fallthrough &fallthrough) {
if (!pOutWaveTrack->GetSelected())
return fallthrough();
//Get start and end times from track
mCurT0 = pOutWaveTrack->GetStartTime();
mCurT1 = pOutWaveTrack->GetEndTime();
@ -268,21 +263,15 @@ bool EffectChangeSpeed::Process()
//ProcessOne() (implemented below) processes a single track
if (!ProcessOne(pOutWaveTrack, start, end))
{
bGoodResult = false;
break;
}
}
mCurTrackNum++;
},
[&](Track *t) {
if (t->IsSyncLockSelected())
t->SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
}
else if (t->IsSyncLockSelected())
{
t->SyncLockAdjust(mT1, mT0 + (mT1 - mT0) * mFactor);
}
//Iterate to the next track
t=iter.Next();
}
);
if (bGoodResult)
ReplaceProcessedTracks(bGoodResult);

View File

@ -1348,154 +1348,152 @@ bool Effect::ProcessPass()
mBufferSize = 0;
mBlockSize = 0;
TrackListIterator iter(mOutputTracks.get());
int count = 0;
bool clear = false;
Track* t = iter.First();
for (t = iter.First(); t; t = iter.Next())
{
if (t->GetKind() != Track::Wave || !t->GetSelected())
{
if (t->IsSyncLockSelected())
{
t->SyncLockAdjust(mT1, mT0 + mDuration);
}
continue;
}
const bool multichannel = mNumAudioIn > 1;
auto range = multichannel
? mOutputTracks->Leaders()
: mOutputTracks->Any();
range.VisitWhile( bGoodResult,
[&](WaveTrack *left, const Track::Fallthrough &fallthrough) {
if (!left->GetSelected())
return fallthrough();
WaveTrack *left = (WaveTrack *)t;
WaveTrack *right;
sampleCount len;
sampleCount leftStart;
sampleCount rightStart;
WaveTrack *right;
sampleCount len;
sampleCount leftStart;
sampleCount rightStart;
if (!isGenerator)
{
GetSamples(left, &leftStart, &len);
mSampleCnt = len;
}
else
{
len = 0;
leftStart = 0;
mSampleCnt = left->TimeToLongSamples(mDuration);
}
mNumChannels = 1;
if (left->GetChannel() == Track::LeftChannel)
{
map[0] = ChannelNameFrontLeft;
}
else if (left->GetChannel() == Track::RightChannel)
{
map[0] = ChannelNameFrontRight;
}
else
{
map[0] = ChannelNameMono;
}
map[1] = ChannelNameEOL;
right = NULL;
rightStart = 0;
if (left->GetLinked() && mNumAudioIn > 1)
{
// Assume linked track is wave
right = static_cast<WaveTrack *>(iter.Next());
if (!isGenerator)
{
GetSamples(right, &rightStart, &len);
}
clear = false;
mNumChannels = 2;
if (right->GetChannel() == Track::LeftChannel)
{
map[1] = ChannelNameFrontLeft;
}
else if (right->GetChannel() == Track::RightChannel)
{
map[1] = ChannelNameFrontRight;
GetSamples(left, &leftStart, &len);
mSampleCnt = len;
}
else
{
map[1] = ChannelNameMono;
len = 0;
leftStart = 0;
mSampleCnt = left->TimeToLongSamples(mDuration);
}
map[2] = ChannelNameEOL;
}
// Let the client know the sample rate
SetSampleRate(left->GetRate());
mNumChannels = 1;
// Get the block size the client wants to use
auto max = left->GetMaxBlockSize() * 2;
mBlockSize = SetBlockSize(max);
if (left->GetChannel() == Track::LeftChannel)
{
map[0] = ChannelNameFrontLeft;
}
else if (left->GetChannel() == Track::RightChannel)
{
map[0] = ChannelNameFrontRight;
}
else
{
map[0] = ChannelNameMono;
}
map[1] = ChannelNameEOL;
// Calculate the buffer size to be at least the max rounded up to the clients
// selected block size.
const auto prevBufferSize = mBufferSize;
mBufferSize = ((max + (mBlockSize - 1)) / mBlockSize) * mBlockSize;
right = NULL;
rightStart = 0;
if (left->GetLinked() && multichannel)
{
// Assume linked track is wave
right = static_cast<WaveTrack *>(left->GetLink());
if (!isGenerator)
{
GetSamples(right, &rightStart, &len);
}
clear = false;
mNumChannels = 2;
// If the buffer size has changed, then (re)allocate the buffers
if (prevBufferSize != mBufferSize)
{
// Always create the number of input buffers the client expects even if we don't have
// the same number of channels.
inBufPos.reinit( mNumAudioIn );
inBuffer.reinit( mNumAudioIn, mBufferSize );
if (right->GetChannel() == Track::LeftChannel)
{
map[1] = ChannelNameFrontLeft;
}
else if (right->GetChannel() == Track::RightChannel)
{
map[1] = ChannelNameFrontRight;
}
else
{
map[1] = ChannelNameMono;
}
map[2] = ChannelNameEOL;
}
// We won't be using more than the first 2 buffers, so clear the rest (if any)
for (size_t i = 2; i < mNumAudioIn; i++)
// Let the client know the sample rate
SetSampleRate(left->GetRate());
// Get the block size the client wants to use
auto max = left->GetMaxBlockSize() * 2;
mBlockSize = SetBlockSize(max);
// Calculate the buffer size to be at least the max rounded up to the clients
// selected block size.
const auto prevBufferSize = mBufferSize;
mBufferSize = ((max + (mBlockSize - 1)) / mBlockSize) * mBlockSize;
// If the buffer size has changed, then (re)allocate the buffers
if (prevBufferSize != mBufferSize)
{
// Always create the number of input buffers the client expects even if we don't have
// the same number of channels.
inBufPos.reinit( mNumAudioIn );
inBuffer.reinit( mNumAudioIn, mBufferSize );
// We won't be using more than the first 2 buffers, so clear the rest (if any)
for (size_t i = 2; i < mNumAudioIn; i++)
{
for (size_t j = 0; j < mBufferSize; j++)
{
inBuffer[i][j] = 0.0;
}
}
// Always create the number of output buffers the client expects even if we don't have
// the same number of channels.
outBufPos.reinit( mNumAudioOut );
// Output buffers get an extra mBlockSize worth to give extra room if
// the plugin adds latency
outBuffer.reinit( mNumAudioOut, mBufferSize + mBlockSize );
}
// (Re)Set the input buffer positions
for (size_t i = 0; i < mNumAudioIn; i++)
{
inBufPos[i] = inBuffer[i].get();
}
// (Re)Set the output buffer positions
for (size_t i = 0; i < mNumAudioOut; i++)
{
outBufPos[i] = outBuffer[i].get();
}
// Clear unused input buffers
if (!right && !clear && mNumAudioIn > 1)
{
for (size_t j = 0; j < mBufferSize; j++)
{
inBuffer[i][j] = 0.0;
inBuffer[1][j] = 0.0;
}
clear = true;
}
// Always create the number of output buffers the client expects even if we don't have
// the same number of channels.
// Output buffers get an extra mBlockSize worth to give extra room if
// the plugin adds latency
outBufPos.reinit( mNumAudioOut );
outBuffer.reinit( mNumAudioOut, mBufferSize + mBlockSize );
}
// Go process the track(s)
bGoodResult = ProcessTrack(
count, map, left, right, leftStart, rightStart, len,
inBuffer, outBuffer, inBufPos, outBufPos);
if (!bGoodResult)
return;
// (Re)Set the input buffer positions
for (size_t i = 0; i < mNumAudioIn; i++)
{
inBufPos[i] = inBuffer[i].get();
count++;
},
[&](Track *t) {
if (t->IsSyncLockSelected())
t->SyncLockAdjust(mT1, mT0 + mDuration);
}
// (Re)Set the output buffer positions
for (size_t i = 0; i < mNumAudioOut; i++)
{
outBufPos[i] = outBuffer[i].get();
}
// Clear unused input buffers
if (!right && !clear && mNumAudioIn > 1)
{
for (size_t j = 0; j < mBufferSize; j++)
{
inBuffer[1][j] = 0.0;
}
clear = true;
}
// Go process the track(s)
bGoodResult = ProcessTrack(
count, map, left, right, leftStart, rightStart, len,
inBuffer, outBuffer, inBufPos, outBufPos);
if (!bGoodResult)
{
break;
}
count++;
}
);
if (bGoodResult && GetType() == EffectTypeGenerate)
{

View File

@ -38,14 +38,11 @@ bool Generator::Process()
// Iterate over the tracks
bool bGoodResult = true;
int ntrack = 0;
TrackListIterator iter(mOutputTracks.get());
Track* t = iter.First();
while (t != NULL)
{
if (t->GetKind() == Track::Wave && t->GetSelected()) {
WaveTrack* track = (WaveTrack*)t;
mOutputTracks->Any().VisitWhile( bGoodResult,
[&](WaveTrack *track, const Track::Fallthrough &fallthrough) {
if (!track->GetSelected())
return fallthrough();
bool editClipCanMove = gPrefs->GetEditClipsCanMove();
//if we can't move clips, and we're generating into an empty space,
@ -59,7 +56,8 @@ bool Generator::Process()
wxICON_STOP,
_("Error"));
Failure();
return false;
bGoodResult = false;
return;
}
if (GetDuration() > 0.0)
@ -87,7 +85,7 @@ bool Generator::Process()
if (!bGoodResult) {
Failure();
return false;
return;
}
}
else
@ -98,21 +96,23 @@ bool Generator::Process()
}
ntrack++;
},
[&](Track *t) {
if (t->IsSyncLockSelected()) {
t->SyncLockAdjust(mT1, mT0 + GetDuration());
}
}
else if (t->IsSyncLockSelected()) {
t->SyncLockAdjust(mT1, mT0 + GetDuration());
}
// Move on to the next track
t = iter.Next();
);
if (bGoodResult) {
Success();
this->ReplaceProcessedTracks(bGoodResult);
mT1 = mT0 + GetDuration(); // Update selection.
}
Success();
this->ReplaceProcessedTracks(bGoodResult);
mT1 = mT0 + GetDuration(); // Update selection.
return true;
return bGoodResult;
}
bool BlockGenerator::GenerateTrack(WaveTrack *tmp,

View File

@ -113,27 +113,19 @@ bool EffectRepeat::Process()
bool bGoodResult = true;
double maxDestLen = 0.0; // used to change selection to generated bit
TrackListIterator iter(mOutputTracks.get());
for (Track *t = iter.First(); t && bGoodResult; t = iter.Next())
{
if (t->GetKind() == Track::Label)
mOutputTracks->Any().VisitWhile( bGoodResult,
[&](LabelTrack *track)
{
if (t->GetSelected() || t->IsSyncLockSelected())
if (track->GetSelected() || track->IsSyncLockSelected())
{
LabelTrack* track = (LabelTrack*)t;
if (!track->Repeat(mT0, mT1, repeatCount))
{
bGoodResult = false;
break;
}
}
}
else if (t->GetKind() == Track::Wave && t->GetSelected())
},
[&](WaveTrack *track, const Track::Fallthrough &fallthrough)
{
WaveTrack* track = (WaveTrack*)t;
if (!track->GetSelected())
return fallthrough(); // Fall through to next lambda
auto start = track->TimeToLongSamples(mT0);
auto end = track->TimeToLongSamples(mT1);
auto len = end - start;
@ -141,9 +133,7 @@ bool EffectRepeat::Process()
double tc = mT0 + tLen;
if (len <= 0)
{
continue;
}
return;
auto dest = track->Copy(mT0, mT1);
for(int j=0; j<repeatCount; j++)
@ -151,7 +141,7 @@ bool EffectRepeat::Process()
if (TrackProgress(nTrack, j / repeatCount)) // TrackProgress returns true on Cancel.
{
bGoodResult = false;
break;
return;
}
track->Paste(tc, dest.get());
tc += tLen;
@ -159,12 +149,13 @@ bool EffectRepeat::Process()
if (tc > maxDestLen)
maxDestLen = tc;
nTrack++;
}
else if (t->IsSyncLockSelected())
},
[&](Track *t)
{
t->SyncLockAdjust(mT1, mT1 + (mT1 - mT0) * repeatCount);
if( t->IsSyncLockSelected() )
t->SyncLockAdjust(mT1, mT1 + (mT1 - mT0) * repeatCount);
}
}
);
if (bGoodResult)
{

View File

@ -67,37 +67,27 @@ bool EffectReverse::Process()
//Track::All is needed because Reverse should move the labels too
this->CopyInputTracks(Track::All); // Set up mOutputTracks.
bool bGoodResult = true;
TrackListIterator iter(mOutputTracks.get());
Track *t = iter.First();
int count = 0;
while (t) {
if (t->GetKind() == Track::Wave &&
(t->GetSelected() || t->IsSyncLockSelected()))
{
WaveTrack *track = (WaveTrack*)t;
auto trackRange =
mOutputTracks->Any() + &Track::IsSelectedOrSyncLockSelected;
trackRange.VisitWhile( bGoodResult,
[&](WaveTrack * track) {
if (mT1 > mT0) {
auto start = track->TimeToLongSamples(mT0);
auto end = track->TimeToLongSamples(mT1);
auto len = end - start;
if (!ProcessOneWave(count, track, start, len))
{
bGoodResult = false;
break;
}
}
}
else if (t->GetKind() == Track::Label &&
(t->GetSelected() || t->IsSyncLockSelected()))
{
LabelTrack *track = (LabelTrack*)t;
count++;
},
[&](LabelTrack * track) {
track->ChangeLabelsOnReverse(mT0, mT1);
count++;
}
t = iter.Next();
count++;
}
);
this->ReplaceProcessedTracks(bGoodResult);
return bGoodResult;

View File

@ -217,8 +217,6 @@ bool EffectSBSMS::Process()
//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.
TrackListIterator iter(mOutputTracks.get());
Track* t;
mCurTrackNum = 0;
double maxDuration = 0.0;
@ -229,19 +227,16 @@ bool EffectSBSMS::Process()
Slide pitchSlide(pitchSlideType,pitchStart,pitchEnd);
mTotalStretch = rateSlide.getTotalStretch();
t = iter.First();
while (bGoodResult && t != NULL) {
if (t->GetKind() == Track::Label &&
(t->GetSelected() || (mustSync && t->IsSyncLockSelected())) )
{
if (!ProcessLabelTrack(static_cast<LabelTrack*>(t))) {
mOutputTracks->Leaders().VisitWhile( bGoodResult,
[&](LabelTrack *lt, const Track::Fallthrough &fallthrough) {
if (!(lt->GetSelected() || (mustSync && lt->IsSyncLockSelected())))
return fallthrough();
if (!ProcessLabelTrack(lt))
bGoodResult = false;
break;
}
}
else if (t->GetKind() == Track::Wave && t->GetSelected() )
{
WaveTrack* leftTrack = (WaveTrack*)t;
},
[&](WaveTrack *leftTrack, const Track::Fallthrough &fallthrough) {
if (!leftTrack->GetSelected())
return fallthrough();
//Get start and end times from track
mCurT0 = leftTrack->GetStartTime();
@ -261,7 +256,7 @@ bool EffectSBSMS::Process()
if (leftTrack->GetLinked()) {
double t;
// Assume linked track is wave or null
rightTrack = static_cast<WaveTrack*>(iter.Next());
rightTrack = static_cast<WaveTrack*>(leftTrack->GetLink());
//Adjust bounds by the right tracks markers
t = rightTrack->GetStartTime();
@ -321,7 +316,8 @@ bool EffectSBSMS::Process()
( samplesToProcess.as_long_long() ),
0, nullptr);
} else {
}
else {
rb.bPitch = false;
outSlideType = (srProcess==srTrack?SlideIdentity:SlideConstant);
outResampleCB = postResampleCB;
@ -414,8 +410,10 @@ bool EffectSBSMS::Process()
frac *= 2.0; // Show twice as far for each track, because we're doing 2 at once.
}
}
if (TrackProgress(nWhichTrack, frac))
return false;
if (TrackProgress(nWhichTrack, frac)) {
bGoodResult = false;
return;
}
}
{
@ -425,35 +423,34 @@ bool EffectSBSMS::Process()
std::rethrow_exception(pException);
}
if (bGoodResult) {
rb.outputLeftTrack->Flush();
if(rightTrack)
rb.outputRightTrack->Flush();
rb.outputLeftTrack->Flush();
if(rightTrack)
rb.outputRightTrack->Flush();
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack.get(),
true, false, warper.get());
leftTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputLeftTrack.get(),
true, false, warper.get());
if(rightTrack)
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack.get(),
true, false, warper.get());
}
if(rightTrack)
rightTrack->ClearAndPaste(mCurT0, mCurT1, rb.outputRightTrack.get(),
true, false, warper.get());
}
mCurTrackNum++;
},
[&](Track *t) {
if (mustSync && t->IsSyncLockSelected())
{
t->SyncLockAdjust(mCurT1, mCurT0 + (mCurT1 - mCurT0) * mTotalStretch);
}
}
else if (mustSync && t->IsSyncLockSelected())
{
t->SyncLockAdjust(mCurT1, mCurT0 + (mCurT1 - mCurT0) * mTotalStretch);
}
//Iterate to the next track
t = iter.Next();
}
);
if (bGoodResult)
if (bGoodResult) {
ReplaceProcessedTracks(bGoodResult);
// Update selection
mT0 = mCurT0;
mT1 = mCurT0 + maxDuration;
// Update selection
mT0 = mCurT0;
mT1 = mCurT0 + maxDuration;
}
return bGoodResult;
}

View File

@ -86,36 +86,28 @@ bool EffectSoundTouch::ProcessWithTimeWarper(const TimeWarper &warper)
this->CopyInputTracks(Track::All);
bool bGoodResult = true;
TrackListIterator iter(mOutputTracks.get());
Track* t;
mCurTrackNum = 0;
m_maxNewLength = 0.0;
t = iter.First();
while (t != NULL) {
if (t->GetKind() == Track::Label &&
(t->GetSelected() || (mustSync && t->IsSyncLockSelected())) )
{
if (!ProcessLabelTrack(static_cast<LabelTrack*>(t), warper))
{
mOutputTracks->Leaders().VisitWhile( bGoodResult,
[&]( LabelTrack *lt, const Track::Fallthrough &fallthrough ) {
if ( !(lt->GetSelected() || (mustSync && lt->IsSyncLockSelected())) )
return fallthrough();
if (!ProcessLabelTrack(lt, warper))
bGoodResult = false;
break;
}
}
},
#ifdef USE_MIDI
else if (t->GetKind() == Track::Note &&
(t->GetSelected() || (mustSync && t->IsSyncLockSelected())))
{
if (!ProcessNoteTrack(static_cast<NoteTrack*>(t), warper))
{
[&]( NoteTrack *nt, const Track::Fallthrough &fallthrough ) {
if ( !(nt->GetSelected() || (mustSync && nt->IsSyncLockSelected())) )
return fallthrough();
if (!ProcessNoteTrack(nt, warper))
bGoodResult = false;
break;
}
}
},
#endif
else if (t->GetKind() == Track::Wave && t->GetSelected())
{
WaveTrack* leftTrack = (WaveTrack*)t;
[&]( WaveTrack *leftTrack, const Track::Fallthrough &fallthrough ) {
if (!leftTrack->GetSelected())
return fallthrough();
//Get start and end times from track
mCurT0 = leftTrack->GetStartTime();
mCurT1 = leftTrack->GetEndTime();
@ -131,7 +123,7 @@ bool EffectSoundTouch::ProcessWithTimeWarper(const TimeWarper &warper)
if (leftTrack->GetLinked()) {
double t;
// Assume linked track is wave
WaveTrack* rightTrack = static_cast<WaveTrack*>(iter.Next());
WaveTrack* rightTrack = static_cast<WaveTrack*>(leftTrack->GetLink());
//Adjust bounds by the right tracks markers
t = rightTrack->GetStartTime();
@ -150,10 +142,7 @@ bool EffectSoundTouch::ProcessWithTimeWarper(const TimeWarper &warper)
//ProcessStereo() (implemented below) processes a stereo track
if (!ProcessStereo(leftTrack, rightTrack, start, end, warper))
{
bGoodResult = false;
break;
}
mCurTrackNum++; // Increment for rightTrack, too.
} else {
//Transform the marker timepoints to samples
@ -165,21 +154,17 @@ bool EffectSoundTouch::ProcessWithTimeWarper(const TimeWarper &warper)
//ProcessOne() (implemented below) processes a single track
if (!ProcessOne(leftTrack, start, end, warper))
{
bGoodResult = false;
break;
}
}
}
mCurTrackNum++;
},
[&]( Track *t ) {
if (mustSync && t->IsSyncLockSelected()) {
t->SyncLockAdjust(mT1, warper.Warp(mT1));
}
}
else if (mustSync && t->IsSyncLockSelected()) {
t->SyncLockAdjust(mT1, warper.Warp(mT1));
}
//Iterate to the next track
t = iter.Next();
}
);
if (bGoodResult)
ReplaceProcessedTracks(bGoodResult);

View File

@ -523,31 +523,26 @@ bool EffectTruncSilence::DoRemoval
mTruncLongestAllowedSilence);
}
double cutLen = std::max(0.0, inLength - outLength);
const double cutLen = std::max(0.0, inLength - outLength);
// Don't waste time cutting nothing.
if( cutLen == 0.0 )
continue;
totalCutLen += cutLen;
TrackListIterator iterOut(mOutputTracks.get());
bool lastSeen = false;
for (Track *t = iterOut.StartWith(firstTrack); t && !lastSeen; t = iterOut.Next())
{
lastSeen = (t == lastTrack);
if (!(t->GetSelected() || t->IsSyncLockSelected()))
continue;
double cutStart = (r->start + r->end - cutLen) / 2;
double cutEnd = cutStart + cutLen;
(mOutputTracks->Any()
.StartingWith(firstTrack).EndingAfter(lastTrack)
+ &Track::IsSelectedOrSyncLockSelected
- [&](const Track *pTrack) { return
// Don't waste time past the end of a track
pTrack->GetEndTime() < r->start;
}
).Visit(
[&](WaveTrack *wt) {
// Don't waste time past the end of a track
if (t->GetEndTime() < r->start)
continue;
// Don't waste time cutting nothing.
if( cutLen == 0.0 )
continue;
double cutStart = (r->start + r->end - cutLen) / 2;
double cutEnd = cutStart + cutLen;
if (t->GetKind() == Track::Wave)
{
// In WaveTracks, clear with a cross-fade
WaveTrack *const wt = static_cast<WaveTrack*>(t);
auto blendFrames = mBlendFrameCount;
// Round start/end times to frame boundaries
cutStart = wt->LongSamplesToTime(wt->TimeToLongSamples(cutStart));
@ -580,11 +575,12 @@ bool EffectTruncSilence::DoRemoval
// Write cross-faded data
wt->Set((samplePtr)buf1.get(), floatSample, t1, blendFrames);
}
else
},
[&](Track *t) {
// Non-wave tracks: just do a sync-lock adjust
t->SyncLockAdjust(cutEnd, cutStart);
}
}
);
++whichReg;
}