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:
parent
3c65731f38
commit
73e61592aa
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user