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

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 a9658e6ef7f7eaefce4dc37a93d389cca7705f41
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 // Pad the recording track with silence, up to the
// maximum time. // maximum time.
auto newTrack = TrackFactory::Get( *p ).NewWaveTrack(); auto newTrack = pending->EmptyCopy();
newTrack->InsertSilence(0.0, t0 - endTime); newTrack->InsertSilence(0.0, t0 - endTime);
newTrack->Flush(); newTrack->Flush();
pending->Clear(endTime, t0); 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 Track::Holder WaveTrack::Copy(double t0, double t1, bool forClipboard) const
{ {
if (t1 < t0) if (t1 < t0)
THROW_INCONSISTENCY_EXCEPTION; THROW_INCONSISTENCY_EXCEPTION;
auto result = std::make_shared<WaveTrack>( mDirManager, mFormat, mRate ); auto result = EmptyCopy();
WaveTrack *newTrack = result.get(); WaveTrack *newTrack = result.get();
newTrack->Init(*this);
// PRL: Why shouldn't cutlines be copied and pasted too? I don't know, but // 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 // that was the old behavior. But this function is also used by the
// Duplicate command and I changed its behavior in that case. // 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; 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, // If forClipboard is true,
// and there is no clip at the end time of the selection, then the result // 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 // 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 // initialization, per examples of Mixer::Mixer and
// EffectSoundTouch::ProcessOne // EffectSoundTouch::ProcessOne
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),
track->GetRate()); auto outputTrack = track->EmptyCopy();
//Get the length of the selection (as double). len is //Get the length of the selection (as double). len is
//used simple to calculate a progress meter, so it is easier //used simple to calculate a progress meter, so it is easier

View File

@ -1613,13 +1613,10 @@ bool Effect::ProcessTrack(int count,
cleared = true; cleared = true;
// Create temporary tracks // Create temporary tracks
genLeft = mFactory->NewWaveTrack(left->GetSampleFormat(), left->GetRate()); genLeft = left->EmptyCopy();
genLeft->SetWaveColorIndex( left->GetWaveColorIndex() );
if (right) { if (right)
genRight = mFactory->NewWaveTrack(right->GetSampleFormat(), right->GetRate()); genRight = right->EmptyCopy();
genRight->SetWaveColorIndex( right->GetWaveColorIndex() );
}
} }
// Call the effect until we run out of input or delayed samples // 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) sampleCount start, sampleCount len)
{ {
// create a NEW WaveTrack to hold all of the output, including 'tails' each end // 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); wxASSERT(mM - 1 < windowSize);
size_t L = windowSize - (mM - 1); //Process L samples at a go 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 buffer1{ trackBlockSize };
Floats buffer2{ trackBlockSize }; Floats buffer2{ trackBlockSize };
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate()); auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
auto originalLen = len; auto originalLen = len;
auto currentSample = start; auto currentSample = start;
@ -632,7 +633,8 @@ bool EffectEqualization48x::ProcessOne1x(int count, WaveTrack * t,
auto trackBlockSize = t->GetMaxBlockSize(); auto trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate()); auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0); mEffectEqualization->TrackProgress(count, 0.0);
int subBufferSize=mBufferCount==8?(mSubBufferSize>>1):mSubBufferSize; // half the buffers if avx is active 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 trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate()); auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0); mEffectEqualization->TrackProgress(count, 0.0);
auto bigRuns = len/(subBufferSize-mBlockSize); auto bigRuns = len/(subBufferSize-mBlockSize);
@ -907,7 +910,8 @@ bool EffectEqualization48x::ProcessOne1x4xThreaded(int count, WaveTrack * t,
for(int i=0;i<mThreadCount;i++) for(int i=0;i<mThreadCount;i++)
mEQWorkers[i].mProcessingType=processingType; mEQWorkers[i].mProcessingType=processingType;
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate()); auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
auto trackBlockSize = t->GetMaxBlockSize(); auto trackBlockSize = t->GetMaxBlockSize();
mEffectEqualization->TrackProgress(count, 0.0); mEffectEqualization->TrackProgress(count, 0.0);
@ -1152,7 +1156,8 @@ bool EffectEqualization48x::ProcessOne8x(int count, WaveTrack * t,
auto trackBlockSize = t->GetMaxBlockSize(); auto trackBlockSize = t->GetMaxBlockSize();
auto output = mEffectEqualization->mFactory->NewWaveTrack(floatSample, t->GetRate()); auto output = t->EmptyCopy();
t->ConvertToSampleFormat( floatSample );
mEffectEqualization->TrackProgress(count, 0.0); mEffectEqualization->TrackProgress(count, 0.0);
int bigRuns=len/(mSubBufferSize-mBlockSize); 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 if(mThreadCount<=0 || blockCount<256) // dont do it without cores or big data
return ProcessOne4x(count, t, start, len); 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(); auto trackBlockSize = t->GetMaxBlockSize();
mEffectEqualization->TrackProgress(count, 0.0); mEffectEqualization->TrackProgress(count, 0.0);

View File

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

View File

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

View File

@ -534,8 +534,7 @@ bool EffectNoiseRemoval::ProcessOne(int count, WaveTrack * track,
StartNewTrack(); StartNewTrack();
if (!mDoProfile) if (!mDoProfile)
mOutputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(), mOutputTrack = track->EmptyCopy();
track->GetRate());
auto bufferSize = track->GetMaxBlockSize(); auto bufferSize = track->GetMaxBlockSize();
Floats buffer{ bufferSize }; 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)); (dlen - ((double)stretch_buf_size * 2.0));
amount = 1.0 + (amount - 1.0) * adjust_amount; amount = 1.0 + (amount - 1.0) * adjust_amount;
auto outputTrack = mFactory->NewWaveTrack(track->GetSampleFormat(),track->GetRate()); auto outputTrack = track->EmptyCopy();
try { try {
// This encloses all the allocations of buffers, including those in // 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); auto warper = createTimeWarper(mCurT0,mCurT1,maxDuration,rateStart,rateEnd,rateSlideType);
rb.outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(), rb.outputLeftTrack = leftTrack->EmptyCopy();
leftTrack->GetRate());
if(rightTrack) if(rightTrack)
rb.outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(), rb.outputRightTrack = rightTrack->EmptyCopy();
rightTrack->GetRate());
long pos = 0; long pos = 0;
long outputCount = -1; long outputCount = -1;

View File

@ -189,7 +189,7 @@ bool EffectSoundTouch::ProcessOne(WaveTrack *track,
{ {
mSoundTouch->setSampleRate((unsigned int)(track->GetRate()+0.5)); 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 //Get the length of the buffer (as double). len is
//used simple to calculate a progress meter, so it is easier //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)); mSoundTouch->setSampleRate((unsigned int)(leftTrack->GetRate() + 0.5));
auto outputLeftTrack = mFactory->NewWaveTrack(leftTrack->GetSampleFormat(), auto outputLeftTrack = leftTrack->EmptyCopy();
leftTrack->GetRate()); auto outputRightTrack = rightTrack->EmptyCopy();
auto outputRightTrack = mFactory->NewWaveTrack(rightTrack->GetSampleFormat(),
rightTrack->GetRate());
//Get the length of the buffer (as double). len is //Get the length of the buffer (as double). len is
//used simple to calculate a progress meter, so it is easier //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 }; Floats rightBuffer{ idealBlockLen };
bool bResult = true; bool bResult = true;
auto outTrack = auto outTrack = mLeftTrack->EmptyCopy();
mFactory->NewWaveTrack(floatSample, mLeftTrack->GetRate()); outTrack->ConvertToSampleFormat( floatSample );
while (index < mEnd) { while (index < mEnd) {
bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen); bResult &= mLeftTrack->Get((samplePtr)leftBuffer.get(), floatSample, index, idealBlockLen);

View File

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

View File

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