1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 23:59:37 +02:00

Bug2532: should preserve sharing of sample blocks when importing AUP (#651)

This commit is contained in:
Paul Licameli 2020-08-30 18:18:18 -04:00 committed by GitHub
parent c17b804750
commit 7294f7a8e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 15 deletions

View File

@ -1470,11 +1470,51 @@ size_t Sequence::GetIdealAppendLen() const
return max - lastBlockLen;
}
/*! @excsafety{Strong} */
SeqBlock::SampleBlockPtr Sequence::AppendNewBlock(
samplePtr buffer, sampleFormat format, size_t len)
{
return DoAppend( buffer, format, len, false );
}
/*! @excsafety{Strong} */
void Sequence::AppendSharedBlock(const SeqBlock::SampleBlockPtr &pBlock)
{
auto len = pBlock->GetSampleCount();
// Quick check to make sure that it doesn't overflow
if (Overflows(mNumSamples.as_double() + ((double)len)))
THROW_INCONSISTENCY_EXCEPTION;
BlockArray newBlock;
newBlock.emplace_back( pBlock, mNumSamples );
auto newNumSamples = mNumSamples + len;
AppendBlocksIfConsistent(newBlock, false,
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
}
/*! @excsafety{Strong} */
void Sequence::Append(samplePtr buffer, sampleFormat format, size_t len)
{
DoAppend(buffer, format, len, true);
}
/*! @excsafety{Strong} */
SeqBlock::SampleBlockPtr Sequence::DoAppend(
samplePtr buffer, sampleFormat format, size_t len, bool coalesce)
{
SeqBlock::SampleBlockPtr result;
if (len == 0)
return;
return result;
auto &factory = *mpFactory;
@ -1492,7 +1532,8 @@ void Sequence::Append(samplePtr buffer, sampleFormat format, size_t len)
size_t bufferSize = mMaxSamples;
SampleBuffer buffer2(bufferSize, mSampleFormat);
bool replaceLast = false;
if (numBlocks > 0 &&
if (coalesce &&
numBlocks > 0 &&
(length =
(pLastBlock = &mBlock.back())->sb->GetSampleCount()) < mMinSamples) {
// Enlarge a sub-minimum block at the end
@ -1529,6 +1570,10 @@ void Sequence::Append(samplePtr buffer, sampleFormat format, size_t len)
SampleBlockPtr pBlock;
if (format == mSampleFormat) {
pBlock = factory.Create(buffer, addedLen, mSampleFormat);
// It's expected that when not requesting coalescence, the
// data should fit in one block
wxASSERT( coalesce || !result );
result = pBlock;
}
else {
CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, addedLen);
@ -1551,6 +1596,8 @@ void Sequence::Append(samplePtr buffer, sampleFormat format, size_t len)
#ifdef VERY_SLOW_CHECKING
ConsistencyCheck(wxT("Append"));
#endif
return result;
}
void Sequence::Blockify(SampleBlockFactory &factory,

View File

@ -103,6 +103,11 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
size_t GetIdealAppendLen() const;
void Append(samplePtr buffer, sampleFormat format, size_t len);
//! Append data, not coalescing blocks, returning a pointer to the new block.
SeqBlock::SampleBlockPtr AppendNewBlock(samplePtr buffer, sampleFormat format, size_t len);
//! Append a complete block, not coalescing
void AppendSharedBlock(const SeqBlock::SampleBlockPtr &pBlock);
void Delete(sampleCount start, sampleCount len);
void SetSilence(sampleCount s0, sampleCount len);
@ -196,6 +201,9 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
int FindBlock(sampleCount pos) const;
SeqBlock::SampleBlockPtr DoAppend(
samplePtr buffer, sampleFormat format, size_t len, bool coalesce);
static void AppendBlock(SampleBlockFactory *pFactory, sampleFormat format,
BlockArray &blocks,
sampleCount &numSamples,

View File

@ -1202,6 +1202,19 @@ void WaveClip::GetDisplayRect(wxRect* r)
*r = mDisplayRect;
}
/*! @excsafety{Strong} */
std::shared_ptr<SampleBlock> WaveClip::AppendNewBlock(
samplePtr buffer, sampleFormat format, size_t len)
{
return mSequence->AppendNewBlock( buffer, format, len );
}
/*! @excsafety{Strong} */
void WaveClip::AppendSharedBlock(const std::shared_ptr<SampleBlock> &pBlock)
{
mSequence->AppendSharedBlock( pBlock );
}
/*! @excsafety{Partial}
-- Some prefix (maybe none) of the buffer is appended,
and no content already flushed to disk is lost. */

View File

@ -26,6 +26,7 @@
class BlockArray;
class Envelope;
class ProgressDialog;
class SampleBlock;
class SampleBlockFactory;
using SampleBlockFactoryPtr = std::shared_ptr<SampleBlockFactory>;
class Sequence;
@ -280,6 +281,13 @@ public:
* function to tell the envelope about it. */
void UpdateEnvelopeTrackLen();
//! For use in importing pre-version-3 projects to preserve sharing of blocks
std::shared_ptr<SampleBlock> AppendNewBlock(
samplePtr buffer, sampleFormat format, size_t len);
//! For use in importing pre-version-3 projects to preserve sharing of blocks
void AppendSharedBlock(const std::shared_ptr<SampleBlock> &pBlock);
/// You must call Flush after the last Append
/// @return true if at least one complete block was created
bool Append(samplePtr buffer, sampleFormat format,

View File

@ -196,7 +196,8 @@ private:
const wxChar **mAttrs;
wxFileName mProjDir;
using BlockFileMap = std::map<wxString, FilePath>;
using BlockFileMap =
std::map<wxString, std::pair<FilePath, std::shared_ptr<SampleBlock>>>;
BlockFileMap mFileMap;
ListOfTracks mTracks;
@ -774,10 +775,9 @@ bool AUPImportFileHandle::HandleProject(XMLTagHandler *&handler)
&files,
"*.*");
for (size_t i = 0; i < cnt; ++i)
for (const auto &fn : files)
{
FilePath fn = files[i];
mFileMap[wxFileNameFromPath(fn)] = fn;
mFileMap[wxFileNameFromPath(fn)] = {fn, {}};
}
}
else if (!wxStrcmp(attr, wxT("rate")))
@ -1199,7 +1199,7 @@ bool AUPImportFileHandle::HandleSimpleBlockFile(XMLTagHandler *&handler)
{
if (mFileMap.find(strValue) != mFileMap.end())
{
filename = mFileMap[strValue];
filename = mFileMap[strValue].first;
}
else
{
@ -1387,6 +1387,14 @@ bool AUPImportFileHandle::AddSamples(const FilePath &filename,
sampleCount origin /* = 0 */,
int channel /* = 0 */)
{
auto pClip = mClip ? mClip : mWaveTrack->RightmostOrNewClip();
auto &pBlock = mFileMap[wxFileNameFromPath(filename)].second;
if (pBlock) {
// Replicate the sharing of blocks
pClip->AppendSharedBlock( pBlock );
return true;
}
// Third party library has its own type alias, check it before
// adding origin + size_t
static_assert(sizeof(sampleCount::type) <= sizeof(sf_count_t),
@ -1533,15 +1541,9 @@ bool AUPImportFileHandle::AddSamples(const FilePath &filename,
wxASSERT(mClip || mWaveTrack);
// Add the samples to the clip/track
if (mClip)
if (pClip)
{
mClip->Append(bufptr, format, cnt);
mClip->Flush();
}
else if (mWaveTrack)
{
mWaveTrack->Append(bufptr, format, cnt);
mWaveTrack->Flush();
pBlock = pClip->AppendNewBlock(bufptr, format, cnt);
}
// Let the finally block know everything is good