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:
parent
06b2831d9b
commit
c2feee6cea
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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 };
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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?
|
||||||
|
@ -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() );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user