Bug2346: Complete fix...

... without making undesirable dependency cycles.

Eliminate calls to NewWaveTrack in effects, but in Edit>Copy too, which was
not mentioned in the bug report.  (Copying a track, deselecting all, and pasting
preserved CLIP colors, but not the TRACK color setting which applies to newly
generated clips.)

Instead, always use the new function WaveTrack::EmptyCopy from the track to be
later replaced, getting color information.

NewWaveTrack is still used in benchmark test, import, the Track menu
commands that make new tracks, recording to new tracks, and generators without
a selection, where there is no track to copy from.

Also when deserializing tracks from the .aup file, in which case the saved
color is later retrieved from the file.

Also, in mix-and-render, where other logic decides whether to copy colors
afterward.

See commit a9658e6ef7
This commit is contained in:
Paul Licameli 2020-03-10 21:40:14 -04:00
parent 06b2831d9b
commit c2feee6cea
16 changed files with 48 additions and 47 deletions

View File

@ -606,7 +606,7 @@ bool ProjectAudioManager::DoRecord(AudacityProject &project,
// Pad the recording track with silence, up to the
// maximum time.
auto newTrack = TrackFactory::Get( *p ).NewWaveTrack();
auto newTrack = pending->EmptyCopy();
newTrack->InsertSilence(0.0, t0 - endTime);
newTrack->Flush();
pending->Clear(endTime, t0);

View File

@ -530,16 +530,21 @@ void WaveTrack::Trim (double t0, double t1)
WaveTrack::Holder WaveTrack::EmptyCopy() const
{
auto result = std::make_shared<WaveTrack>( mDirManager, mFormat, mRate );
result->Init(*this);
return result;
}
Track::Holder WaveTrack::Copy(double t0, double t1, bool forClipboard) const
{
if (t1 < t0)
THROW_INCONSISTENCY_EXCEPTION;
auto result = std::make_shared<WaveTrack>( mDirManager, mFormat, mRate );
auto result = EmptyCopy();
WaveTrack *newTrack = result.get();
newTrack->Init(*this);
// PRL: Why shouldn't cutlines be copied and pasted too? I don't know, but
// that was the old behavior. But this function is also used by the
// Duplicate command and I changed its behavior in that case.

View File

@ -158,6 +158,10 @@ private:
Track::Holder Cut(double t0, double t1) override;
// Make another track copying format, rate, color, etc. but containing no
// clips
Holder EmptyCopy() const;
// If forClipboard is true,
// and there is no clip at the end time of the selection, then the result
// will contain a "placeholder" clip whose only purpose is to make

View File

@ -479,8 +479,8 @@ bool EffectChangeSpeed::ProcessOne(WaveTrack * track,
// initialization, per examples of Mixer::Mixer and
// EffectSoundTouch::ProcessOne
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),
track->GetRate());
auto outputTrack = track->EmptyCopy();
//Get the length of the selection (as double). len is
//used simple to calculate a progress meter, so it is easier

View File

@ -1613,13 +1613,10 @@ bool Effect::ProcessTrack(int count,
cleared = true;
// Create temporary tracks
genLeft = mFactory->NewWaveTrack(left->GetSampleFormat(), left->GetRate());
genLeft->SetWaveColorIndex( left->GetWaveColorIndex() );
genLeft = left->EmptyCopy();
if (right) {
genRight = mFactory->NewWaveTrack(right->GetSampleFormat(), right->GetRate());
genRight->SetWaveColorIndex( right->GetWaveColorIndex() );
}
if (right)
genRight = right->EmptyCopy();
}
// Call the effect until we run out of input or delayed samples

View File

@ -1288,7 +1288,8 @@ bool EffectEqualization::ProcessOne(int count, WaveTrack * t,
sampleCount start, sampleCount len)
{
// create a NEW WaveTrack to hold all of the output, including 'tails' each end
auto output = mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
wxASSERT(mM - 1 < windowSize);
size_t L = windowSize - (mM - 1); //Process L samples at a go

View File

@ -410,7 +410,8 @@ bool EffectEqualization48x::DeltaTrack(
Floats buffer1{ trackBlockSize };
Floats buffer2{ trackBlockSize };
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
auto originalLen = len;
auto currentSample = start;
@ -632,7 +633,8 @@ bool EffectEqualization48x::ProcessOne1x(int count, WaveTrack * t,
auto trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0);
int subBufferSize=mBufferCount==8?(mSubBufferSize>>1):mSubBufferSize; // half the buffers if avx is active
@ -818,7 +820,8 @@ bool EffectEqualization48x::ProcessOne4x(int count, WaveTrack * t,
auto trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0);
auto bigRuns = len/(subBufferSize-mBlockSize);
@ -907,7 +910,8 @@ bool EffectEqualization48x::ProcessOne1x4xThreaded(int count, WaveTrack * t,
for(int i=0;i<mThreadCount;i++)
mEQWorkers[i].mProcessingType=processingType;
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
auto trackBlockSize = t->GetMaxBlockSize();
mEffectEqualization->TrackProgress(count, 0.0);
@ -1152,7 +1156,8 @@ bool EffectEqualization48x::ProcessOne8x(int count, WaveTrack * t,
auto trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0);
int bigRuns=len/(mSubBufferSize-mBlockSize);
@ -1203,7 +1208,8 @@ bool EffectEqualization48x::ProcessOne8xThreaded(int count, WaveTrack * t,
if(mThreadCount<=0 || blockCount<256) // dont do it without cores or big data
return ProcessOne4x(count, t, start, len);
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate());
auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
auto trackBlockSize = t->GetMaxBlockSize();
mEffectEqualization->TrackProgress(count, 0.0);

View File

@ -65,10 +65,7 @@ bool Generator::Process()
{
auto pProject = FindProject();
// Create a temporary track
WaveTrack::Holder tmp(
mFactory->NewWaveTrack(track->GetSampleFormat(),
track->GetRate())
);
auto tmp = track->EmptyCopy();
BeforeTrack(*track);
BeforeGenerate();

View File

@ -1317,7 +1317,7 @@ bool EffectNoiseReduction::Worker::ProcessOne
WaveTrack::Holder outputTrack;
if(!mDoProfile)
outputTrack = factory.NewWaveTrack(track->GetSampleFormat(), track->GetRate());
outputTrack = track->EmptyCopy();
auto bufferSize = track->GetMaxBlockSize();
FloatVector buffer(bufferSize);

View File

@ -534,8 +534,7 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
StartNewTrack();
if (!mDoProfile)
mOutputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),
track->GetRate());
mOutputTrack = track->EmptyCopy();
auto bufferSize = track->GetMaxBlockSize();
Floats buffer{ bufferSize };

View File

@ -336,7 +336,7 @@ bool EffectPaulstretch::ProcessOne(WaveTrack *track,double t0,double t1,int coun
(dlen - ((double)stretch_buf_size * 2.0));
amount = 1.0 + (amount - 1.0) * adjust_amount;
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate());
auto outputTrack = track->EmptyCopy();
try {
// This encloses all the allocations of buffers, including those in

View File

@ -374,11 +374,10 @@ bool EffectSBSMS::Process()
auto warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
leftTrack->GetRate());
rb.outputLeftTrack = leftTrack->EmptyCopy();
if(rightTrack)
rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
rightTrack->GetRate());
rb.outputRightTrack = rightTrack->EmptyCopy();
long pos = 0;
long outputCount = -1;

View File

@ -189,7 +189,7 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
{
mSoundTouch->setSampleRate((unsigned int)(track->GetRate()+0.5));
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(), track->GetRate());
auto outputTrack = track->EmptyCopy();
//Get the length of the buffer (as double). len is
//used simple to calculate a progress meter, so it is easier
@ -262,10 +262,8 @@ bool EffectSoundTouch::ProcessStereo(
{
mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate() + 0.5));
auto outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(),
leftTrack->GetRate());
auto outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
rightTrack->GetRate());
auto outputLeftTrack = leftTrack->EmptyCopy();
auto outputRightTrack = rightTrack->EmptyCopy();
//Get the length of the buffer (as double). len is
//used simple to calculate a progress meter, so it is easier

View File

@ -139,8 +139,8 @@ bool EffectStereoToMono::ProcessOne(int count)
Floats rightBuffer{ idealBlockLen };
bool bResult = true;
auto outTrack =
mFactory->NewWaveTrack(floatSample, mLeftTrack->GetRate());
auto outTrack = mLeftTrack->EmptyCopy();
outTrack->ConvertToSampleFormat( floatSample );
while (index < mEnd) {
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);

View File

@ -1498,15 +1498,12 @@ bool NyquistEffect::ProcessOne()
double rate = mCurTrack[0]->GetRate();
for (int i = 0; i < outChannels; i++) {
sampleFormat format = mCurTrack[i]->GetSampleFormat();
if (outChannels == (int)mCurNumChannels) {
rate = mCurTrack[i]->GetRate();
}
outputTrack[i] = mFactory->NewWaveTrack(format, rate);
if ( mCurTrack[i] )
outputTrack[i]->SetWaveColorIndex( mCurTrack[i]->GetWaveColorIndex() );
outputTrack[i] = mCurTrack[i]->EmptyCopy();
outputTrack[i]->SetRate( rate );
// Clean the initial buffer states again for the get callbacks
// -- is this really needed?

View File

@ -101,8 +101,7 @@ bool DoPasteNothingSelected(AudacityProject &project)
// Cause duplication of block files on disk, when copy is
// between projects
locker.emplace(wc);
uNewTrack = trackFactory.NewWaveTrack(
wc->GetSampleFormat(), wc->GetRate()),
uNewTrack = wc->EmptyCopy();
pNewTrack = uNewTrack.get();
},
#ifdef USE_MIDI
@ -597,8 +596,7 @@ void OnPaste(const CommandContext &context)
wt->ClearAndPaste(t0, t1, wc, true, true);
}
else {
auto tmp = trackFactory.NewWaveTrack(
wt->GetSampleFormat(), wt->GetRate());
auto tmp = wt->EmptyCopy();
tmp->InsertSilence( 0.0,
// MJS: Is this correct?
clipboard.Duration() );