1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-09-17 16:50:26 +02:00

Sequence::Append* give strong guarantee

This commit is contained in:
Paul Licameli 2016-12-01 20:01:40 -05:00
parent 63cf80d244
commit fc0f093db7
3 changed files with 60 additions and 58 deletions

View File

@ -689,13 +689,15 @@ void Sequence::InsertSilence(sampleCount s0, sampleCount len)
Paste(s0, &sTrack);
}
bool Sequence::AppendAlias(const wxString &fullPath,
void Sequence::AppendAlias(const wxString &fullPath,
sampleCount start,
size_t len, int channel, bool useOD)
// STRONG-GUARANTEE
{
// Quick check to make sure that it doesn't overflow
if (Overflows((mNumSamples.as_double()) + ((double)len)))
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
SeqBlock newBlock(
useOD?
@ -705,16 +707,16 @@ bool Sequence::AppendAlias(const wxString &fullPath,
);
mBlock.push_back(newBlock);
mNumSamples += len;
return true;
}
bool Sequence::AppendCoded(const wxString &fName, sampleCount start,
void Sequence::AppendCoded(const wxString &fName, sampleCount start,
size_t len, int channel, int decodeType)
// STRONG-GUARANTEE
{
// Quick check to make sure that it doesn't overflow
if (Overflows((mNumSamples.as_double()) + ((double)len)))
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
SeqBlock newBlock(
mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType),
@ -722,8 +724,6 @@ bool Sequence::AppendCoded(const wxString &fName, sampleCount start,
);
mBlock.push_back(newBlock);
mNumSamples += len;
return true;
}
void Sequence::AppendBlock
@ -1518,22 +1518,32 @@ size_t Sequence::GetIdealAppendLen() const
return max - lastBlockLen;
}
bool Sequence::Append(samplePtr buffer, sampleFormat format,
void Sequence::Append(samplePtr buffer, sampleFormat format,
size_t len, XMLWriter* blockFileLog /*=NULL*/)
// STRONG-GUARANTEE
{
if (len == 0)
return;
// Quick check to make sure that it doesn't overflow
if (Overflows(mNumSamples.as_double() + ((double)len)))
return false;
//THROW_INCONSISTENCY_EXCEPTION
;
BlockArray newBlock;
sampleCount newNumSamples = mNumSamples;
// If the last block is not full, we need to add samples to it
int numBlocks = mBlock.size();
SeqBlock *pLastBlock;
decltype(pLastBlock->f->GetLength()) length;
SampleBuffer buffer2(mMaxSamples, mSampleFormat);
bool replaceLast = false;
if (numBlocks > 0 &&
(length =
(pLastBlock = &mBlock.back())->f->GetLength()) < mMinSamples) {
SeqBlock &lastBlock = *pLastBlock;
// Enlarge a sub-minimum block at the end
const SeqBlock &lastBlock = *pLastBlock;
const auto addLen = std::min(mMaxSamples - length, len);
Read(buffer2.ptr(), mSampleFormat, lastBlock, 0, length, true);
@ -1544,11 +1554,13 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
mSampleFormat,
addLen);
const int newLastBlockLen = length + addLen;
const auto newLastBlockLen = length + addLen;
SeqBlock newLastBlock(
mDirManager->NewSimpleBlockFile(buffer2.ptr(), newLastBlockLen, mSampleFormat,
blockFileLog != NULL),
mDirManager->NewSimpleBlockFile(
buffer2.ptr(), newLastBlockLen, mSampleFormat,
blockFileLog != NULL
),
lastBlock.start
);
@ -1557,46 +1569,49 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format,
static_cast< SimpleBlockFile * >( &*newLastBlock.f )
->SaveXML( *blockFileLog );
lastBlock = newLastBlock;
newBlock.push_back( newLastBlock );
len -= addLen;
mNumSamples += addLen;
newNumSamples += addLen;
buffer += addLen * SAMPLE_SIZE(format);
replaceLast = true;
}
// Append the rest as NEW blocks
while (len) {
const auto idealSamples = GetIdealBlockSize();
const auto l = std::min(idealSamples, len);
const auto addedLen = std::min(idealSamples, len);
BlockFilePtr pFile;
if (format == mSampleFormat) {
pFile = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat,
blockFileLog != NULL);
pFile = mDirManager->NewSimpleBlockFile(
buffer, addedLen, mSampleFormat, blockFileLog != NULL);
}
else {
CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, l);
pFile = mDirManager->NewSimpleBlockFile(buffer2.ptr(), l, mSampleFormat,
blockFileLog != NULL);
CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, addedLen);
pFile = mDirManager->NewSimpleBlockFile(
buffer2.ptr(), addedLen, mSampleFormat, blockFileLog != NULL);
}
if (blockFileLog)
// shouldn't throw, because XMLWriter is not XMLFileWriter
static_cast< SimpleBlockFile * >( &*pFile )->SaveXML( *blockFileLog );
mBlock.push_back(SeqBlock(pFile, mNumSamples));
newBlock.push_back(SeqBlock(pFile, mNumSamples));
buffer += l * SAMPLE_SIZE(format);
mNumSamples += l;
len -= l;
buffer += addedLen * SAMPLE_SIZE(format);
newNumSamples += addedLen;
len -= addedLen;
}
AppendBlocksIfConsistent(newBlock, replaceLast,
newNumSamples, wxT("Append"));
// JKC: During generate we use Append again and again.
// If generating a long sequence this test would give O(n^2)
// performance - not good!
#ifdef VERY_SLOW_CHECKING
ConsistencyCheck(wxT("Append"));
#endif
return true;
}
void Sequence::Blockify

View File

@ -107,14 +107,14 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
void Paste(sampleCount s0, const Sequence *src);
size_t GetIdealAppendLen() const;
bool Append(samplePtr buffer, sampleFormat format, size_t len,
void Append(samplePtr buffer, sampleFormat format, size_t len,
XMLWriter* blockFileLog=NULL);
void Delete(sampleCount start, sampleCount len);
bool AppendAlias(const wxString &fullPath,
void AppendAlias(const wxString &fullPath,
sampleCount start,
size_t len, int channel, bool useOD);
bool AppendCoded(const wxString &fName, sampleCount start,
void AppendCoded(const wxString &fName, sampleCount start,
size_t len, int channel, int decodeType);
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.

View File

@ -1403,13 +1403,10 @@ void WaveClip::Append(samplePtr buffer, sampleFormat format,
for(;;) {
if (mAppendBufferLen >= blockSize) {
bool success =
// flush some previously appended contents
// use STRONG-GUARANTEE
mSequence->Append(mAppendBuffer.ptr(), seqFormat, blockSize,
blockFileLog);
if (!success)
return;
// flush some previously appended contents
// use STRONG-GUARANTEE
mSequence->Append(mAppendBuffer.ptr(), seqFormat, blockSize,
blockFileLog);
// use NOFAIL-GUARANTEE for rest of this "if"
memmove(mAppendBuffer.ptr(),
@ -1444,14 +1441,11 @@ void WaveClip::AppendAlias(const wxString &fName, sampleCount start,
// STRONG-GUARANTEE
{
// use STRONG-GUARANTEE
bool result = mSequence->AppendAlias(fName, start, len, channel,useOD);
mSequence->AppendAlias(fName, start, len, channel,useOD);
// use NOFAIL-GUARANTEE
if (result)
{
UpdateEnvelopeTrackLen();
MarkChanged();
}
UpdateEnvelopeTrackLen();
MarkChanged();
}
void WaveClip::AppendCoded(const wxString &fName, sampleCount start,
@ -1459,14 +1453,11 @@ void WaveClip::AppendCoded(const wxString &fName, sampleCount start,
// STRONG-GUARANTEE
{
// use STRONG-GUARANTEE
bool result = mSequence->AppendCoded(fName, start, len, channel, decodeType);
mSequence->AppendCoded(fName, start, len, channel, decodeType);
// use NOFAIL-GUARANTEE
if (result)
{
UpdateEnvelopeTrackLen();
MarkChanged();
}
UpdateEnvelopeTrackLen();
MarkChanged();
}
void WaveClip::Flush()
@ -1479,7 +1470,6 @@ void WaveClip::Flush()
//wxLogDebug(wxT(" mAppendBufferLen=%lli"), (long long) mAppendBufferLen);
//wxLogDebug(wxT(" previous sample count %lli"), (long long) mSequence->GetNumSamples());
bool success = true;
if (mAppendBufferLen > 0) {
auto cleanup = finally( [&] {
@ -1492,7 +1482,8 @@ void WaveClip::Flush()
MarkChanged();
} );
success = mSequence->Append(mAppendBuffer.ptr(), mSequence->GetSampleFormat(), mAppendBufferLen);
mSequence->Append(mAppendBuffer.ptr(), mSequence->GetSampleFormat(),
mAppendBufferLen);
}
//wxLogDebug(wxT("now sample count %lli"), (long long) mSequence->GetNumSamples());
@ -1904,12 +1895,8 @@ void WaveClip::Resample(int rate, ProgressDialog *progress)
break;
}
if (!newSequence->Append((samplePtr)outBuffer.get(), floatSample,
outGenerated))
{
error = true;
break;
}
newSequence->Append((samplePtr)outBuffer.get(), floatSample,
outGenerated);
if (progress)
{