1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-23 07:58:05 +02:00

Sequence::ConvertToSampleFormat gives strong guarantee

This commit is contained in:
Paul Licameli 2016-11-28 10:15:34 -05:00
parent 3c65731f38
commit 73e61592aa
3 changed files with 34 additions and 53 deletions

View File

@ -129,19 +129,16 @@ bool Sequence::SetSampleFormat(sampleFormat format)
}
*/
bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
bool Sequence::ConvertToSampleFormat(sampleFormat format)
// STRONG-GUARANTEE
{
wxASSERT(pbChanged);
*pbChanged = false;
// Caller should check this no-change case before calling; we ignore it here.
if (format == mSampleFormat)
return true;
// no change
return false;
if (mBlock.size() == 0)
{
mSampleFormat = format;
*pbChanged = true;
return true;
}
@ -153,25 +150,32 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
mMinSamples = sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2;
mMaxSamples = mMinSamples * 2;
BlockArray newBlockArray;
// Use the ratio of old to NEW mMaxSamples to make a reasonable guess at allocation.
newBlockArray.reserve(1 + mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples));
bool bSuccess = false;
auto cleanup = finally( [&] {
if (!bSuccess) {
// Conversion failed. Revert these member vars.
mSampleFormat = oldFormat;
mMaxSamples = oldMaxSamples;
mMinSamples = oldMinSamples;
}
} );
BlockArray newBlockArray;
// Use the ratio of old to NEW mMaxSamples to make a reasonable guess
// at allocation.
newBlockArray.reserve
(1 + mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples));
bool bSuccess = true;
{
SampleBuffer bufferOld(oldMaxSamples, oldFormat);
SampleBuffer bufferNew(oldMaxSamples, format);
for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++)
for (size_t i = 0, nn = mBlock.size(); i < nn; i++)
{
SeqBlock &oldSeqBlock = mBlock[i];
const auto &oldBlockFile = oldSeqBlock.f;
const auto len = oldBlockFile->GetLength();
bSuccess = (oldBlockFile->ReadData(bufferOld.ptr(), oldFormat, 0, len) > 0);
if (!bSuccess)
break;
Read(bufferOld.ptr(), oldFormat, oldSeqBlock, 0, len, true);
CopySamples(bufferOld.ptr(), oldFormat, bufferNew.ptr(), format, len);
@ -189,42 +193,20 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged)
const unsigned prevSize = newBlockArray.size();
Blockify(*mDirManager, mMaxSamples, mSampleFormat,
newBlockArray, blockstart, bufferNew.ptr(), len);
bSuccess = (newBlockArray.size() > prevSize);
if (bSuccess)
*pbChanged = true;
}
}
if (bSuccess)
{
// Invalidate all the old, non-aliased block files.
// Aliased files will be converted at save, per comment above.
// Invalidate all the old, non-aliased block files.
// Aliased files will be converted at save, per comment above.
// Replace with NEW blocks.
mBlock.swap(newBlockArray);
}
else
{
/* vvvvv We *should do the following, but TrackPanel::OnFormatChange() doesn't actually check the conversion results,
it just assumes the conversion was successful.
TODO: Uncomment this section when TrackPanel::OnFormatChange() is upgraded to check the results.
// Commit the changes to block file array
CommitChangesIfConsistent
(newBlockArray, mNumSamples, wxT("Sequence::ConvertToSampleFormat()"));
PRL: I don't understand why the comment above justifies leaving the sequence in an inconsistent state.
If this function must fail, better to leave it as a no-op on this sequence. I am uncommenting the
lines below, and adding one to revert mMinSamples too.
*/
// Commit the other changes
bSuccess = true;
// Conversion failed. Revert these member vars.
mSampleFormat = oldFormat;
mMaxSamples = oldMaxSamples;
mMinSamples = oldMinSamples;
*pbChanged = false; // Revert overall change flag, in case we had some partial success in the loop.
}
ConsistencyCheck(wxT("Sequence::ConvertToSampleFormat()"));
return bSuccess;
return true;
}
std::pair<float, float> Sequence::GetMinMax(

View File

@ -162,8 +162,9 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
//
sampleFormat GetSampleFormat() const;
// bool SetSampleFormat(sampleFormat format);
bool ConvertToSampleFormat(sampleFormat format, bool* pbChanged);
// Return true iff there is a change
bool ConvertToSampleFormat(sampleFormat format);
//
// Retrieving summary info

View File

@ -1342,11 +1342,9 @@ void WaveClip::ConvertToSampleFormat(sampleFormat format)
// Note: it is not necessary to do this recursively to cutlines.
// They get converted as needed when they are expanded.
bool bChanged;
bool bResult = mSequence->ConvertToSampleFormat(format, &bChanged);
if (bResult && bChanged)
auto bChanged = mSequence->ConvertToSampleFormat(format);
if (bChanged)
MarkChanged();
wxASSERT(bResult); // TODO: Throw an actual error.
}
void WaveClip::UpdateEnvelopeTrackLen()