From 38ba19183d3f86617ec3b8fa90774e77ece2bf82 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Fri, 29 Jan 2016 11:12:56 -0500 Subject: [PATCH 01/16] One less indirection accessing SeqBlock --- src/AutoRecovery.cpp | 8 +- src/Dependencies.cpp | 18 +- src/DirManager.cpp | 20 +- src/DirManager.h | 10 +- src/Project.cpp | 6 +- src/Sequence.cpp | 714 +++++++++++++------------- src/Sequence.h | 24 +- src/UndoManager.cpp | 4 +- src/ondemand/ODComputeSummaryTask.cpp | 17 +- src/ondemand/ODDecodeTask.cpp | 18 +- 10 files changed, 432 insertions(+), 407 deletions(-) diff --git a/src/AutoRecovery.cpp b/src/AutoRecovery.cpp index 8a68ecfaf..dd193c356 100644 --- a/src/AutoRecovery.cpp +++ b/src/AutoRecovery.cpp @@ -326,10 +326,14 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, Sequence* seq = clip->GetSequence(); // Load the blockfile from the XML - BlockFile* blockFile = NULL; DirManager* dirManager = mProject->GetDirManager(); dirManager->SetLoadingFormat(seq->GetSampleFormat()); - dirManager->SetLoadingTarget(&blockFile); + + BlockArray array; + array.resize(1); + dirManager->SetLoadingTarget(&array, 0); + BlockFile *& blockFile = array[0].f; + if (!dirManager->HandleXMLTag(tag, attrs) || !blockFile) { // This should only happen if there is a bug diff --git a/src/Dependencies.cpp b/src/Dependencies.cpp index 77cf4fce9..c6d6f73c7 100644 --- a/src/Dependencies.cpp +++ b/src/Dependencies.cpp @@ -60,7 +60,7 @@ WX_DECLARE_HASH_MAP(BlockFile *, bool, // in the current set of tracks. Enumerating that array allows // you to process all block files in the current set. static void GetAllSeqBlocks(AudacityProject *project, - BlockArray *outBlocks) + BlockPtrArray *outBlocks) { TrackList *tracks = project->GetTracks(); TrackListIterator iter(tracks); @@ -74,8 +74,8 @@ static void GetAllSeqBlocks(AudacityProject *project, Sequence *sequence = clip->GetSequence(); BlockArray *blocks = sequence->GetBlockArray(); int i; - for (i = 0; i < (int)blocks->GetCount(); i++) - outBlocks->Add(blocks->Item(i)); + for (i = 0; i < (int)blocks->size(); i++) + outBlocks->push_back(&blocks->at(i)); node = node->GetNext(); } } @@ -92,11 +92,11 @@ static void ReplaceBlockFiles(AudacityProject *project, ReplacedBlockFileHash &hash) { DirManager *dirManager = project->GetDirManager(); - BlockArray blocks; + BlockPtrArray blocks; GetAllSeqBlocks(project, &blocks); int i; - for (i = 0; i < (int)blocks.GetCount(); i++) { + for (i = 0; i < (int)blocks.size(); i++) { if (hash.count(blocks[i]->f) > 0) { BlockFile *src = blocks[i]->f; BlockFile *dst = hash[src]; @@ -114,14 +114,14 @@ void FindDependencies(AudacityProject *project, { sampleFormat format = project->GetDefaultFormat(); - BlockArray blocks; + BlockPtrArray blocks; GetAllSeqBlocks(project, &blocks); AliasedFileHash aliasedFileHash; BoolBlockFileHash blockFileHash; int i; - for (i = 0; i < (int)blocks.GetCount(); i++) { + for (i = 0; i < (int)blocks.size(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { @@ -181,13 +181,13 @@ static void RemoveDependencies(AudacityProject *project, aliasedFileHash[fileNameStr] = &aliasedFiles->Item(i); } - BlockArray blocks; + BlockPtrArray blocks; GetAllSeqBlocks(project, &blocks); const sampleFormat format = project->GetDefaultFormat(); ReplacedBlockFileHash blockFileHash; wxLongLong completedBytes = 0; - for (i = 0; i < blocks.GetCount(); i++) { + for (i = 0; i < blocks.size(); i++) { BlockFile *f = blocks[i]->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { diff --git a/src/DirManager.cpp b/src/DirManager.cpp index 847df38c8..df16bb4b5 100644 --- a/src/DirManager.cpp +++ b/src/DirManager.cpp @@ -98,6 +98,7 @@ #include "Internat.h" #include "Project.h" #include "Prefs.h" +#include "Sequence.h" #include "widgets/Warning.h" #include "widgets/MultiDialog.h" @@ -349,6 +350,7 @@ DirManager::DirManager() projName = wxT(""); mLoadingTarget = NULL; + mLoadingTargetIdx = 0; mMaxSamples = -1; // toplevel pool hash is fully populated to begin @@ -1009,10 +1011,12 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs) BlockFile* pBlockFile = NULL; - if( !wxStricmp(tag, wxT("silentblockfile")) ) { + BlockFile *&target = mLoadingTarget->at(mLoadingTargetIdx).f; + + if (!wxStricmp(tag, wxT("silentblockfile"))) { // Silent blocks don't actually have a file associated, so // we don't need to worry about the hash table at all - *mLoadingTarget = SilentBlockFile::BuildFromXML(*this, attrs); + target = SilentBlockFile::BuildFromXML(*this, attrs); return true; } else if ( !wxStricmp(tag, wxT("simpleblockfile")) ) @@ -1074,7 +1078,7 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs) return false; } else - *mLoadingTarget = pBlockFile; + target = pBlockFile; // // If the block we loaded is already in the hash table, then the @@ -1082,21 +1086,21 @@ bool DirManager::HandleXMLTag(const wxChar *tag, const wxChar **attrs) // return a reference to the existing object instead. // - wxString name = (*mLoadingTarget)->GetFileName().GetName(); + wxString name = target->GetFileName().GetName(); BlockFile *retrieved = mBlockFileHash[name]; if (retrieved) { // Lock it in order to delete it safely, i.e. without having // it delete the file, too... - (*mLoadingTarget)->Lock(); - delete (*mLoadingTarget); + target->Lock(); + delete target; Ref(retrieved); // Add one to its reference count - *mLoadingTarget = retrieved; + target = retrieved; return true; } // This is a new object - mBlockFileHash[name]=*mLoadingTarget; + mBlockFileHash[name] = target; // MakeBlockFileName wasn't used so we must add the directory // balancing information BalanceInfoAdd(name); diff --git a/src/DirManager.h b/src/DirManager.h index dc8af0fc8..9c0330844 100644 --- a/src/DirManager.h +++ b/src/DirManager.h @@ -21,6 +21,7 @@ #include "xml/XMLTagHandler.h" class wxHashTable; +class BlockArray; class BlockFile; class SequenceTest; @@ -101,7 +102,11 @@ class DirManager: public XMLTagHandler { // For debugging only int GetRefCount(BlockFile * f); - void SetLoadingTarget(BlockFile **target) { mLoadingTarget = target; } + void SetLoadingTarget(BlockArray *pArray, unsigned idx) + { + mLoadingTarget = pArray; + mLoadingTargetIdx = idx; + } void SetLoadingFormat(sampleFormat format) { mLoadingFormat = format; } void SetLoadingBlockLength(sampleCount len) { mLoadingBlockLen = len; } void SetMaxSamples(sampleCount max) { mMaxSamples = max; } @@ -186,7 +191,8 @@ class DirManager: public XMLTagHandler { wxArrayString aliasList; - BlockFile **mLoadingTarget; + BlockArray *mLoadingTarget; + unsigned mLoadingTargetIdx; sampleFormat mLoadingFormat; sampleCount mLoadingBlockLen; diff --git a/src/Project.cpp b/src/Project.cpp index 9df141fe3..0f8409b3e 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -3737,10 +3737,10 @@ void AudacityProject::AddImportedTracks(wxString fileName, if (newTracks[i]->GetKind() == WaveTrack::Wave) { WaveClip* clip = ((WaveTrack*)newTracks[i])->GetClipByIndex(0); - if (clip && clip->GetSequence()->GetBlockArray()->GetCount()) + if (clip && clip->GetSequence()->GetBlockArray()->size()) { - SeqBlock* block = clip->GetSequence()->GetBlockArray()->Item(0); - if (block->f->IsAlias()) + SeqBlock& block = clip->GetSequence()->GetBlockArray()->at(0); + if (block.f->IsAlias()) { mImportedDependencies = true; } diff --git a/src/Sequence.cpp b/src/Sequence.cpp index e84cdf942..24bfd49fb 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -88,10 +88,10 @@ Sequence::Sequence(const Sequence &orig, DirManager *projDirManager) Sequence::~Sequence() { - for (unsigned int i = 0; i < mBlock->GetCount(); i++) { - if (mBlock->Item(i)->f) - mDirManager->Deref(mBlock->Item(i)->f); - delete mBlock->Item(i); + for (unsigned int i = 0; i < mBlock->size(); i++) { + BlockFile *const file = mBlock->at(i).f; + if (file) + mDirManager->Deref(file); } delete mBlock; @@ -110,24 +110,24 @@ sampleCount Sequence::GetIdealBlockSize() const bool Sequence::Lock() { - for (unsigned int i = 0; i < mBlock->GetCount(); i++) - mBlock->Item(i)->f->Lock(); + for (unsigned int i = 0; i < mBlock->size(); i++) + mBlock->at(i).f->Lock(); return true; } bool Sequence::CloseLock() { - for (unsigned int i = 0; i < mBlock->GetCount(); i++) - mBlock->Item(i)->f->CloseLock(); + for (unsigned int i = 0; i < mBlock->size(); i++) + mBlock->at(i).f->CloseLock(); return true; } bool Sequence::Unlock() { - for (unsigned int i = 0; i < mBlock->GetCount(); i++) - mBlock->Item(i)->f->Unlock(); + for (unsigned int i = 0; i < mBlock->size(); i++) + mBlock->at(i).f->Unlock(); return true; } @@ -139,7 +139,7 @@ sampleFormat Sequence::GetSampleFormat() const bool Sequence::SetSampleFormat(sampleFormat format) { - if (mBlock->GetCount() > 0 || mNumSamples > 0) + if (mBlock->size() > 0 || mNumSamples > 0) return false; mSampleFormat = format; @@ -155,7 +155,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) if (format == mSampleFormat) return true; - if (mBlock->GetCount() == 0) + if (mBlock->size() == 0) { mSampleFormat = format; *pbChanged = true; @@ -172,19 +172,19 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) BlockArray* pNewBlockArray = new BlockArray(); // Use the ratio of old to new mMaxSamples to make a reasonable guess at allocation. - pNewBlockArray->Alloc(mBlock->GetCount() * ((float)oldMaxSamples / (float)mMaxSamples)); + pNewBlockArray->reserve(mBlock->size() * ((float)oldMaxSamples / (float)mMaxSamples)); bool bSuccess = true; - for (size_t i = 0; (i < mBlock->GetCount() && bSuccess); i++) + for (size_t i = 0; (i < mBlock->size() && bSuccess); i++) { - SeqBlock* pOldSeqBlock = mBlock->Item(i); - BlockFile* pOldBlockFile = pOldSeqBlock->f; + SeqBlock &oldSeqBlock = mBlock->at(i); + BlockFile* oldBlockFile = oldSeqBlock.f; - sampleCount len = pOldSeqBlock->f->GetLength(); + sampleCount len = oldBlockFile->GetLength(); samplePtr bufferOld = NewSamples(len, oldFormat); samplePtr bufferNew = NewSamples(len, mSampleFormat); - bSuccess = (pOldBlockFile->ReadData(bufferOld, oldFormat, 0, len) > 0); + bSuccess = (oldBlockFile->ReadData(bufferOld, oldFormat, 0, len) > 0); if (!bSuccess) { DeleteSamples(bufferNew); @@ -205,13 +205,13 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) // Using Blockify will handle the cases where len > the new mMaxSamples. Previous code did not. BlockArray* pSplitBlockArray = Blockify(bufferNew, len); - bSuccess = (pSplitBlockArray->GetCount() > 0); + bSuccess = (pSplitBlockArray->size() > 0); if (bSuccess) { - for (size_t j = 0; j < pSplitBlockArray->GetCount(); j++) + const sampleCount blockstart = mBlock->at(i).start; + for (size_t j = 0; j < pSplitBlockArray->size(); j++) { - pSplitBlockArray->Item(j)->start += mBlock->Item(i)->start; - pNewBlockArray->Add(pSplitBlockArray->Item(j)); + pNewBlockArray->push_back(pSplitBlockArray->at(j).Plus(blockstart)); } *pbChanged = true; } @@ -225,11 +225,11 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) { // Invalidate all the old, non-aliased block files. // Aliased files will be converted at save, per comment above. - for (size_t i = 0; (i < mBlock->GetCount() && bSuccess); i++) + for (size_t i = 0; (i < mBlock->size() && bSuccess); i++) { - SeqBlock* pOldSeqBlock = mBlock->Item(i); - mDirManager->Deref(pOldSeqBlock->f); - pOldSeqBlock->f = NULL; //vvv ...so we don't delete the file when we delete mBlock, next. ANSWER-ME: Right, or delete? + BlockFile *& pOldFile = mBlock->at(i).f; + mDirManager->Deref(pOldFile); + pOldFile = NULL; //vvv ...so we don't delete the file when we delete mBlock, next. ANSWER-ME: Right, or delete? } delete mBlock; @@ -259,7 +259,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) bool Sequence::GetMinMax(sampleCount start, sampleCount len, float * outMin, float * outMax) const { - if (len == 0 || mBlock->GetCount() == 0) { + if (len == 0 || mBlock->size() == 0) { *outMin = float(0.0); // FLT_MAX? So it doesn't look like a spurious '0' to a caller? *outMax = float(0.0); // -FLT_MAX? So it doesn't look like a spurious '0' to a caller? return true; @@ -280,7 +280,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, for (b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; - mBlock->Item(b)->f->GetMinMax(&blockMin, &blockMax, &blockRMS); + mBlock->at(b).f->GetMinMax(&blockMin, &blockMax, &blockRMS); if (blockMin < min) min = blockMin; @@ -292,43 +292,51 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, // selection may only partly overlap these blocks. If the overall min/max // of either of these blocks is within min...max, then we can ignore them. // If not, we need read some samples and summaries from disk. - float block0Min, block0Max, block0RMS; - mBlock->Item(block0)->f->GetMinMax(&block0Min, &block0Max, &block0RMS); + { + float block0Min, block0Max, block0RMS; + SeqBlock &theBlock = mBlock->at(block0); + BlockFile *theFile = theBlock.f; + theFile->GetMinMax(&block0Min, &block0Max, &block0RMS); - if (block0Min < min || block0Max > max) { - s0 = start - mBlock->Item(block0)->start; - l0 = len; - maxl0 = mBlock->Item(block0)->start + mBlock->Item(block0)->f->GetLength() - start; - wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19 - if (l0 > maxl0) - l0 = maxl0; + if (block0Min < min || block0Max > max) { + s0 = start - theBlock.start; + l0 = len; + maxl0 = theBlock.start + theFile->GetLength() - start; + wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19 + if (l0 > maxl0) + l0 = maxl0; - float partialMin, partialMax, partialRMS; - mBlock->Item(block0)->f->GetMinMax(s0, l0, - &partialMin, &partialMax, &partialRMS); - if (partialMin < min) - min = partialMin; - if (partialMax > max) - max = partialMax; + float partialMin, partialMax, partialRMS; + theFile->GetMinMax(s0, l0, + &partialMin, &partialMax, &partialRMS); + if (partialMin < min) + min = partialMin; + if (partialMax > max) + max = partialMax; + } } - float block1Min, block1Max, block1RMS; - mBlock->Item(block1)->f->GetMinMax(&block1Min, &block1Max, &block1RMS); + { + float block1Min, block1Max, block1RMS; + SeqBlock &theBlock = mBlock->at(block1); + BlockFile *theFile = theBlock.f; + theFile->GetMinMax(&block1Min, &block1Max, &block1RMS); - if (block1 > block0 && - (block1Min < min || block1Max > max)) { + if (block1 > block0 && + (block1Min < min || block1Max > max)) { - s0 = 0; - l0 = (start + len) - mBlock->Item(block1)->start; - wxASSERT(l0 <= mMaxSamples); // Vaughan, 2011-10-19 + s0 = 0; + l0 = (start + len) - theBlock.start; + wxASSERT(l0 <= mMaxSamples); // Vaughan, 2011-10-19 - float partialMin, partialMax, partialRMS; - mBlock->Item(block1)->f->GetMinMax(s0, l0, - &partialMin, &partialMax, &partialRMS); - if (partialMin < min) - min = partialMin; - if (partialMax > max) - max = partialMax; + float partialMin, partialMax, partialRMS; + theFile->GetMinMax(s0, l0, + &partialMin, &partialMax, &partialRMS); + if (partialMin < min) + min = partialMin; + if (partialMax > max) + max = partialMax; + } } *outMin = min; @@ -342,7 +350,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, { // len is the number of samples that we want the rms of. // it may be longer than a block, and the code is carefully set up to handle that. - if (len == 0 || mBlock->GetCount() == 0) { + if (len == 0 || mBlock->size() == 0) { *outRMS = float(0.0); return true; } @@ -362,34 +370,44 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, for (b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; - mBlock->Item(b)->f->GetMinMax(&blockMin, &blockMax, &blockRMS); + const SeqBlock &theBlock = mBlock->at(b); + BlockFile *const theFile = theBlock.f; + theFile->GetMinMax(&blockMin, &blockMax, &blockRMS); - sumsq += blockRMS * blockRMS * mBlock->Item(b)->f->GetLength(); - length += mBlock->Item(b)->f->GetLength(); + const sampleCount fileLen = theFile->GetLength(); + sumsq += blockRMS * blockRMS * fileLen; + length += fileLen; } // Now we take the first and last blocks into account, noting that the // selection may only partly overlap these blocks. // If not, we need read some samples and summaries from disk. - s0 = start - mBlock->Item(block0)->start; - l0 = len; - maxl0 = mBlock->Item(block0)->start + mBlock->Item(block0)->f->GetLength() - start; - wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19 - if (l0 > maxl0) - l0 = maxl0; + { + const SeqBlock &theBlock = mBlock->at(block0); + BlockFile *const theFile = theBlock.f; + s0 = start - theBlock.start; + l0 = len; + maxl0 = theBlock.start + theFile->GetLength() - start; + wxASSERT(maxl0 <= mMaxSamples); // Vaughan, 2011-10-19 + if (l0 > maxl0) + l0 = maxl0; - float partialMin, partialMax, partialRMS; - mBlock->Item(block0)->f->GetMinMax(s0, l0, &partialMin, &partialMax, &partialRMS); + float partialMin, partialMax, partialRMS; + theFile->GetMinMax(s0, l0, &partialMin, &partialMax, &partialRMS); - sumsq += partialRMS * partialRMS * l0; - length += l0; + sumsq += partialRMS * partialRMS * l0; + length += l0; + } if (block1 > block0) { - s0 = 0; - l0 = (start + len) - mBlock->Item(block1)->start; + const SeqBlock &theBlock = mBlock->at(block1); + BlockFile *const theFile = theBlock.f; - mBlock->Item(block1)->f->GetMinMax(s0, l0, - &partialMin, &partialMax, &partialRMS); + s0 = 0; + l0 = (start + len) - theBlock.start; + + float partialMin, partialMax, partialRMS; + theFile->GetMinMax(s0, l0, &partialMin, &partialMax, &partialRMS); sumsq += partialRMS * partialRMS * l0; length += l0; } @@ -409,7 +427,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) if (s0 >= s1 || s0 >= mNumSamples || s1 < 0) return false; - int numBlocks = mBlock->GetCount(); + int numBlocks = mBlock->size(); int b0 = FindBlock(s0); int b1 = FindBlock(s1); @@ -424,29 +442,32 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) // Do the first block - if (b0 >= 0 && b0 < numBlocks && s0 != mBlock->Item(b0)->start) { - - blocklen = (mBlock->Item(b0)->start + mBlock->Item(b0)->f->GetLength() - s0); + if (b0 >= 0 && b0 < numBlocks && s0 != mBlock->at(b0).start) { + const SeqBlock &block = mBlock->at(b0); + BlockFile *const file = block.f; + blocklen = block.start + file->GetLength() - s0; if (blocklen > (s1 - s0)) blocklen = s1 - s0; - wxASSERT(mBlock->Item(b0)->f->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 + wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 Get(buffer, mSampleFormat, s0, blocklen); (*dest)->Append(buffer, mSampleFormat, blocklen); } - if (b0 >= 0 && b0 < numBlocks && s0 == mBlock->Item(b0)->start) { + if (b0 >= 0 && b0 < numBlocks && s0 == mBlock->at(b0).start) { b0--; } // If there are blocks in the middle, copy the blockfiles directly for (int b = b0 + 1; b < b1; b++) - ((Sequence *)*dest)->AppendBlock(mBlock->Item(b)); + (*dest)->AppendBlock(mBlock->at(b)); // Do the last block if (b1 > b0 && b1 < numBlocks) { - blocklen = (s1 - mBlock->Item(b1)->start); - wxASSERT(mBlock->Item(b1)->f->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 - Get(buffer, mSampleFormat, mBlock->Item(b1)->start, blocklen); + const SeqBlock &block = mBlock->at(b1); + BlockFile *const file = block.f; + blocklen = (s1 - block.start); + wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 + Get(buffer, mSampleFormat, block.start, blocklen); (*dest)->Append(buffer, mSampleFormat, blocklen); } @@ -489,45 +510,46 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) BlockArray *srcBlock = src->mBlock; sampleCount addedLen = src->mNumSamples; - unsigned int srcNumBlocks = srcBlock->GetCount(); + unsigned int srcNumBlocks = srcBlock->size(); int sampleSize = SAMPLE_SIZE(mSampleFormat); if (addedLen == 0 || srcNumBlocks == 0) return true; int b = FindBlock(s); - size_t numBlocks = mBlock->GetCount(); + size_t numBlocks = mBlock->size(); if (numBlocks == 0 || - (s == mNumSamples && mBlock->Item(numBlocks-1)->f->GetLength() >= mMinSamples)) { + (s == mNumSamples && mBlock->at(numBlocks-1).f->GetLength() >= mMinSamples)) { // Special case: this track is currently empty, or it's safe to append // onto the end because the current last block is longer than the // minimum size for (unsigned int i = 0; i < srcNumBlocks; i++) - AppendBlock(srcBlock->Item(i)); + AppendBlock(srcBlock->at(i)); return ConsistencyCheck(wxT("Paste branch one")); } + SeqBlock *pBlock; + sampleCount length; if ((b >= 0 ) && (b < (int)numBlocks) - && ((mBlock->Item(b)->f->GetLength() + addedLen) < mMaxSamples)) { + && (length = (pBlock = &mBlock->at(b))->f->GetLength()) + addedLen < mMaxSamples) { // Special case: we can fit all of the new samples inside of // one block! + SeqBlock &block = *pBlock; samplePtr buffer = NewSamples(mMaxSamples, mSampleFormat); - int splitPoint = s - mBlock->Item(b)->start; - Read(buffer, mSampleFormat, mBlock->Item(b), 0, splitPoint); + int splitPoint = s - block.start; + Read(buffer, mSampleFormat, block, 0, splitPoint); src->Get(buffer + splitPoint*sampleSize, mSampleFormat, 0, addedLen); Read(buffer + (splitPoint + addedLen)*sampleSize, - mSampleFormat, mBlock->Item(b), - splitPoint, mBlock->Item(b)->f->GetLength() - splitPoint); + mSampleFormat, block, + splitPoint, length - splitPoint); - SeqBlock *largerBlock = new SeqBlock(); - largerBlock->start = mBlock->Item(b)->start; - sampleCount largerBlockLen = mBlock->Item(b)->f->GetLength() + addedLen; + sampleCount largerBlockLen = length + addedLen; if (largerBlockLen > mMaxSamples) { wxLogError( @@ -536,15 +558,14 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); largerBlockLen = mMaxSamples; // Prevent overruns, per NGS report for UmixIt. } - largerBlock->f = + BlockFile *const file = mDirManager->NewSimpleBlockFile(buffer, largerBlockLen, mSampleFormat); - mDirManager->Deref(mBlock->Item(b)->f); - delete mBlock->Item(b); - mBlock->Item(b) = largerBlock; + mDirManager->Deref(block.f); + block.f = file; for (unsigned int i = b + 1; i < numBlocks; i++) - mBlock->Item(i)->start += addedLen; + mBlock->at(i).start += addedLen; mNumSamples += addedLen; @@ -558,17 +579,17 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // into one big block along with the split block, // then resplit it all BlockArray *newBlock = new BlockArray(); - newBlock->Alloc(numBlocks + srcNumBlocks + 2); + newBlock->reserve(numBlocks + srcNumBlocks + 2); int newNumBlocks = 0; for (int i = 0; i < b; i++) { - newBlock->Add(mBlock->Item(i)); + newBlock->push_back(mBlock->at(i)); newNumBlocks++; } - SeqBlock *splitBlock = mBlock->Item(b); - sampleCount splitLen = mBlock->Item(b)->f->GetLength(); - int splitPoint = s - splitBlock->start; + SeqBlock &splitBlock = mBlock->at(b); + sampleCount splitLen = splitBlock.f->GetLength(); + int splitPoint = s - splitBlock.start; unsigned int i; if (srcNumBlocks <= 4) { @@ -582,12 +603,11 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) 0, addedLen); Read(sumBuffer + (splitPoint + addedLen) * sampleSize, mSampleFormat, splitBlock, splitPoint, - splitBlock->f->GetLength() - splitPoint); + splitLen - splitPoint); BlockArray *split = Blockify(sumBuffer, sum); - for (i = 0; i < split->GetCount(); i++) { - split->Item(i)->start += splitBlock->start; - newBlock->Add(split->Item(i)); + for (i = 0; i < split->size(); i++) { + newBlock->push_back(split->at(i).Plus(splitBlock.start)); newNumBlocks++; } delete split; @@ -601,7 +621,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // half of the split block. sampleCount srcFirstTwoLen = - srcBlock->Item(0)->f->GetLength() + srcBlock->Item(1)->f->GetLength(); + srcBlock->at(0).f->GetLength() + srcBlock->at(1).f->GetLength(); sampleCount leftLen = splitPoint + srcFirstTwoLen; samplePtr leftBuffer = NewSamples(leftLen, mSampleFormat); @@ -610,39 +630,35 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) mSampleFormat, 0, srcFirstTwoLen); BlockArray *split = Blockify(leftBuffer, leftLen); - for (i = 0; i < split->GetCount(); i++) { - split->Item(i)->start += splitBlock->start; - newBlock->Add(split->Item(i)); + for (i = 0; i < split->size(); i++) { + newBlock->push_back(split->at(i).Plus(splitBlock.start)); newNumBlocks++; } delete split; DeleteSamples(leftBuffer); for (i = 2; i < srcNumBlocks - 2; i++) { - SeqBlock *insertBlock = new SeqBlock(); - insertBlock->start = srcBlock->Item(i)->start + s; - - insertBlock->f = mDirManager->CopyBlockFile(srcBlock->Item(i)->f); - if (!insertBlock->f) { + const SeqBlock &block = srcBlock->at(i); + BlockFile *const file = mDirManager->CopyBlockFile(block.f); + if (!file) { wxASSERT(false); // TODO: Handle this better, alert the user of failure. - delete insertBlock; - newBlock->Clear(); delete newBlock; return false; } - newBlock->Add(insertBlock); + newBlock->push_back(SeqBlock(file, block.start + s)); newNumBlocks++; } + const SeqBlock &penultimate = srcBlock->at(srcNumBlocks - 2); sampleCount srcLastTwoLen = - srcBlock->Item(srcNumBlocks - 2)->f->GetLength() + - srcBlock->Item(srcNumBlocks - 1)->f->GetLength(); - sampleCount rightSplit = splitBlock->f->GetLength() - splitPoint; + penultimate.f->GetLength() + + srcBlock->at(srcNumBlocks - 1).f->GetLength(); + sampleCount rightSplit = splitBlock.f->GetLength() - splitPoint; sampleCount rightLen = rightSplit + srcLastTwoLen; samplePtr rightBuffer = NewSamples(rightLen, mSampleFormat); - sampleCount lastStart = srcBlock->Item(srcNumBlocks - 2)->start; + sampleCount lastStart = penultimate.start; src->Get(rightBuffer, mSampleFormat, lastStart, srcLastTwoLen); Read(rightBuffer + srcLastTwoLen * sampleSize, mSampleFormat, @@ -651,23 +667,20 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) sampleCount pos = s + lastStart; split = Blockify(rightBuffer, rightLen); - for (i = 0; i < split->Count(); i++) { - split->Item(i)->start += pos; - newBlock->Add(split->Item(i)); + for (i = 0; i < split->size(); i++) { + newBlock->push_back(split->at(i).Plus(pos)); newNumBlocks++; } delete split; DeleteSamples(rightBuffer); } - mDirManager->Deref(splitBlock->f); - delete splitBlock; + mDirManager->Deref(splitBlock.f); // Copy remaining blocks to new block array and // swap the new block array in for the old for (i = b + 1; i < numBlocks; i++) { - mBlock->Item(i)->start += addedLen; - newBlock->Add(mBlock->Item(i)); + newBlock->push_back(mBlock->at(i).Plus(addedLen)); newNumBlocks++; } @@ -704,11 +717,7 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len) while (len) { sampleCount l = (len > idealSamples ? idealSamples : len); - SeqBlock *w = new SeqBlock(); - w->start = pos; - w->f = new SilentBlockFile(l); - - sTrack->mBlock->Add(w); + sTrack->mBlock->push_back(SeqBlock(new SilentBlockFile(l), pos)); pos += l; len -= l; @@ -732,14 +741,14 @@ bool Sequence::AppendAlias(wxString fullPath, if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) return false; - SeqBlock *newBlock = new SeqBlock(); - - newBlock->start = mNumSamples; - newBlock->f = useOD? - mDirManager->NewODAliasBlockFile(fullPath, start, len, channel): - mDirManager->NewAliasBlockFile(fullPath, start, len, channel); - mBlock->Add(newBlock); - mNumSamples += newBlock->f->GetLength(); + SeqBlock newBlock( + useOD? + mDirManager->NewODAliasBlockFile(fullPath, start, len, channel): + mDirManager->NewAliasBlockFile(fullPath, start, len, channel), + mNumSamples + ); + mBlock->push_back(newBlock); + mNumSamples += newBlock.f->GetLength(); return true; } @@ -751,37 +760,37 @@ bool Sequence::AppendCoded(wxString fName, sampleCount start, if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) return false; - SeqBlock *newBlock = new SeqBlock(); - - newBlock->start = mNumSamples; - newBlock->f = mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType); - mBlock->Add(newBlock); - mNumSamples += newBlock->f->GetLength(); + SeqBlock newBlock( + mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType), + mNumSamples + ); + mBlock->push_back(newBlock); + mNumSamples += newBlock.f->GetLength(); return true; } -bool Sequence::AppendBlock(SeqBlock * b) +bool Sequence::AppendBlock(SeqBlock &b) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)b->f->GetLength()) > wxLL(9223372036854775807)) + if (((double)mNumSamples) + ((double)b.f->GetLength()) > wxLL(9223372036854775807)) return false; - SeqBlock *newBlock = new SeqBlock(); - newBlock->start = mNumSamples; - newBlock->f = mDirManager->CopyBlockFile(b->f); - if (!newBlock->f) { + SeqBlock newBlock( + mDirManager->CopyBlockFile(b.f), + mNumSamples + ); + if (!newBlock.f) { /// \todo Error Could not paste! (Out of disk space?) wxASSERT(false); // TODO: Handle this better, alert the user of failure. - delete newBlock; return false; } //Don't need to Ref because it was done by CopyBlockFile, above... - //mDirManager->Ref(newBlock->f); + //mDirManager->Ref(newBlock.f); - mBlock->Add(newBlock); - mNumSamples += newBlock->f->GetLength(); + mBlock->push_back(newBlock); + mNumSamples += newBlock.f->GetLength(); // Don't do a consistency check here because this // function gets called in an inner loop @@ -793,10 +802,11 @@ bool Sequence::AppendBlock(SeqBlock * b) unsigned int Sequence::GetODFlags() { unsigned int ret = 0; - for (unsigned int i = 0; i < mBlock->GetCount(); i++){ - if(!mBlock->Item(i)->f->IsDataAvailable()) - ret = ret|((ODDecodeBlockFile*)mBlock->Item(i)->f)->GetDecodeType(); - else if(!mBlock->Item(i)->f->IsSummaryAvailable()) + for (unsigned int i = 0; i < mBlock->size(); i++) { + BlockFile *const file = mBlock->at(i).f; + if(!file->IsDataAvailable()) + ret = ret|(static_cast(file))->GetDecodeType(); + else if(!file->IsSummaryAvailable()) ret = ret|ODTask::eODPCMSummary; } return ret; @@ -805,7 +815,7 @@ unsigned int Sequence::GetODFlags() sampleCount Sequence::GetBlockStart(sampleCount position) const { int b = FindBlock(position); - return mBlock->Item(b)->start; + return mBlock->at(b).start; } sampleCount Sequence::GetBestBlockSize(sampleCount start) const @@ -815,14 +825,16 @@ sampleCount Sequence::GetBestBlockSize(sampleCount start) const // sample. The value returned will always be nonzero and will be no larger // than the value of GetMaxBlockSize(); int b = FindBlock(start); - int numBlocks = mBlock->GetCount(); + int numBlocks = mBlock->size(); - sampleCount result = (mBlock->Item(b)->start + mBlock->Item(b)->f->GetLength() - start); + const SeqBlock &block = mBlock->at(b); + sampleCount result = (block.start + block.f->GetLength() - start); + sampleCount length; while(result < mMinSamples && b+1Item(b+1)->f->GetLength()+result) <= mMaxSamples) { + ((length = mBlock->at(b+1).f->GetLength()) + result) <= mMaxSamples) { b++; - result += mBlock->Item(b)->f->GetLength(); + result += length; } wxASSERT(result > 0 && result <= mMaxSamples); @@ -836,9 +848,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) /* handle waveblock tag and it's attributes */ if (!wxStrcmp(tag, wxT("waveblock"))) { - SeqBlock *wb = new SeqBlock(); - wb->f = NULL; - wb->start = 0; + SeqBlock wb; // loop through attrs, which is a null-terminated list of // attribute-value pairs @@ -850,12 +860,11 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) break; // Both these attributes have non-negative integer counts of samples, so - // we can test & convert here, making sure that values > 2^31 are OK - // because long clips will need them. + // we can test & convert here, making sure that values > 2^31 are OK + // because long clips will need them. const wxString strValue = value; if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&nValue) || (nValue < 0)) { - delete (wb); mErrorOpening = true; wxLogWarning( wxT(" Sequence has bad %s attribute value, %s, that should be a positive integer."), @@ -864,7 +873,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) } if (!wxStrcmp(attr, wxT("start"))) - wb->start = nValue; + wb.start = nValue; // Vaughan, 2011-10-10: I don't think we ever write a "len" attribute for "waveblock" tag, // so I think this is actually legacy code, or something intended, but not completed. @@ -878,7 +887,6 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) // if the size of the block is bigger than mMaxSamples. if (nValue > mMaxSamples) { - delete (wb); mErrorOpening = true; return false; } @@ -886,8 +894,8 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) } } // while - mBlock->Add(wb); - mDirManager->SetLoadingTarget(&wb->f); + mBlock->push_back(wb); + mDirManager->SetLoadingTarget(mBlock, mBlock->size() - 1); return true; } @@ -925,7 +933,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) else if (!wxStrcmp(attr, wxT("sampleformat"))) { // This attribute is a sample format, normal int - long fValue; + long fValue; if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&fValue) || (fValue < 0) || !XMLValueChecker::IsValidSampleFormat(fValue)) { mErrorOpening = true; @@ -934,7 +942,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) mSampleFormat = (sampleFormat)fValue; } else if (!wxStrcmp(attr, wxT("numsamples"))) - { + { // This attribute is a sample count, so can be 64bit if (!XMLValueChecker::IsGoodInt64(strValue) || !strValue.ToLongLong(&nValue) || (nValue < 0)) { @@ -942,7 +950,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) return false; } mNumSamples = nValue; - } + } } // while //// Both mMaxSamples and mSampleFormat should have been set. @@ -968,14 +976,15 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Make sure that the sequence is valid. // First, replace missing blockfiles with SilentBlockFiles unsigned int b; - for (b = 0; b < mBlock->GetCount(); b++) { - if (!mBlock->Item(b)->f) { + for (b = 0; b < mBlock->size(); b++) { + SeqBlock &block = mBlock->at(b); + if (!block.f) { sampleCount len; - if (b < mBlock->GetCount()-1) - len = mBlock->Item(b+1)->start - mBlock->Item(b)->start; + if (b < mBlock->size()-1) + len = mBlock->at(b+1).start - block.start; else - len = mNumSamples - mBlock->Item(b)->start; + len = mNumSamples - block.start; if (len > mMaxSamples) { @@ -987,7 +996,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); len = mMaxSamples; } - mBlock->Item(b)->f = new SilentBlockFile(len); + block.f = new SilentBlockFile(len); wxLogWarning( wxT("Gap detected in project file. Replacing missing block file with silence.")); mErrorOpening = true; @@ -996,22 +1005,23 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Next, make sure that start times and lengths are consistent sampleCount numSamples = 0; - for (b = 0; b < mBlock->GetCount(); b++) { - if (mBlock->Item(b)->start != numSamples) { - wxString sFileAndExtension = mBlock->Item(b)->f->GetFileName().GetFullName(); + for (b = 0; b < mBlock->size(); b++) { + SeqBlock &block = mBlock->at(b); + if (block.start != numSamples) { + wxString sFileAndExtension = block.f->GetFileName().GetFullName(); if (sFileAndExtension.IsEmpty()) sFileAndExtension = wxT("(replaced with silence)"); else sFileAndExtension = wxT("\"") + sFileAndExtension + wxT("\""); wxLogWarning( wxT("Gap detected in project file.\n Start (%s) for block file %s is more than one sample past end of previous block (%s).\n Moving start back so blocks are contiguous."), - Internat::ToString(((wxLongLong)(mBlock->Item(b)->start)).ToDouble(), 0).c_str(), + Internat::ToString(((wxLongLong)(block.start)).ToDouble(), 0).c_str(), sFileAndExtension.c_str(), Internat::ToString(((wxLongLong)(numSamples)).ToDouble(), 0).c_str()); - mBlock->Item(b)->start = numSamples; + block.start = numSamples; mErrorOpening = true; } - numSamples += mBlock->Item(b)->f->GetLength(); + numSamples += block.f->GetLength(); } if (mNumSamples != numSamples) { wxLogWarning( @@ -1043,29 +1053,29 @@ void Sequence::WriteXML(XMLWriter &xmlFile) xmlFile.WriteAttr(wxT("sampleformat"), mSampleFormat); xmlFile.WriteAttr(wxT("numsamples"), mNumSamples); - for (b = 0; b < mBlock->GetCount(); b++) { - SeqBlock *bb = mBlock->Item(b); + for (b = 0; b < mBlock->size(); b++) { + SeqBlock &bb = mBlock->at(b); // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451. // Also, don't check against mMaxSamples for AliasBlockFiles, because if you convert sample format, // mMaxSample gets changed to match the format, but the number of samples in the aliased file // has not changed (because sample format conversion was not actually done in the aliased file. - if (!bb->f->IsAlias() && (bb->f->GetLength() > mMaxSamples)) + if (!bb.f->IsAlias() && (bb.f->GetLength() > mMaxSamples)) { wxString sMsg = wxString::Format( _("Sequence has block file with length %s > mMaxSamples %s.\nTruncating to mMaxSamples."), - Internat::ToString(((wxLongLong)(bb->f->GetLength())).ToDouble(), 0).c_str(), + Internat::ToString(((wxLongLong)(bb.f->GetLength())).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); wxMessageBox(sMsg, _("Warning - Length in Writing Sequence"), wxICON_EXCLAMATION | wxOK); wxLogWarning(sMsg); - bb->f->SetLength(mMaxSamples); + bb.f->SetLength(mMaxSamples); } xmlFile.StartTag(wxT("waveblock")); - xmlFile.WriteAttr(wxT("start"), bb->start); + xmlFile.WriteAttr(wxT("start"), bb.start); - bb->f->SaveXML(xmlFile); + bb.f->SaveXML(xmlFile); xmlFile.EndTag(wxT("waveblock")); } @@ -1076,17 +1086,18 @@ void Sequence::WriteXML(XMLWriter &xmlFile) int Sequence::FindBlock(sampleCount pos, sampleCount lo, sampleCount guess, sampleCount hi) const { - wxASSERT(mBlock->Item(guess)->f->GetLength() > 0); + const SeqBlock &block = mBlock->at(guess); + wxASSERT(block.f->GetLength() > 0); wxASSERT(lo <= guess && guess <= hi && lo <= hi); - if (pos >= mBlock->Item(guess)->start && - pos < mBlock->Item(guess)->start + mBlock->Item(guess)->f->GetLength()) + if (pos >= block.start && + pos < block.start + block.f->GetLength()) return guess; //this is a binary search, but we probably could benefit by something more like //dictionary search where we guess something smarter than the binary division //of the unsearched area, since samples are usually proportional to block file number. - if (pos < mBlock->Item(guess)->start) + if (pos < block.start) return FindBlock(pos, lo, (lo + guess) / 2, guess); else return FindBlock(pos, guess + 1, (guess + 1 + hi) / 2, hi); @@ -1096,7 +1107,7 @@ int Sequence::FindBlock(sampleCount pos) const { wxASSERT(pos >= 0 && pos <= mNumSamples); - int numBlocks = mBlock->GetCount(); + int numBlocks = mBlock->size(); if (pos == 0) return 0; @@ -1107,20 +1118,19 @@ int Sequence::FindBlock(sampleCount pos) const int rval = FindBlock(pos, 0, numBlocks / 2, numBlocks); wxASSERT(rval >= 0 && rval < numBlocks && - pos >= mBlock->Item(rval)->start && - pos < mBlock->Item(rval)->start + mBlock->Item(rval)->f->GetLength()); + pos >= mBlock->at(rval).start && + pos < mBlock->at(rval).start + mBlock->at(rval).f->GetLength()); return rval; } bool Sequence::Read(samplePtr buffer, sampleFormat format, - SeqBlock * b, sampleCount start, sampleCount len) const + const SeqBlock &b, sampleCount start, sampleCount len) const { - wxASSERT(b); wxASSERT(start >= 0); - wxASSERT(start + len <= b->f->GetLength()); + wxASSERT(start + len <= b.f->GetLength()); - BlockFile *f = b->f; + BlockFile *f = b.f; int result = f->ReadData(buffer, format, start, len); @@ -1135,26 +1145,26 @@ bool Sequence::Read(samplePtr buffer, sampleFormat format, return true; } -bool Sequence::CopyWrite(samplePtr buffer, SeqBlock *b, +bool Sequence::CopyWrite(samplePtr buffer, SeqBlock &b, sampleCount start, sampleCount len) { // We don't ever write to an existing block; to support Undo, // we copy the old block entirely into memory, dereference it, // make the change, and then write the new block to disk. - wxASSERT(b); - wxASSERT(b->f->GetLength() <= mMaxSamples); - wxASSERT(start + len <= b->f->GetLength()); + const sampleCount length = b.f->GetLength(); + wxASSERT(length <= mMaxSamples); + wxASSERT(start + len <= length); int sampleSize = SAMPLE_SIZE(mSampleFormat); samplePtr newBuffer = NewSamples(mMaxSamples, mSampleFormat); wxASSERT(newBuffer); - Read(newBuffer, mSampleFormat, b, 0, b->f->GetLength()); + Read(newBuffer, mSampleFormat, b, 0, length); memcpy(newBuffer + start*sampleSize, buffer, len*sampleSize); - BlockFile *oldBlockFile = b->f; - b->f = mDirManager->NewSimpleBlockFile(newBuffer, b->f->GetLength(), mSampleFormat); + BlockFile *oldBlockFile = b.f; + b.f = mDirManager->NewSimpleBlockFile(newBuffer, length, mSampleFormat); mDirManager->Deref(oldBlockFile); @@ -1172,13 +1182,14 @@ bool Sequence::Get(samplePtr buffer, sampleFormat format, int b = FindBlock(start); while (len) { + const SeqBlock &block = mBlock->at(b); sampleCount blen = - mBlock->Item(b)->start + mBlock->Item(b)->f->GetLength() - start; + block.start + block.f->GetLength() - start; if (blen > len) blen = len; - sampleCount bstart = (start - (mBlock->Item(b)->start)); + sampleCount bstart = (start - (block.start)); - Read(buffer, format, mBlock->Item(b), bstart, blen); + Read(buffer, format, block, bstart, blen); len -= blen; buffer += (blen * SAMPLE_SIZE(format)); @@ -1213,33 +1224,34 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, int b = FindBlock(start); while (len) { - int blen = mBlock->Item(b)->start + mBlock->Item(b)->f->GetLength() - start; + SeqBlock &block = mBlock->at(b); + int blen = block.start + block.f->GetLength() - start; if (blen > len) blen = len; if (buffer) { if (format == mSampleFormat) - CopyWrite(buffer, mBlock->Item(b), start - mBlock->Item(b)->start, + CopyWrite(buffer, block, start - block.start, blen); else { CopySamples(buffer, format, temp, mSampleFormat, blen); - CopyWrite(temp, mBlock->Item(b), start - mBlock->Item(b)->start, + CopyWrite(temp, block, start - block.start, blen); } buffer += (blen * SAMPLE_SIZE(format)); } else { // If it's a full block of silence - if (start == mBlock->Item(b)->start && - blen == mBlock->Item(b)->f->GetLength()) { + if (start == block.start && + blen == block.f->GetLength()) { - mDirManager->Deref(mBlock->Item(b)->f); - mBlock->Item(b)->f = new SilentBlockFile(blen); + mDirManager->Deref(block.f); + block.f = new SilentBlockFile(blen); } else { // Otherwise write silence just to the portion of the block - CopyWrite(silence, mBlock->Item(b), - start - mBlock->Item(b)->start, blen); + CopyWrite(silence, block, + start - block.start, blen); } } @@ -1325,7 +1337,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, sampleCount whereNext = 0; // Loop over block files, opening and reading and closing each // not more than once - unsigned nBlocks = mBlock->GetCount(); + unsigned nBlocks = mBlock->size(); const unsigned int block0 = FindBlock(s0); for (unsigned int b = block0; b < nBlocks; ++b) { if (b > block0) @@ -1335,9 +1347,9 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, // Find the range of sample values for this block that // are in the display. - SeqBlock *const pSeqBlock = mBlock->Item(b); - const sampleCount start = pSeqBlock->start; - nextSrcX = std::min(s1, start + pSeqBlock->f->GetLength()); + SeqBlock &seqBlock = mBlock->at(b); + const sampleCount start = seqBlock.start; + nextSrcX = std::min(s1, start + seqBlock.f->GetLength()); // The column for pixel p covers samples from // where[p] up to but excluding where[p + 1]. @@ -1401,13 +1413,13 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, default: case 1: // Read samples - Read((samplePtr)temp, floatSample, pSeqBlock, startPosition, num); + Read((samplePtr)temp, floatSample, seqBlock, startPosition, num); break; case 256: // Read triples //check to see if summary data has been computed - if (pSeqBlock->f->IsSummaryAvailable()) - pSeqBlock->f->Read256(temp, startPosition, num); + if (seqBlock.f->IsSummaryAvailable()) + seqBlock.f->Read256(temp, startPosition, num); else //otherwise, mark the display as not yet computed blockStatus = -1 - b; @@ -1415,8 +1427,8 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, case 65536: // Read triples //check to see if summary data has been computed - if (pSeqBlock->f->IsSummaryAvailable()) - pSeqBlock->f->Read64K(temp, startPosition, num); + if (seqBlock.f->IsSummaryAvailable()) + seqBlock.f->Read64K(temp, startPosition, num); else //otherwise, mark the display as not yet computed blockStatus = -1 - b; @@ -1498,14 +1510,14 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, sampleCount Sequence::GetIdealAppendLen() { - int numBlocks = mBlock->GetCount(); + int numBlocks = mBlock->size(); sampleCount max = GetMaxBlockSize(); sampleCount lastBlockLen; if (numBlocks == 0) return max; - lastBlockLen = mBlock->Item(numBlocks-1)->f->GetLength(); + lastBlockLen = mBlock->at(numBlocks-1).f->GetLength(); if (lastBlockLen == max) return max; else @@ -1520,40 +1532,42 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, return false; // If the last block is not full, we need to add samples to it - int numBlocks = mBlock->GetCount(); - if (numBlocks > 0 && mBlock->Item(numBlocks - 1)->f->GetLength() < mMinSamples) { - SeqBlock *lastBlock = mBlock->Item(numBlocks - 1); + int numBlocks = mBlock->size(); + sampleCount length; + SeqBlock *pLastBlock; + if (numBlocks > 0 && + (length = + (pLastBlock = &mBlock->at(numBlocks - 1))->f->GetLength()) < mMinSamples) { + SeqBlock &lastBlock = *pLastBlock; sampleCount addLen; - if (lastBlock->f->GetLength() + len < mMaxSamples) + if (length + len < mMaxSamples) addLen = len; else - addLen = GetIdealBlockSize() - lastBlock->f->GetLength(); + addLen = GetIdealBlockSize() - length; - SeqBlock *newLastBlock = new SeqBlock(); - - samplePtr buffer2 = NewSamples((lastBlock->f->GetLength() + addLen), mSampleFormat); - Read(buffer2, mSampleFormat, lastBlock, 0, lastBlock->f->GetLength()); + samplePtr buffer2 = NewSamples((length + addLen), mSampleFormat); + Read(buffer2, mSampleFormat, lastBlock, 0, length); CopySamples(buffer, format, - buffer2 + lastBlock->f->GetLength() * SAMPLE_SIZE(mSampleFormat), + buffer2 + length * SAMPLE_SIZE(mSampleFormat), mSampleFormat, addLen); - newLastBlock->start = lastBlock->start; - int newLastBlockLen = lastBlock->f->GetLength() + addLen; + int newLastBlockLen = length + addLen; - newLastBlock->f = + SeqBlock newLastBlock( mDirManager->NewSimpleBlockFile(buffer2, newLastBlockLen, mSampleFormat, - blockFileLog != NULL); + blockFileLog != NULL), + lastBlock.start + ); if (blockFileLog) - ((SimpleBlockFile*)newLastBlock->f)->SaveXML(*blockFileLog); + static_cast(newLastBlock.f)->SaveXML(*blockFileLog); DeleteSamples(buffer2); - mDirManager->Deref(lastBlock->f); - delete lastBlock; - mBlock->Item(numBlocks - 1) = newLastBlock; + mDirManager->Deref(lastBlock.f); + lastBlock = newLastBlock; len -= addLen; mNumSamples += addLen; @@ -1578,23 +1592,21 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, while (len) { sampleCount idealSamples = GetIdealBlockSize(); sampleCount l = (len > idealSamples ? idealSamples : len); - SeqBlock *w = new SeqBlock(); - w->start = mNumSamples; - + BlockFile *pFile; if (format == mSampleFormat) { - w->f = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat, + pFile = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat, blockFileLog != NULL); } else { CopySamples(buffer, format, temp, mSampleFormat, l); - w->f = mDirManager->NewSimpleBlockFile(temp, l, mSampleFormat, + pFile = mDirManager->NewSimpleBlockFile(temp, l, mSampleFormat, blockFileLog != NULL); } if (blockFileLog) - ((SimpleBlockFile*)w->f)->SaveXML(*blockFileLog); + static_cast(pFile)->SaveXML(*blockFileLog); - mBlock->Add(w); + mBlock->push_back(SeqBlock(pFile, mNumSamples)); buffer += l * SAMPLE_SIZE(format); mNumSamples += l; @@ -1619,20 +1631,20 @@ BlockArray *Sequence::Blockify(samplePtr buffer, sampleCount len) if (len <= 0) return list; - list->Alloc(10); + list->reserve(10); int num = (len + (mMaxSamples - 1)) / mMaxSamples; for (int i = 0; i < num; i++) { - SeqBlock *b = new SeqBlock(); + SeqBlock b; - b->start = i * len / num; - int newLen = ((i + 1) * len / num) - b->start; - samplePtr bufStart = buffer + (b->start * SAMPLE_SIZE(mSampleFormat)); + b.start = i * len / num; + int newLen = ((i + 1) * len / num) - b.start; + samplePtr bufStart = buffer + (b.start * SAMPLE_SIZE(mSampleFormat)); - b->f = mDirManager->NewSimpleBlockFile(bufStart, newLen, mSampleFormat); + b.f = mDirManager->NewSimpleBlockFile(bufStart, newLen, mSampleFormat); - list->Add(b); + list->push_back(b); } return list; @@ -1652,7 +1664,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) //both functions, LockDeleteUpdateMutex(); - unsigned int numBlocks = mBlock->GetCount(); + unsigned int numBlocks = mBlock->size(); unsigned int newNumBlocks = 0; unsigned int b0 = FindBlock(start); @@ -1663,10 +1675,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Special case: if the samples to delete are all within a single // block and the resulting length is not too small, perform the // deletion within this block: - if (b0 == b1 && mBlock->Item(b0)->f->GetLength() - len >= mMinSamples) { - SeqBlock *b = mBlock->Item(b0); - sampleCount pos = start - b->start; - sampleCount newLen = b->f->GetLength() - len; + SeqBlock *pBlock; + sampleCount length; + if (b0 == b1 && (length = (pBlock = &mBlock->at(b0))->f->GetLength()) - len >= mMinSamples) { + SeqBlock &b = *pBlock; + sampleCount pos = start - b.start; + sampleCount newLen = length - len; samplePtr buffer = NewSamples(newLen, mSampleFormat); @@ -1674,20 +1688,18 @@ bool Sequence::Delete(sampleCount start, sampleCount len) Read(buffer + (pos * sampleSize), mSampleFormat, b, pos + len, newLen - pos); - SeqBlock *newBlock = new SeqBlock(); - newBlock->start = b->start; - newBlock->f = - mDirManager->NewSimpleBlockFile(buffer, newLen, mSampleFormat); - - mBlock->Item(b0) = newBlock; + BlockFile *const oldFile = b.f; + b = SeqBlock( + mDirManager->NewSimpleBlockFile(buffer, newLen, mSampleFormat), + b.start + ); for (unsigned int j = b0 + 1; j < numBlocks; j++) - mBlock->Item(j)->start -= len; + mBlock->at(j).start -= len; DeleteSamples(buffer); - mDirManager->Deref(b->f); - delete b; + mDirManager->Deref(oldFile); mNumSamples -= len; UnlockDeleteUpdateMutex(); @@ -1697,13 +1709,13 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Create a new array of blocks BlockArray *newBlock = new BlockArray(); - newBlock->Alloc(numBlocks - (b1 - b0) + 2); + newBlock->reserve(numBlocks - (b1 - b0) + 2); // Copy the blocks before the deletion point over to // the new array unsigned int i; for (i = 0; i < b0; i++) { - newBlock->Add(mBlock->Item(i)); + newBlock->push_back(mBlock->at(i)); newNumBlocks++; } @@ -1712,30 +1724,25 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). - SeqBlock *preBlock = mBlock->Item(b0); - sampleCount preBufferLen = start - preBlock->start; + SeqBlock &preBlock = mBlock->at(b0); + sampleCount preBufferLen = start - preBlock.start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { - SeqBlock *insBlock = new SeqBlock(); - - insBlock->start = preBlock->start; - samplePtr preBuffer = NewSamples(preBufferLen, mSampleFormat); Read(preBuffer, mSampleFormat, preBlock, 0, preBufferLen); - insBlock->f = + BlockFile *const pFile = mDirManager->NewSimpleBlockFile(preBuffer, preBufferLen, mSampleFormat); DeleteSamples(preBuffer); - newBlock->Add(insBlock); + newBlock->push_back(SeqBlock(pFile, preBlock.start)); newNumBlocks++; if (b0 != b1) { - mDirManager->Deref(preBlock->f); - delete preBlock; + mDirManager->Deref(preBlock.f); } } else { - SeqBlock *prepreBlock = mBlock->Item(b0 - 1); - sampleCount prepreLen = prepreBlock->f->GetLength(); + SeqBlock &prepreBlock = mBlock->at(b0 - 1); + sampleCount prepreLen = prepreBlock.f->GetLength(); sampleCount sum = prepreLen + preBufferLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); @@ -1745,38 +1752,32 @@ bool Sequence::Delete(sampleCount start, sampleCount len) preBlock, 0, preBufferLen); BlockArray *split = Blockify(sumBuffer, sum); - split->Item(0)->start += prepreBlock->start; - newBlock->Item(b0 - 1) = split->Item(0); - for (i = 1; i < split->GetCount(); i++) { - split->Item(i)->start += prepreBlock->start; - newBlock->Add(split->Item(i)); + newBlock->at(b0 - 1) = split->at(0).Plus(prepreBlock.start); + for (i = 1; i < split->size(); i++) { + newBlock->push_back(split->at(i).Plus(prepreBlock.start)); newNumBlocks++; } delete split; DeleteSamples(sumBuffer); - mDirManager->Deref(prepreBlock->f); - delete prepreBlock; + mDirManager->Deref(prepreBlock.f); if (b0 != b1) { - mDirManager->Deref(preBlock->f); - delete preBlock; + mDirManager->Deref(preBlock.f); } } } else { // The sample where we begin deletion happens to fall // right on the beginning of a block. if (b0 != b1) { - mDirManager->Deref(mBlock->Item(b0)->f); - delete mBlock->Item(b0); + mDirManager->Deref(preBlock.f); } } // Next, delete blocks strictly between b0 and b1 for (i = b0 + 1; i < b1; i++) { - mDirManager->Deref(mBlock->Item(i)->f); - delete mBlock->Item(i); + mDirManager->Deref(mBlock->at(i).f); } // Now, symmetrically, grab the samples in block b1 after the @@ -1784,43 +1785,37 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). - SeqBlock *postBlock = mBlock->Item(b1); + SeqBlock &postBlock = mBlock->at(b1); sampleCount postBufferLen = - (postBlock->start + postBlock->f->GetLength()) - (start + len); + (postBlock.start + postBlock.f->GetLength()) - (start + len); if (postBufferLen) { if (postBufferLen >= mMinSamples || b1 == numBlocks - 1) { - SeqBlock *insBlock = new SeqBlock(); - - insBlock->start = start; - samplePtr postBuffer = NewSamples(postBufferLen, mSampleFormat); - sampleCount pos = (start + len) - postBlock->start; + sampleCount pos = (start + len) - postBlock.start; Read(postBuffer, mSampleFormat, postBlock, pos, postBufferLen); - insBlock->f = + BlockFile *const file= mDirManager->NewSimpleBlockFile(postBuffer, postBufferLen, mSampleFormat); DeleteSamples(postBuffer); - newBlock->Add(insBlock); + newBlock->push_back(SeqBlock(file, start)); newNumBlocks++; - mDirManager->Deref(postBlock->f); - delete postBlock; + mDirManager->Deref(postBlock.f); } else { - SeqBlock *postpostBlock = mBlock->Item(b1 + 1); - sampleCount postpostLen = postpostBlock->f->GetLength(); + SeqBlock &postpostBlock = mBlock->at(b1 + 1); + sampleCount postpostLen = postpostBlock.f->GetLength(); sampleCount sum = postpostLen + postBufferLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); - sampleCount pos = (start + len) - postBlock->start; + sampleCount pos = (start + len) - postBlock.start; Read(sumBuffer, mSampleFormat, postBlock, pos, postBufferLen); Read(sumBuffer + (postBufferLen * sampleSize), mSampleFormat, postpostBlock, 0, postpostLen); BlockArray *split = Blockify(sumBuffer, sum); - for (i = 0; i < split->GetCount(); i++) { - split->Item(i)->start += start; - newBlock->Add(split->Item(i)); + for (i = 0; i < split->size(); i++) { + newBlock->push_back(split->at(i).Plus(start)); newNumBlocks++; } delete split; @@ -1828,22 +1823,18 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(sumBuffer); - mDirManager->Deref(postpostBlock->f); - delete postpostBlock; - mDirManager->Deref(postBlock->f); - delete postBlock; + mDirManager->Deref(postpostBlock.f); + mDirManager->Deref(postBlock.f); } } else { // The sample where we begin deletion happens to fall // right on the end of a block. - mDirManager->Deref(mBlock->Item(b1)->f); - delete mBlock->Item(b1); + mDirManager->Deref(postBlock.f); } // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) { - mBlock->Item(i)->start -= len; - newBlock->Add(mBlock->Item(i)); + newBlock->push_back(mBlock->at(i).Plus(-len)); newNumBlocks++; } @@ -1862,16 +1853,16 @@ bool Sequence::ConsistencyCheck(const wxChar *whereStr) { unsigned int i; sampleCount pos = 0; - unsigned int numBlocks = mBlock->GetCount(); + unsigned int numBlocks = mBlock->size(); bool bError = false; for (i = 0; i < numBlocks; i++) { - SeqBlock* pSeqBlock = mBlock->Item(i); - if (pos != pSeqBlock->start) + SeqBlock &seqBlock = mBlock->at(i); + if (pos != seqBlock.start) bError = true; - if (pSeqBlock->f) - pos += mBlock->Item(i)->f->GetLength(); + if (seqBlock.f) + pos += seqBlock.f->GetLength(); else bError = true; } @@ -1895,27 +1886,27 @@ void Sequence::DebugPrintf(wxString *dest) unsigned int i; int pos = 0; - for (i = 0; i < mBlock->GetCount(); i++) { - SeqBlock* pSeqBlock = mBlock->Item(i); + for (i = 0; i < mBlock->size(); i++) { + SeqBlock &seqBlock = mBlock->at(i); *dest += wxString::Format (wxT(" Block %3u: start %8lld, len %8lld, refs %d, "), i, - (long long) pSeqBlock->start, - pSeqBlock->f ? (long long) pSeqBlock->f->GetLength() : 0, - pSeqBlock->f ? mDirManager->GetRefCount(pSeqBlock->f) : 0); + (long long) seqBlock.start, + seqBlock.f ? (long long) seqBlock.f->GetLength() : 0, + seqBlock.f ? mDirManager->GetRefCount(seqBlock.f) : 0); - if (pSeqBlock->f) - *dest += pSeqBlock->f->GetFileName().GetFullName(); + if (seqBlock.f) + *dest += seqBlock.f->GetFileName().GetFullName(); else *dest += wxT(""); - if ((pos != pSeqBlock->start) || !pSeqBlock->f) + if ((pos != seqBlock.start) || !seqBlock.f) *dest += wxT(" ERROR\n"); else *dest += wxT("\n"); - if (pSeqBlock->f) - pos += pSeqBlock->f->GetLength(); + if (seqBlock.f) + pos += seqBlock.f->GetLength(); } if (pos != mNumSamples) *dest += wxString::Format @@ -1935,10 +1926,7 @@ int Sequence::GetMaxDiskBlockSize() void Sequence::AppendBlockFile(BlockFile* blockFile) { - SeqBlock *w = new SeqBlock(); - w->start = mNumSamples; - w->f = blockFile; - mBlock->Add(w); + mBlock->push_back(SeqBlock(blockFile, mNumSamples)); mNumSamples += blockFile->GetLength(); #ifdef VERY_SLOW_CHECKING diff --git a/src/Sequence.h b/src/Sequence.h index d577704fb..9a4232b14 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -11,6 +11,7 @@ #ifndef __AUDACITY_SEQUENCE__ #define __AUDACITY_SEQUENCE__ +#include #include #include @@ -36,8 +37,23 @@ class SeqBlock { BlockFile * f; ///the sample in the global wavetrack that this block starts at. sampleCount start; + + SeqBlock() + : f(NULL), start(0) + {} + + SeqBlock(BlockFile *f_, sampleCount start_) + : f(f_), start(start_) + {} + + // Construct a SeqBlock with changed start, same file + SeqBlock Plus(sampleCount delta) const + { + return SeqBlock(f, start + delta); + } }; -WX_DEFINE_ARRAY(SeqBlock *, BlockArray); +class BlockArray : public std::vector {}; +WX_DEFINE_ARRAY(SeqBlock *, BlockPtrArray); class Sequence: public XMLTagHandler { public: @@ -214,15 +230,15 @@ class Sequence: public XMLTagHandler { int FindBlock(sampleCount pos, sampleCount lo, sampleCount guess, sampleCount hi) const; - bool AppendBlock(SeqBlock *b); + bool AppendBlock(SeqBlock &b); bool Read(samplePtr buffer, sampleFormat format, - SeqBlock * b, + const SeqBlock &b, sampleCount start, sampleCount len) const; // These are the two ways to write data to a block bool FirstWrite(samplePtr buffer, SeqBlock * b, sampleCount len); - bool CopyWrite(samplePtr buffer, SeqBlock * b, + bool CopyWrite(samplePtr buffer, SeqBlock &b, sampleCount start, sampleCount len); // Both block-writing methods and AppendAlias call this diff --git a/src/UndoManager.cpp b/src/UndoManager.cpp index ba8ecbef9..3730775fa 100644 --- a/src/UndoManager.cpp +++ b/src/UndoManager.cpp @@ -80,9 +80,9 @@ void UndoManager::CalculateSpaceUsage() { // Scan all blockfiles within current clip BlockArray *blocks = it->GetData()->GetSequenceBlockArray(); - for (size_t b = 0, cnt = blocks->GetCount(); b < cnt; b++) + for (size_t b = 0, cnt = blocks->size(); b < cnt; b++) { - BlockFile *file = blocks->Item(b)->f; + BlockFile *file = blocks->at(b).f; // Accumulate space used by the file if the file didn't exist // in the previous level diff --git a/src/ondemand/ODComputeSummaryTask.cpp b/src/ondemand/ODComputeSummaryTask.cpp index 7bc0ca0c0..0c10d99eb 100644 --- a/src/ondemand/ODComputeSummaryTask.cpp +++ b/src/ondemand/ODComputeSummaryTask.cpp @@ -202,22 +202,25 @@ void ODComputeSummaryTask::Update() insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n) - for(i=0; i<(int)blocks->GetCount(); i++) + for(i=0; i<(int)blocks->size(); i++) { //if there is data but no summary, this blockfile needs summarizing. - if(blocks->Item(i)->f->IsDataAvailable() && !blocks->Item(i)->f->IsSummaryAvailable()) + SeqBlock &block = blocks->at(i); + BlockFile *const file = block.f; + if(file->IsDataAvailable() && !file->IsSummaryAvailable()) { - blocks->Item(i)->f->Ref(); - ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start); - ((ODPCMAliasBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); + file->Ref(); + ODPCMAliasBlockFile *const odpcmaFile = static_cast(file); + odpcmaFile->SetStart(block.start); + odpcmaFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); //these will always be linear within a sequence-lets take advantage of this by keeping a cursor. while(insertCursor<(int)tempBlocks.size()&& (sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) < - (sampleCount)(((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetStart()+((ODPCMAliasBlockFile*)blocks->Item(i)->f)->GetClipOffset())) + (sampleCount)(odpcmaFile->GetStart()+odpcmaFile->GetClipOffset())) insertCursor++; - tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODPCMAliasBlockFile*)blocks->Item(i)->f); + tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile); } } seq->UnlockDeleteUpdateMutex(); diff --git a/src/ondemand/ODDecodeTask.cpp b/src/ondemand/ODDecodeTask.cpp index bd4f483ae..b0867f5a4 100644 --- a/src/ondemand/ODDecodeTask.cpp +++ b/src/ondemand/ODDecodeTask.cpp @@ -154,22 +154,26 @@ void ODDecodeTask::Update() int insertCursor; insertCursor =0;//OD TODO:see if this works, removed from inner loop (bfore was n*n) - for(i=0; i<(int)blocks->GetCount(); i++) + for (i = 0; i<(int)blocks->size(); i++) { //since we have more than one ODBlockFile, we will need type flags to cast. - if(!blocks->Item(i)->f->IsDataAvailable() && ((ODDecodeBlockFile*)blocks->Item(i)->f)->GetDecodeType()==this->GetODType()) + SeqBlock &block = blocks->at(i); + BlockFile *const file = block.f; + ODDecodeBlockFile *oddbFile; + if (!file->IsDataAvailable() && + (oddbFile = static_cast(file))->GetDecodeType() == this->GetODType()) { - blocks->Item(i)->f->Ref(); - ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetStart(blocks->Item(i)->start); - ((ODDecodeBlockFile*)blocks->Item(i)->f)->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); + file->Ref(); + oddbFile->SetStart(block.start); + oddbFile->SetClipOffset((sampleCount)(clip->GetStartTime()*clip->GetRate())); //these will always be linear within a sequence-lets take advantage of this by keeping a cursor. while(insertCursor<(int)tempBlocks.size()&& (sampleCount)(tempBlocks[insertCursor]->GetStart()+tempBlocks[insertCursor]->GetClipOffset()) < - (sampleCount)(((ODDecodeBlockFile*)blocks->Item(i)->f)->GetStart()+((ODDecodeBlockFile*)blocks->Item(i)->f)->GetClipOffset())) + (sampleCount)((oddbFile->GetStart()+oddbFile->GetClipOffset()))) insertCursor++; - tempBlocks.insert(tempBlocks.begin()+insertCursor++,(ODDecodeBlockFile*)blocks->Item(i)->f); + tempBlocks.insert(tempBlocks.begin()+insertCursor++, oddbFile); } } From 51fbc697cffa38f3d42649f169a10709f920e727 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 30 Jan 2016 12:50:53 -0500 Subject: [PATCH 02/16] One less indirection accessing Sequence::mBlock --- src/Dependencies.cpp | 6 +- src/Project.cpp | 7 +- src/Sequence.cpp | 233 +++++++++++++++++++++---------------------- src/Sequence.h | 6 +- src/WaveClip.cpp | 2 +- 5 files changed, 123 insertions(+), 131 deletions(-) diff --git a/src/Dependencies.cpp b/src/Dependencies.cpp index c6d6f73c7..8e576dec6 100644 --- a/src/Dependencies.cpp +++ b/src/Dependencies.cpp @@ -72,10 +72,10 @@ static void GetAllSeqBlocks(AudacityProject *project, while(node) { WaveClip *clip = node->GetData(); Sequence *sequence = clip->GetSequence(); - BlockArray *blocks = sequence->GetBlockArray(); + BlockArray &blocks = sequence->GetBlockArray(); int i; - for (i = 0; i < (int)blocks->size(); i++) - outBlocks->push_back(&blocks->at(i)); + for (i = 0; i < (int)blocks.size(); i++) + outBlocks->push_back(&blocks.at(i)); node = node->GetNext(); } } diff --git a/src/Project.cpp b/src/Project.cpp index 0f8409b3e..513925f31 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -3737,9 +3737,10 @@ void AudacityProject::AddImportedTracks(wxString fileName, if (newTracks[i]->GetKind() == WaveTrack::Wave) { WaveClip* clip = ((WaveTrack*)newTracks[i])->GetClipByIndex(0); - if (clip && clip->GetSequence()->GetBlockArray()->size()) + BlockArray &blocks = clip->GetSequence()->GetBlockArray(); + if (clip && blocks.size()) { - SeqBlock& block = clip->GetSequence()->GetBlockArray()->at(0); + SeqBlock& block = blocks.at(0); if (block.f->IsAlias()) { mImportedDependencies = true; @@ -5189,7 +5190,7 @@ void AudacityProject::CaptureKeyboard(wxWindow *handler) } // static -void AudacityProject::ReleaseKeyboard(wxWindow *handler) +void AudacityProject::ReleaseKeyboard(wxWindow * /* handler */) { AudacityProject *project = GetActiveProject(); if (project) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 24bfd49fb..5afc517af 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -58,7 +58,6 @@ Sequence::Sequence(DirManager * projDirManager, sampleFormat format) mDirManager->Ref(); mNumSamples = 0; mSampleFormat = format; - mBlock = new BlockArray(); mMinSamples = sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2; mMaxSamples = mMinSamples * 2; @@ -79,8 +78,6 @@ Sequence::Sequence(const Sequence &orig, DirManager *projDirManager) mMinSamples = orig.mMinSamples; mErrorOpening = false; - mBlock = new BlockArray(); - bool bResult = Paste(0, &orig); wxASSERT(bResult); // TO DO: Actually handle this. (void)bResult; @@ -88,13 +85,12 @@ Sequence::Sequence(const Sequence &orig, DirManager *projDirManager) Sequence::~Sequence() { - for (unsigned int i = 0; i < mBlock->size(); i++) { - BlockFile *const file = mBlock->at(i).f; + for (unsigned int i = 0; i < mBlock.size(); i++) { + BlockFile *const file = mBlock.at(i).f; if (file) mDirManager->Deref(file); } - delete mBlock; mDirManager->Deref(); } @@ -110,24 +106,24 @@ sampleCount Sequence::GetIdealBlockSize() const bool Sequence::Lock() { - for (unsigned int i = 0; i < mBlock->size(); i++) - mBlock->at(i).f->Lock(); + for (unsigned int i = 0; i < mBlock.size(); i++) + mBlock.at(i).f->Lock(); return true; } bool Sequence::CloseLock() { - for (unsigned int i = 0; i < mBlock->size(); i++) - mBlock->at(i).f->CloseLock(); + for (unsigned int i = 0; i < mBlock.size(); i++) + mBlock.at(i).f->CloseLock(); return true; } bool Sequence::Unlock() { - for (unsigned int i = 0; i < mBlock->size(); i++) - mBlock->at(i).f->Unlock(); + for (unsigned int i = 0; i < mBlock.size(); i++) + mBlock.at(i).f->Unlock(); return true; } @@ -139,7 +135,7 @@ sampleFormat Sequence::GetSampleFormat() const bool Sequence::SetSampleFormat(sampleFormat format) { - if (mBlock->size() > 0 || mNumSamples > 0) + if (mBlock.size() > 0 || mNumSamples > 0) return false; mSampleFormat = format; @@ -155,7 +151,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) if (format == mSampleFormat) return true; - if (mBlock->size() == 0) + if (mBlock.size() == 0) { mSampleFormat = format; *pbChanged = true; @@ -170,14 +166,14 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) mMinSamples = sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2; mMaxSamples = mMinSamples * 2; - BlockArray* pNewBlockArray = new BlockArray(); + BlockArray newBlockArray; // Use the ratio of old to new mMaxSamples to make a reasonable guess at allocation. - pNewBlockArray->reserve(mBlock->size() * ((float)oldMaxSamples / (float)mMaxSamples)); + newBlockArray.reserve(mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples)); bool bSuccess = true; - for (size_t i = 0; (i < mBlock->size() && bSuccess); i++) + for (size_t i = 0; (i < mBlock.size() && bSuccess); i++) { - SeqBlock &oldSeqBlock = mBlock->at(i); + SeqBlock &oldSeqBlock = mBlock.at(i); BlockFile* oldBlockFile = oldSeqBlock.f; sampleCount len = oldBlockFile->GetLength(); @@ -208,10 +204,10 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) bSuccess = (pSplitBlockArray->size() > 0); if (bSuccess) { - const sampleCount blockstart = mBlock->at(i).start; + const sampleCount blockstart = mBlock.at(i).start; for (size_t j = 0; j < pSplitBlockArray->size(); j++) { - pNewBlockArray->push_back(pSplitBlockArray->at(j).Plus(blockstart)); + newBlockArray.push_back(pSplitBlockArray->at(j).Plus(blockstart)); } *pbChanged = true; } @@ -225,16 +221,15 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) { // Invalidate all the old, non-aliased block files. // Aliased files will be converted at save, per comment above. - for (size_t i = 0; (i < mBlock->size() && bSuccess); i++) + for (size_t i = 0; (i < mBlock.size() && bSuccess); i++) { - BlockFile *& pOldFile = mBlock->at(i).f; + BlockFile *& pOldFile = mBlock.at(i).f; mDirManager->Deref(pOldFile); - pOldFile = NULL; //vvv ...so we don't delete the file when we delete mBlock, next. ANSWER-ME: Right, or delete? + pOldFile = NULL; //vvv ...so we don't delete the file when we swap mBlock, next. ANSWER-ME: Right, or delete? } - delete mBlock; // Replace with new blocks. - mBlock = pNewBlockArray; + mBlock.swap(newBlockArray); } else { @@ -247,7 +242,6 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) mMaxSamples = oldMaxSamples; */ - delete pNewBlockArray; // Failed. Throw out the scratch array. *pbChanged = false; // Revert overall change flag, in case we had some partial success in the loop. } @@ -259,7 +253,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) bool Sequence::GetMinMax(sampleCount start, sampleCount len, float * outMin, float * outMax) const { - if (len == 0 || mBlock->size() == 0) { + if (len == 0 || mBlock.size() == 0) { *outMin = float(0.0); // FLT_MAX? So it doesn't look like a spurious '0' to a caller? *outMax = float(0.0); // -FLT_MAX? So it doesn't look like a spurious '0' to a caller? return true; @@ -280,7 +274,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, for (b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; - mBlock->at(b).f->GetMinMax(&blockMin, &blockMax, &blockRMS); + mBlock.at(b).f->GetMinMax(&blockMin, &blockMax, &blockRMS); if (blockMin < min) min = blockMin; @@ -294,7 +288,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, // If not, we need read some samples and summaries from disk. { float block0Min, block0Max, block0RMS; - SeqBlock &theBlock = mBlock->at(block0); + const SeqBlock &theBlock = mBlock.at(block0); BlockFile *theFile = theBlock.f; theFile->GetMinMax(&block0Min, &block0Max, &block0RMS); @@ -318,7 +312,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, { float block1Min, block1Max, block1RMS; - SeqBlock &theBlock = mBlock->at(block1); + const SeqBlock &theBlock = mBlock.at(block1); BlockFile *theFile = theBlock.f; theFile->GetMinMax(&block1Min, &block1Max, &block1RMS); @@ -350,7 +344,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, { // len is the number of samples that we want the rms of. // it may be longer than a block, and the code is carefully set up to handle that. - if (len == 0 || mBlock->size() == 0) { + if (len == 0 || mBlock.size() == 0) { *outRMS = float(0.0); return true; } @@ -370,7 +364,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, for (b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; - const SeqBlock &theBlock = mBlock->at(b); + const SeqBlock &theBlock = mBlock.at(b); BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&blockMin, &blockMax, &blockRMS); @@ -383,7 +377,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, // selection may only partly overlap these blocks. // If not, we need read some samples and summaries from disk. { - const SeqBlock &theBlock = mBlock->at(block0); + const SeqBlock &theBlock = mBlock.at(block0); BlockFile *const theFile = theBlock.f; s0 = start - theBlock.start; l0 = len; @@ -400,7 +394,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, } if (block1 > block0) { - const SeqBlock &theBlock = mBlock->at(block1); + const SeqBlock &theBlock = mBlock.at(block1); BlockFile *const theFile = theBlock.f; s0 = 0; @@ -427,7 +421,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) if (s0 >= s1 || s0 >= mNumSamples || s1 < 0) return false; - int numBlocks = mBlock->size(); + int numBlocks = mBlock.size(); int b0 = FindBlock(s0); int b1 = FindBlock(s1); @@ -442,8 +436,8 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) // Do the first block - if (b0 >= 0 && b0 < numBlocks && s0 != mBlock->at(b0).start) { - const SeqBlock &block = mBlock->at(b0); + if (b0 >= 0 && b0 < numBlocks && s0 != mBlock.at(b0).start) { + const SeqBlock &block = mBlock.at(b0); BlockFile *const file = block.f; blocklen = block.start + file->GetLength() - s0; if (blocklen > (s1 - s0)) @@ -454,16 +448,16 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) (*dest)->Append(buffer, mSampleFormat, blocklen); } - if (b0 >= 0 && b0 < numBlocks && s0 == mBlock->at(b0).start) { + if (b0 >= 0 && b0 < numBlocks && s0 == mBlock.at(b0).start) { b0--; } // If there are blocks in the middle, copy the blockfiles directly for (int b = b0 + 1; b < b1; b++) - (*dest)->AppendBlock(mBlock->at(b)); + (*dest)->AppendBlock(mBlock.at(b)); // Do the last block if (b1 > b0 && b1 < numBlocks) { - const SeqBlock &block = mBlock->at(b1); + const SeqBlock &block = mBlock.at(b1); BlockFile *const file = block.f; blocklen = (s1 - block.start); wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 @@ -508,25 +502,25 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) return false; } - BlockArray *srcBlock = src->mBlock; + const BlockArray &srcBlock = src->mBlock; sampleCount addedLen = src->mNumSamples; - unsigned int srcNumBlocks = srcBlock->size(); + unsigned int srcNumBlocks = srcBlock.size(); int sampleSize = SAMPLE_SIZE(mSampleFormat); if (addedLen == 0 || srcNumBlocks == 0) return true; int b = FindBlock(s); - size_t numBlocks = mBlock->size(); + size_t numBlocks = mBlock.size(); if (numBlocks == 0 || - (s == mNumSamples && mBlock->at(numBlocks-1).f->GetLength() >= mMinSamples)) { + (s == mNumSamples && mBlock.at(numBlocks-1).f->GetLength() >= mMinSamples)) { // Special case: this track is currently empty, or it's safe to append // onto the end because the current last block is longer than the // minimum size for (unsigned int i = 0; i < srcNumBlocks; i++) - AppendBlock(srcBlock->at(i)); + AppendBlock(srcBlock.at(i)); return ConsistencyCheck(wxT("Paste branch one")); } @@ -534,7 +528,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) SeqBlock *pBlock; sampleCount length; if ((b >= 0 ) && (b < (int)numBlocks) - && (length = (pBlock = &mBlock->at(b))->f->GetLength()) + addedLen < mMaxSamples) { + && (length = (pBlock = &mBlock.at(b))->f->GetLength()) + addedLen < mMaxSamples) { // Special case: we can fit all of the new samples inside of // one block! @@ -565,7 +559,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) block.f = file; for (unsigned int i = b + 1; i < numBlocks; i++) - mBlock->at(i).start += addedLen; + mBlock.at(i).start += addedLen; mNumSamples += addedLen; @@ -578,16 +572,16 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // it's simplest to just lump all the data together // into one big block along with the split block, // then resplit it all - BlockArray *newBlock = new BlockArray(); - newBlock->reserve(numBlocks + srcNumBlocks + 2); + BlockArray newBlock; + newBlock.reserve(numBlocks + srcNumBlocks + 2); int newNumBlocks = 0; for (int i = 0; i < b; i++) { - newBlock->push_back(mBlock->at(i)); + newBlock.push_back(mBlock.at(i)); newNumBlocks++; } - SeqBlock &splitBlock = mBlock->at(b); + SeqBlock &splitBlock = mBlock.at(b); sampleCount splitLen = splitBlock.f->GetLength(); int splitPoint = s - splitBlock.start; @@ -607,7 +601,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->size(); i++) { - newBlock->push_back(split->at(i).Plus(splitBlock.start)); + newBlock.push_back(split->at(i).Plus(splitBlock.start)); newNumBlocks++; } delete split; @@ -621,7 +615,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // half of the split block. sampleCount srcFirstTwoLen = - srcBlock->at(0).f->GetLength() + srcBlock->at(1).f->GetLength(); + srcBlock.at(0).f->GetLength() + srcBlock.at(1).f->GetLength(); sampleCount leftLen = splitPoint + srcFirstTwoLen; samplePtr leftBuffer = NewSamples(leftLen, mSampleFormat); @@ -631,29 +625,28 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) BlockArray *split = Blockify(leftBuffer, leftLen); for (i = 0; i < split->size(); i++) { - newBlock->push_back(split->at(i).Plus(splitBlock.start)); + newBlock.push_back(split->at(i).Plus(splitBlock.start)); newNumBlocks++; } delete split; DeleteSamples(leftBuffer); for (i = 2; i < srcNumBlocks - 2; i++) { - const SeqBlock &block = srcBlock->at(i); + const SeqBlock &block = srcBlock.at(i); BlockFile *const file = mDirManager->CopyBlockFile(block.f); if (!file) { wxASSERT(false); // TODO: Handle this better, alert the user of failure. - delete newBlock; return false; } - newBlock->push_back(SeqBlock(file, block.start + s)); + newBlock.push_back(SeqBlock(file, block.start + s)); newNumBlocks++; } - const SeqBlock &penultimate = srcBlock->at(srcNumBlocks - 2); + const SeqBlock &penultimate = srcBlock.at(srcNumBlocks - 2); sampleCount srcLastTwoLen = penultimate.f->GetLength() + - srcBlock->at(srcNumBlocks - 1).f->GetLength(); + srcBlock.at(srcNumBlocks - 1).f->GetLength(); sampleCount rightSplit = splitBlock.f->GetLength() - splitPoint; sampleCount rightLen = rightSplit + srcLastTwoLen; @@ -668,7 +661,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) split = Blockify(rightBuffer, rightLen); for (i = 0; i < split->size(); i++) { - newBlock->push_back(split->at(i).Plus(pos)); + newBlock.push_back(split->at(i).Plus(pos)); newNumBlocks++; } delete split; @@ -680,12 +673,11 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // Copy remaining blocks to new block array and // swap the new block array in for the old for (i = b + 1; i < numBlocks; i++) { - newBlock->push_back(mBlock->at(i).Plus(addedLen)); + newBlock.push_back(mBlock.at(i).Plus(addedLen)); newNumBlocks++; } - delete mBlock; - mBlock = newBlock; + mBlock.swap(newBlock); mNumSamples += addedLen; @@ -717,7 +709,7 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len) while (len) { sampleCount l = (len > idealSamples ? idealSamples : len); - sTrack->mBlock->push_back(SeqBlock(new SilentBlockFile(l), pos)); + sTrack->mBlock.push_back(SeqBlock(new SilentBlockFile(l), pos)); pos += l; len -= l; @@ -747,7 +739,7 @@ bool Sequence::AppendAlias(wxString fullPath, mDirManager->NewAliasBlockFile(fullPath, start, len, channel), mNumSamples ); - mBlock->push_back(newBlock); + mBlock.push_back(newBlock); mNumSamples += newBlock.f->GetLength(); return true; @@ -764,13 +756,13 @@ bool Sequence::AppendCoded(wxString fName, sampleCount start, mDirManager->NewODDecodeBlockFile(fName, start, len, channel, decodeType), mNumSamples ); - mBlock->push_back(newBlock); + mBlock.push_back(newBlock); mNumSamples += newBlock.f->GetLength(); return true; } -bool Sequence::AppendBlock(SeqBlock &b) +bool Sequence::AppendBlock(const SeqBlock &b) { // Quick check to make sure that it doesn't overflow if (((double)mNumSamples) + ((double)b.f->GetLength()) > wxLL(9223372036854775807)) @@ -789,7 +781,7 @@ bool Sequence::AppendBlock(SeqBlock &b) //Don't need to Ref because it was done by CopyBlockFile, above... //mDirManager->Ref(newBlock.f); - mBlock->push_back(newBlock); + mBlock.push_back(newBlock); mNumSamples += newBlock.f->GetLength(); // Don't do a consistency check here because this @@ -802,8 +794,8 @@ bool Sequence::AppendBlock(SeqBlock &b) unsigned int Sequence::GetODFlags() { unsigned int ret = 0; - for (unsigned int i = 0; i < mBlock->size(); i++) { - BlockFile *const file = mBlock->at(i).f; + for (unsigned int i = 0; i < mBlock.size(); i++) { + BlockFile *const file = mBlock.at(i).f; if(!file->IsDataAvailable()) ret = ret|(static_cast(file))->GetDecodeType(); else if(!file->IsSummaryAvailable()) @@ -815,7 +807,7 @@ unsigned int Sequence::GetODFlags() sampleCount Sequence::GetBlockStart(sampleCount position) const { int b = FindBlock(position); - return mBlock->at(b).start; + return mBlock.at(b).start; } sampleCount Sequence::GetBestBlockSize(sampleCount start) const @@ -825,14 +817,14 @@ sampleCount Sequence::GetBestBlockSize(sampleCount start) const // sample. The value returned will always be nonzero and will be no larger // than the value of GetMaxBlockSize(); int b = FindBlock(start); - int numBlocks = mBlock->size(); + int numBlocks = mBlock.size(); - const SeqBlock &block = mBlock->at(b); + const SeqBlock &block = mBlock.at(b); sampleCount result = (block.start + block.f->GetLength() - start); sampleCount length; while(result < mMinSamples && b+1at(b+1).f->GetLength()) + result) <= mMaxSamples) { + ((length = mBlock.at(b+1).f->GetLength()) + result) <= mMaxSamples) { b++; result += length; } @@ -894,8 +886,8 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) } } // while - mBlock->push_back(wb); - mDirManager->SetLoadingTarget(mBlock, mBlock->size() - 1); + mBlock.push_back(wb); + mDirManager->SetLoadingTarget(&mBlock, mBlock.size() - 1); return true; } @@ -976,13 +968,13 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Make sure that the sequence is valid. // First, replace missing blockfiles with SilentBlockFiles unsigned int b; - for (b = 0; b < mBlock->size(); b++) { - SeqBlock &block = mBlock->at(b); + for (b = 0; b < mBlock.size(); b++) { + SeqBlock &block = mBlock.at(b); if (!block.f) { sampleCount len; - if (b < mBlock->size()-1) - len = mBlock->at(b+1).start - block.start; + if (b < mBlock.size()-1) + len = mBlock.at(b+1).start - block.start; else len = mNumSamples - block.start; @@ -1005,8 +997,8 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Next, make sure that start times and lengths are consistent sampleCount numSamples = 0; - for (b = 0; b < mBlock->size(); b++) { - SeqBlock &block = mBlock->at(b); + for (b = 0; b < mBlock.size(); b++) { + SeqBlock &block = mBlock.at(b); if (block.start != numSamples) { wxString sFileAndExtension = block.f->GetFileName().GetFullName(); if (sFileAndExtension.IsEmpty()) @@ -1053,8 +1045,8 @@ void Sequence::WriteXML(XMLWriter &xmlFile) xmlFile.WriteAttr(wxT("sampleformat"), mSampleFormat); xmlFile.WriteAttr(wxT("numsamples"), mNumSamples); - for (b = 0; b < mBlock->size(); b++) { - SeqBlock &bb = mBlock->at(b); + for (b = 0; b < mBlock.size(); b++) { + SeqBlock &bb = mBlock.at(b); // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451. // Also, don't check against mMaxSamples for AliasBlockFiles, because if you convert sample format, @@ -1086,7 +1078,7 @@ void Sequence::WriteXML(XMLWriter &xmlFile) int Sequence::FindBlock(sampleCount pos, sampleCount lo, sampleCount guess, sampleCount hi) const { - const SeqBlock &block = mBlock->at(guess); + const SeqBlock &block = mBlock.at(guess); wxASSERT(block.f->GetLength() > 0); wxASSERT(lo <= guess && guess <= hi && lo <= hi); @@ -1107,7 +1099,7 @@ int Sequence::FindBlock(sampleCount pos) const { wxASSERT(pos >= 0 && pos <= mNumSamples); - int numBlocks = mBlock->size(); + int numBlocks = mBlock.size(); if (pos == 0) return 0; @@ -1118,8 +1110,8 @@ int Sequence::FindBlock(sampleCount pos) const int rval = FindBlock(pos, 0, numBlocks / 2, numBlocks); wxASSERT(rval >= 0 && rval < numBlocks && - pos >= mBlock->at(rval).start && - pos < mBlock->at(rval).start + mBlock->at(rval).f->GetLength()); + pos >= mBlock.at(rval).start && + pos < mBlock.at(rval).start + mBlock.at(rval).f->GetLength()); return rval; } @@ -1182,7 +1174,7 @@ bool Sequence::Get(samplePtr buffer, sampleFormat format, int b = FindBlock(start); while (len) { - const SeqBlock &block = mBlock->at(b); + const SeqBlock &block = mBlock.at(b); sampleCount blen = block.start + block.f->GetLength() - start; if (blen > len) @@ -1224,7 +1216,7 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, int b = FindBlock(start); while (len) { - SeqBlock &block = mBlock->at(b); + SeqBlock &block = mBlock.at(b); int blen = block.start + block.f->GetLength() - start; if (blen > len) blen = len; @@ -1337,7 +1329,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, sampleCount whereNext = 0; // Loop over block files, opening and reading and closing each // not more than once - unsigned nBlocks = mBlock->size(); + unsigned nBlocks = mBlock.size(); const unsigned int block0 = FindBlock(s0); for (unsigned int b = block0; b < nBlocks; ++b) { if (b > block0) @@ -1347,7 +1339,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, // Find the range of sample values for this block that // are in the display. - SeqBlock &seqBlock = mBlock->at(b); + SeqBlock &seqBlock = mBlock.at(b); const sampleCount start = seqBlock.start; nextSrcX = std::min(s1, start + seqBlock.f->GetLength()); @@ -1510,14 +1502,14 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, sampleCount Sequence::GetIdealAppendLen() { - int numBlocks = mBlock->size(); + int numBlocks = mBlock.size(); sampleCount max = GetMaxBlockSize(); sampleCount lastBlockLen; if (numBlocks == 0) return max; - lastBlockLen = mBlock->at(numBlocks-1).f->GetLength(); + lastBlockLen = mBlock.at(numBlocks-1).f->GetLength(); if (lastBlockLen == max) return max; else @@ -1532,12 +1524,12 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, return false; // If the last block is not full, we need to add samples to it - int numBlocks = mBlock->size(); + int numBlocks = mBlock.size(); sampleCount length; SeqBlock *pLastBlock; if (numBlocks > 0 && (length = - (pLastBlock = &mBlock->at(numBlocks - 1))->f->GetLength()) < mMinSamples) { + (pLastBlock = &mBlock.at(numBlocks - 1))->f->GetLength()) < mMinSamples) { SeqBlock &lastBlock = *pLastBlock; sampleCount addLen; if (length + len < mMaxSamples) @@ -1606,7 +1598,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, if (blockFileLog) static_cast(pFile)->SaveXML(*blockFileLog); - mBlock->push_back(SeqBlock(pFile, mNumSamples)); + mBlock.push_back(SeqBlock(pFile, mNumSamples)); buffer += l * SAMPLE_SIZE(format); mNumSamples += l; @@ -1664,7 +1656,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) //both functions, LockDeleteUpdateMutex(); - unsigned int numBlocks = mBlock->size(); + unsigned int numBlocks = mBlock.size(); unsigned int newNumBlocks = 0; unsigned int b0 = FindBlock(start); @@ -1677,7 +1669,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // deletion within this block: SeqBlock *pBlock; sampleCount length; - if (b0 == b1 && (length = (pBlock = &mBlock->at(b0))->f->GetLength()) - len >= mMinSamples) { + if (b0 == b1 && (length = (pBlock = &mBlock.at(b0))->f->GetLength()) - len >= mMinSamples) { SeqBlock &b = *pBlock; sampleCount pos = start - b.start; sampleCount newLen = length - len; @@ -1695,7 +1687,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) ); for (unsigned int j = b0 + 1; j < numBlocks; j++) - mBlock->at(j).start -= len; + mBlock.at(j).start -= len; DeleteSamples(buffer); @@ -1708,14 +1700,14 @@ bool Sequence::Delete(sampleCount start, sampleCount len) } // Create a new array of blocks - BlockArray *newBlock = new BlockArray(); - newBlock->reserve(numBlocks - (b1 - b0) + 2); + BlockArray newBlock; + newBlock.reserve(numBlocks - (b1 - b0) + 2); // Copy the blocks before the deletion point over to // the new array unsigned int i; for (i = 0; i < b0; i++) { - newBlock->push_back(mBlock->at(i)); + newBlock.push_back(mBlock.at(i)); newNumBlocks++; } @@ -1724,7 +1716,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). - SeqBlock &preBlock = mBlock->at(b0); + SeqBlock &preBlock = mBlock.at(b0); sampleCount preBufferLen = start - preBlock.start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { @@ -1734,14 +1726,14 @@ bool Sequence::Delete(sampleCount start, sampleCount len) mDirManager->NewSimpleBlockFile(preBuffer, preBufferLen, mSampleFormat); DeleteSamples(preBuffer); - newBlock->push_back(SeqBlock(pFile, preBlock.start)); + newBlock.push_back(SeqBlock(pFile, preBlock.start)); newNumBlocks++; if (b0 != b1) { mDirManager->Deref(preBlock.f); } } else { - SeqBlock &prepreBlock = mBlock->at(b0 - 1); + SeqBlock &prepreBlock = mBlock.at(b0 - 1); sampleCount prepreLen = prepreBlock.f->GetLength(); sampleCount sum = prepreLen + preBufferLen; @@ -1752,9 +1744,9 @@ bool Sequence::Delete(sampleCount start, sampleCount len) preBlock, 0, preBufferLen); BlockArray *split = Blockify(sumBuffer, sum); - newBlock->at(b0 - 1) = split->at(0).Plus(prepreBlock.start); + newBlock.at(b0 - 1) = split->at(0).Plus(prepreBlock.start); for (i = 1; i < split->size(); i++) { - newBlock->push_back(split->at(i).Plus(prepreBlock.start)); + newBlock.push_back(split->at(i).Plus(prepreBlock.start)); newNumBlocks++; } delete split; @@ -1777,7 +1769,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Next, delete blocks strictly between b0 and b1 for (i = b0 + 1; i < b1; i++) { - mDirManager->Deref(mBlock->at(i).f); + mDirManager->Deref(mBlock.at(i).f); } // Now, symmetrically, grab the samples in block b1 after the @@ -1785,7 +1777,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). - SeqBlock &postBlock = mBlock->at(b1); + SeqBlock &postBlock = mBlock.at(b1); sampleCount postBufferLen = (postBlock.start + postBlock.f->GetLength()) - (start + len); if (postBufferLen) { @@ -1798,12 +1790,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(postBuffer); - newBlock->push_back(SeqBlock(file, start)); + newBlock.push_back(SeqBlock(file, start)); newNumBlocks++; mDirManager->Deref(postBlock.f); } else { - SeqBlock &postpostBlock = mBlock->at(b1 + 1); + SeqBlock &postpostBlock = mBlock.at(b1 + 1); sampleCount postpostLen = postpostBlock.f->GetLength(); sampleCount sum = postpostLen + postBufferLen; @@ -1815,7 +1807,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) BlockArray *split = Blockify(sumBuffer, sum); for (i = 0; i < split->size(); i++) { - newBlock->push_back(split->at(i).Plus(start)); + newBlock.push_back(split->at(i).Plus(start)); newNumBlocks++; } delete split; @@ -1834,13 +1826,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) { - newBlock->push_back(mBlock->at(i).Plus(-len)); + newBlock.push_back(mBlock.at(i).Plus(-len)); newNumBlocks++; } // Substitute our new array for the old one - delete mBlock; - mBlock = newBlock; + mBlock.swap(newBlock); // Update total number of samples and do a consistency check. mNumSamples -= len; @@ -1853,11 +1844,11 @@ bool Sequence::ConsistencyCheck(const wxChar *whereStr) { unsigned int i; sampleCount pos = 0; - unsigned int numBlocks = mBlock->size(); + unsigned int numBlocks = mBlock.size(); bool bError = false; for (i = 0; i < numBlocks; i++) { - SeqBlock &seqBlock = mBlock->at(i); + SeqBlock &seqBlock = mBlock.at(i); if (pos != seqBlock.start) bError = true; @@ -1886,8 +1877,8 @@ void Sequence::DebugPrintf(wxString *dest) unsigned int i; int pos = 0; - for (i = 0; i < mBlock->size(); i++) { - SeqBlock &seqBlock = mBlock->at(i); + for (i = 0; i < mBlock.size(); i++) { + SeqBlock &seqBlock = mBlock.at(i); *dest += wxString::Format (wxT(" Block %3u: start %8lld, len %8lld, refs %d, "), i, @@ -1926,7 +1917,7 @@ int Sequence::GetMaxDiskBlockSize() void Sequence::AppendBlockFile(BlockFile* blockFile) { - mBlock->push_back(SeqBlock(blockFile, mNumSamples)); + mBlock.push_back(SeqBlock(blockFile, mNumSamples)); mNumSamples += blockFile->GetLength(); #ifdef VERY_SLOW_CHECKING diff --git a/src/Sequence.h b/src/Sequence.h index 9a4232b14..f460af796 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -188,7 +188,7 @@ class Sequence: public XMLTagHandler { // you're doing! // - BlockArray *GetBlockArray() {return mBlock;} + BlockArray &GetBlockArray() {return mBlock;} /// void LockDeleteUpdateMutex(){mDeleteUpdateMutex.Lock();} @@ -208,7 +208,7 @@ class Sequence: public XMLTagHandler { DirManager *mDirManager; - BlockArray *mBlock; + BlockArray mBlock; sampleFormat mSampleFormat; sampleCount mNumSamples; @@ -230,7 +230,7 @@ class Sequence: public XMLTagHandler { int FindBlock(sampleCount pos, sampleCount lo, sampleCount guess, sampleCount hi) const; - bool AppendBlock(SeqBlock &b); + bool AppendBlock(const SeqBlock &b); bool Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 8dd55982a..56171ad7b 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -366,7 +366,7 @@ bool WaveClip::SetSamples(samplePtr buffer, sampleFormat format, BlockArray* WaveClip::GetSequenceBlockArray() { - return mSequence->GetBlockArray(); + return &mSequence->GetBlockArray(); } double WaveClip::GetStartTime() const From 7be911b7fbc984d4f564bd8afc57738b41565b98 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 30 Jan 2016 13:18:38 -0500 Subject: [PATCH 03/16] Simplify the use of Sequence::Blockify() --- src/Sequence.cpp | 96 ++++++++++++------------------------------------ src/Sequence.h | 2 +- 2 files changed, 24 insertions(+), 74 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 5afc517af..28ddd5cbe 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -200,18 +200,12 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) // from the old blocks... Oh no! // Using Blockify will handle the cases where len > the new mMaxSamples. Previous code did not. - BlockArray* pSplitBlockArray = Blockify(bufferNew, len); - bSuccess = (pSplitBlockArray->size() > 0); + const sampleCount blockstart = oldSeqBlock.start; + const unsigned prevSize = newBlockArray.size(); + Blockify(newBlockArray, blockstart, bufferNew, len); + bSuccess = (newBlockArray.size() > prevSize); if (bSuccess) - { - const sampleCount blockstart = mBlock.at(i).start; - for (size_t j = 0; j < pSplitBlockArray->size(); j++) - { - newBlockArray.push_back(pSplitBlockArray->at(j).Plus(blockstart)); - } *pbChanged = true; - } - delete pSplitBlockArray; DeleteSamples(bufferNew); DeleteSamples(bufferOld); @@ -574,12 +568,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // then resplit it all BlockArray newBlock; newBlock.reserve(numBlocks + srcNumBlocks + 2); - int newNumBlocks = 0; - - for (int i = 0; i < b; i++) { - newBlock.push_back(mBlock.at(i)); - newNumBlocks++; - } + newBlock.insert(newBlock.end(), mBlock.begin(), mBlock.begin() + b); SeqBlock &splitBlock = mBlock.at(b); sampleCount splitLen = splitBlock.f->GetLength(); @@ -599,12 +588,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) splitBlock, splitPoint, splitLen - splitPoint); - BlockArray *split = Blockify(sumBuffer, sum); - for (i = 0; i < split->size(); i++) { - newBlock.push_back(split->at(i).Plus(splitBlock.start)); - newNumBlocks++; - } - delete split; + Blockify(newBlock, splitBlock.start, sumBuffer, sum); DeleteSamples(sumBuffer); } else { @@ -623,12 +607,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) src->Get(leftBuffer + splitPoint*sampleSize, mSampleFormat, 0, srcFirstTwoLen); - BlockArray *split = Blockify(leftBuffer, leftLen); - for (i = 0; i < split->size(); i++) { - newBlock.push_back(split->at(i).Plus(splitBlock.start)); - newNumBlocks++; - } - delete split; + Blockify(newBlock, splitBlock.start, leftBuffer, leftLen); DeleteSamples(leftBuffer); for (i = 2; i < srcNumBlocks - 2; i++) { @@ -640,7 +619,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) } newBlock.push_back(SeqBlock(file, block.start + s)); - newNumBlocks++; } const SeqBlock &penultimate = srcBlock.at(srcNumBlocks - 2); @@ -659,12 +637,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) sampleCount pos = s + lastStart; - split = Blockify(rightBuffer, rightLen); - for (i = 0; i < split->size(); i++) { - newBlock.push_back(split->at(i).Plus(pos)); - newNumBlocks++; - } - delete split; + Blockify(newBlock, pos, rightBuffer, rightLen); DeleteSamples(rightBuffer); } @@ -672,10 +645,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // Copy remaining blocks to new block array and // swap the new block array in for the old - for (i = b + 1; i < numBlocks; i++) { + for (i = b + 1; i < numBlocks; i++) newBlock.push_back(mBlock.at(i).Plus(addedLen)); - newNumBlocks++; - } mBlock.swap(newBlock); @@ -1617,29 +1588,26 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, return true; } -BlockArray *Sequence::Blockify(samplePtr buffer, sampleCount len) +void Sequence::Blockify(BlockArray &list, sampleCount start, samplePtr buffer, sampleCount len) { - BlockArray *list = new BlockArray(); if (len <= 0) - return list; + return; - list->reserve(10); - - int num = (len + (mMaxSamples - 1)) / mMaxSamples; + const int num = (len + (mMaxSamples - 1)) / mMaxSamples; + list.reserve(list.size() + num); for (int i = 0; i < num; i++) { SeqBlock b; - b.start = i * len / num; - int newLen = ((i + 1) * len / num) - b.start; - samplePtr bufStart = buffer + (b.start * SAMPLE_SIZE(mSampleFormat)); + const sampleCount offset = i * len / num; + b.start = start + offset; + int newLen = ((i + 1) * len / num) - offset; + samplePtr bufStart = buffer + (offset * SAMPLE_SIZE(mSampleFormat)); b.f = mDirManager->NewSimpleBlockFile(bufStart, newLen, mSampleFormat); - list->push_back(b); + list.push_back(b); } - - return list; } bool Sequence::Delete(sampleCount start, sampleCount len) @@ -1657,7 +1625,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len) LockDeleteUpdateMutex(); unsigned int numBlocks = mBlock.size(); - unsigned int newNumBlocks = 0; unsigned int b0 = FindBlock(start); unsigned int b1 = FindBlock(start + len - 1); @@ -1705,11 +1672,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Copy the blocks before the deletion point over to // the new array + newBlock.insert(newBlock.end(), mBlock.begin(), mBlock.begin() + b0); unsigned int i; - for (i = 0; i < b0; i++) { - newBlock.push_back(mBlock.at(i)); - newNumBlocks++; - } // First grab the samples in block b0 before the deletion point // into preBuffer. If this is enough samples for its own block, @@ -1727,7 +1691,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(preBuffer); newBlock.push_back(SeqBlock(pFile, preBlock.start)); - newNumBlocks++; if (b0 != b1) { mDirManager->Deref(preBlock.f); @@ -1743,13 +1706,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len) Read(sumBuffer + prepreLen*sampleSize, mSampleFormat, preBlock, 0, preBufferLen); - BlockArray *split = Blockify(sumBuffer, sum); - newBlock.at(b0 - 1) = split->at(0).Plus(prepreBlock.start); - for (i = 1; i < split->size(); i++) { - newBlock.push_back(split->at(i).Plus(prepreBlock.start)); - newNumBlocks++; - } - delete split; + newBlock.erase(newBlock.end() - 1); + Blockify(newBlock, prepreBlock.start, sumBuffer, sum); DeleteSamples(sumBuffer); @@ -1791,7 +1749,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(postBuffer); newBlock.push_back(SeqBlock(file, start)); - newNumBlocks++; mDirManager->Deref(postBlock.f); } else { @@ -1805,12 +1762,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) Read(sumBuffer + (postBufferLen * sampleSize), mSampleFormat, postpostBlock, 0, postpostLen); - BlockArray *split = Blockify(sumBuffer, sum); - for (i = 0; i < split->size(); i++) { - newBlock.push_back(split->at(i).Plus(start)); - newNumBlocks++; - } - delete split; + Blockify(newBlock, start, sumBuffer, sum); b1++; DeleteSamples(sumBuffer); @@ -1825,10 +1777,8 @@ bool Sequence::Delete(sampleCount start, sampleCount len) } // Copy the remaining blocks over from the old array - for (i = b1 + 1; i < numBlocks; i++) { + for (i = b1 + 1; i < numBlocks; i++) newBlock.push_back(mBlock.at(i).Plus(-len)); - newNumBlocks++; - } // Substitute our new array for the old one mBlock.swap(newBlock); diff --git a/src/Sequence.h b/src/Sequence.h index f460af796..4cee5a9af 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -246,7 +246,7 @@ class Sequence: public XMLTagHandler { void *GetSummary(samplePtr buffer, sampleCount len, float *min, float *max, float *rms); - BlockArray *Blockify(samplePtr buffer, sampleCount len); + void Blockify(BlockArray &list, sampleCount start, samplePtr buffer, sampleCount len); public: From 13f7d0a81be789437efd0638d563ba21df837054 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 12:56:21 -0500 Subject: [PATCH 04/16] Added consistency checks for Sequence, hoisted out of inner loops. --- src/AutoRecovery.cpp | 63 +++++++++++++++++++++++++++++++++----------- src/AutoRecovery.h | 4 +++ src/Sequence.cpp | 7 +++-- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/AutoRecovery.cpp b/src/AutoRecovery.cpp index dd193c356..00e1f33f7 100644 --- a/src/AutoRecovery.cpp +++ b/src/AutoRecovery.cpp @@ -283,6 +283,28 @@ RecordingRecoveryHandler::RecordingRecoveryHandler(AudacityProject* proj) mNumChannels = -1; } +int RecordingRecoveryHandler::FindTrack() const +{ + WaveTrackArray tracks = mProject->GetTracks()->GetWaveTrackArray(false); + int index; + if (mAutoSaveIdent) + { + for (index = 0; index < (int)tracks.GetCount(); index++) + { + if (tracks[index]->GetAutoSaveIdent() == mAutoSaveIdent) + { + break; + } + } + } + else + { + index = tracks.GetCount() - mNumChannels + mChannel; + } + + return index; +} + bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, const wxChar **attrs) { @@ -296,23 +318,9 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, return false; } - // We need to find the track and sequence where the blockfile belongs WaveTrackArray tracks = mProject->GetTracks()->GetWaveTrackArray(false); - int index; - if (mAutoSaveIdent) - { - for (index = 0; index < (int) tracks.GetCount(); index++) - { - if (tracks[index]->GetAutoSaveIdent() == mAutoSaveIdent) - { - break; - } - } - } - else - { - index = tracks.GetCount() - mNumChannels + mChannel; - } + int index = FindTrack(); + // We need to find the track and sequence where the blockfile belongs if (index < 0 || index >= (int) tracks.GetCount()) { @@ -391,6 +399,29 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, return true; } +void RecordingRecoveryHandler::HandleXMLEndTag(const wxChar *tag) +{ + if (wxStrcmp(tag, wxT("simpleblockfile")) == 0) + // Still in inner looop + return; + + WaveTrackArray tracks = mProject->GetTracks()->GetWaveTrackArray(false); + int index = FindTrack(); + // We need to find the track and sequence where the blockfile belongs + + if (index < 0 || index >= (int)tracks.GetCount()) { + // This should only happen if there is a bug + wxASSERT(false); + } + else { + WaveTrack* track = tracks.Item(index); + WaveClip* clip = track->NewestOrNewClip(); + Sequence* seq = clip->GetSequence(); + + seq->ConsistencyCheck(wxT("RecordingRecoveryHandler::HandleXMLEndTag")); + } +} + XMLTagHandler* RecordingRecoveryHandler::HandleXMLChild(const wxChar *tag) { if (wxStrcmp(tag, wxT("simpleblockfile")) == 0) diff --git a/src/AutoRecovery.h b/src/AutoRecovery.h index 8d5ee548b..66239401e 100644 --- a/src/AutoRecovery.h +++ b/src/AutoRecovery.h @@ -46,12 +46,16 @@ class RecordingRecoveryHandler: public XMLTagHandler public: RecordingRecoveryHandler(AudacityProject* proj); virtual bool HandleXMLTag(const wxChar *tag, const wxChar **attrs); + virtual void HandleXMLEndTag(const wxChar *tag); virtual XMLTagHandler *HandleXMLChild(const wxChar *tag); // This class only knows reading tags virtual void WriteXML(XMLWriter & WXUNUSED(xmlFile)) { wxASSERT(false); } private: + + int FindTrack() const; + AudacityProject* mProject; int mChannel; int mNumChannels; diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 28ddd5cbe..1c23ba2e6 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -461,7 +461,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) DeleteSamples(buffer); - return true; + return ConsistencyCheck(wxT("Sequence::Copy()")); } bool Sequence::Paste(sampleCount s, const Sequence *src) @@ -756,7 +756,7 @@ bool Sequence::AppendBlock(const SeqBlock &b) mNumSamples += newBlock.f->GetLength(); // Don't do a consistency check here because this - // function gets called in an inner loop + // function gets called in an inner loop. return true; } @@ -1870,6 +1870,9 @@ void Sequence::AppendBlockFile(BlockFile* blockFile) mBlock.push_back(SeqBlock(blockFile, mNumSamples)); mNumSamples += blockFile->GetLength(); + // PRL: I hoisted the intended consistency check out of the inner loop + // See RecordingRecoveryHandler::HandleXMLEndTag + #ifdef VERY_SLOW_CHECKING ConsistencyCheck(wxT("AppendBlockFile")); #endif From 6c28276dafe83bcc5cee0c0b68b5882857578c1b Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 12:58:30 -0500 Subject: [PATCH 05/16] Use RAII idiom for lock and locking mutex in Sequence --- src/Sequence.cpp | 4 +--- src/Sequence.h | 15 +++++++++++++++ src/ondemand/ODComputeSummaryTask.cpp | 3 +-- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 1c23ba2e6..594e3a32e 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -1622,7 +1622,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) //TODO: add a ref-deref mechanism to SeqBlock/BlockArray so we don't have to make this a critical section. //On-demand threads iterate over the mBlocks and the GUI thread deletes them, so for now put a mutex here over //both functions, - LockDeleteUpdateMutex(); + DeleteUpdateMutexLocker locker(*this); unsigned int numBlocks = mBlock.size(); @@ -1661,7 +1661,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len) mDirManager->Deref(oldFile); mNumSamples -= len; - UnlockDeleteUpdateMutex(); return ConsistencyCheck(wxT("Delete - branch one")); } @@ -1786,7 +1785,6 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Update total number of samples and do a consistency check. mNumSamples -= len; - UnlockDeleteUpdateMutex(); return ConsistencyCheck(wxT("Delete - branch two")); } diff --git a/src/Sequence.h b/src/Sequence.h index 4cee5a9af..a257869ce 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -194,6 +194,21 @@ class Sequence: public XMLTagHandler { void LockDeleteUpdateMutex(){mDeleteUpdateMutex.Lock();} void UnlockDeleteUpdateMutex(){mDeleteUpdateMutex.Unlock();} + // RAII idiom wrapping the functions above + struct DeleteUpdateMutexLocker { + DeleteUpdateMutexLocker(Sequence &sequence) + : mSequence(sequence) + { + mSequence.LockDeleteUpdateMutex(); + } + ~DeleteUpdateMutexLocker() + { + mSequence.UnlockDeleteUpdateMutex(); + } + private: + Sequence &mSequence; + }; + private: // diff --git a/src/ondemand/ODComputeSummaryTask.cpp b/src/ondemand/ODComputeSummaryTask.cpp index 0c10d99eb..1d818fb03 100644 --- a/src/ondemand/ODComputeSummaryTask.cpp +++ b/src/ondemand/ODComputeSummaryTask.cpp @@ -190,7 +190,7 @@ void ODComputeSummaryTask::Update() seq = clip->GetSequence(); //This lock may be way too big since the whole file is one sequence. //TODO: test for large files and find a way to break it down. - seq->LockDeleteUpdateMutex(); + Sequence::DeleteUpdateMutexLocker locker(*seq); //See Sequence::Delete() for why need this for now.. //We don't need the mBlockFilesMutex here because it is only for the vector list. @@ -223,7 +223,6 @@ void ODComputeSummaryTask::Update() tempBlocks.insert(tempBlocks.begin() + insertCursor++, odpcmaFile); } } - seq->UnlockDeleteUpdateMutex(); node = node->GetNext(); } } From e6987284e3b4511e0efb02797ff4f087977d27ad Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 12:59:44 -0500 Subject: [PATCH 06/16] Rewrote Sequence::FindBlock, without recursion, and with dictionary search --- src/Sequence.cpp | 60 +++++++++++++++++++++++++++--------------------- src/Sequence.h | 2 -- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 594e3a32e..d2e820285 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -1046,40 +1046,48 @@ void Sequence::WriteXML(XMLWriter &xmlFile) xmlFile.EndTag(wxT("sequence")); } -int Sequence::FindBlock(sampleCount pos, sampleCount lo, - sampleCount guess, sampleCount hi) const -{ - const SeqBlock &block = mBlock.at(guess); - wxASSERT(block.f->GetLength() > 0); - wxASSERT(lo <= guess && guess <= hi && lo <= hi); - - if (pos >= block.start && - pos < block.start + block.f->GetLength()) - return guess; - - //this is a binary search, but we probably could benefit by something more like - //dictionary search where we guess something smarter than the binary division - //of the unsearched area, since samples are usually proportional to block file number. - if (pos < block.start) - return FindBlock(pos, lo, (lo + guess) / 2, guess); - else - return FindBlock(pos, guess + 1, (guess + 1 + hi) / 2, hi); -} - int Sequence::FindBlock(sampleCount pos) const { - wxASSERT(pos >= 0 && pos <= mNumSamples); - - int numBlocks = mBlock.size(); + wxASSERT(pos >= 0 && pos < mNumSamples); if (pos == 0) return 0; - if (pos == mNumSamples) - return (numBlocks - 1); + int numBlocks = mBlock.size(); - int rval = FindBlock(pos, 0, numBlocks / 2, numBlocks); + sampleCount lo = 0, loSamples = 0; + sampleCount hi = numBlocks, hiSamples = mNumSamples; + sampleCount guess; + while (true) { + //this is not a binary search, but a + //dictionary search where we guess something smarter than the binary division + //of the unsearched area, since samples are usually proportional to block file number. + const double frac = double(pos - loSamples) / (hiSamples - loSamples); + guess = std::min(hi - 1, lo + sampleCount(frac * (hi - lo))); + const SeqBlock &block = mBlock.at(guess); + + wxASSERT(block.f->GetLength() > 0); + wxASSERT(lo <= guess && guess < hi && lo < hi); + + if (pos < block.start) { + wxASSERT(lo != guess); + hi = guess; + hiSamples = block.start; + } + else { + const sampleCount nextStart = block.start + block.f->GetLength(); + if (pos < nextStart) + break; + else { + wxASSERT(guess < hi - 1); + lo = guess + 1; + loSamples = nextStart; + } + } + } + + const int rval = guess; wxASSERT(rval >= 0 && rval < numBlocks && pos >= mBlock.at(rval).start && pos < mBlock.at(rval).start + mBlock.at(rval).f->GetLength()); diff --git a/src/Sequence.h b/src/Sequence.h index a257869ce..954f14265 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -242,8 +242,6 @@ class Sequence: public XMLTagHandler { void CalcSummaryInfo(); int FindBlock(sampleCount pos) const; - int FindBlock(sampleCount pos, sampleCount lo, - sampleCount guess, sampleCount hi) const; bool AppendBlock(const SeqBlock &b); From ca56876aaffd87fb766441c5b251810b67874197 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 13:01:55 -0500 Subject: [PATCH 07/16] Various minor fixes in Sequence --- src/DirManager.h | 5 +- src/Sequence.cpp | 397 ++++++++++++++++++++++++----------------------- src/Sequence.h | 24 +-- src/WaveClip.cpp | 2 +- 4 files changed, 218 insertions(+), 210 deletions(-) diff --git a/src/DirManager.h b/src/DirManager.h index 9c0330844..2ab32d078 100644 --- a/src/DirManager.h +++ b/src/DirManager.h @@ -109,7 +109,10 @@ class DirManager: public XMLTagHandler { } void SetLoadingFormat(sampleFormat format) { mLoadingFormat = format; } void SetLoadingBlockLength(sampleCount len) { mLoadingBlockLen = len; } - void SetMaxSamples(sampleCount max) { mMaxSamples = max; } + + // Note: following affects only the loading of block files when opening a project + void SetLoadingMaxSamples(sampleCount max) { mMaxSamples = max; } + bool HandleXMLTag(const wxChar *tag, const wxChar **attrs); XMLTagHandler *HandleXMLChild(const wxChar * WXUNUSED(tag)) { return NULL; } void WriteXML(XMLWriter & WXUNUSED(xmlFile)) { wxASSERT(false); } // This class only reads tags. diff --git a/src/Sequence.cpp b/src/Sequence.cpp index d2e820285..642326e49 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -53,30 +53,28 @@ int Sequence::sMaxDiskBlockSize = 1048576; // Sequence methods Sequence::Sequence(DirManager * projDirManager, sampleFormat format) + : mDirManager(projDirManager) + , mSampleFormat(format) + , mNumSamples(0) + , mMinSamples(sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2) + , mMaxSamples(mMinSamples * 2) + , mErrorOpening(false) { - mDirManager = projDirManager; mDirManager->Ref(); - mNumSamples = 0; - mSampleFormat = format; - - mMinSamples = sMaxDiskBlockSize / SAMPLE_SIZE(mSampleFormat) / 2; - mMaxSamples = mMinSamples * 2; - mErrorOpening = false; } +// essentially a copy constructor - but you must pass in the +// current project's DirManager, because we might be copying +// from one project to another Sequence::Sequence(const Sequence &orig, DirManager *projDirManager) + : mDirManager(projDirManager) + , mNumSamples(0) + , mSampleFormat(orig.mSampleFormat) + , mMinSamples(orig.mMinSamples) + , mMaxSamples(orig.mMaxSamples) + , mErrorOpening(false) { - // essentially a copy constructor - but you must pass in the - // current project's DirManager, because we might be copying - // from one project to another - - mDirManager = projDirManager; mDirManager->Ref(); - mNumSamples = 0; - mSampleFormat = orig.mSampleFormat; - mMaxSamples = orig.mMaxSamples; - mMinSamples = orig.mMinSamples; - mErrorOpening = false; bool bResult = Paste(0, &orig); wxASSERT(bResult); // TO DO: Actually handle this. @@ -85,15 +83,22 @@ Sequence::Sequence(const Sequence &orig, DirManager *projDirManager) Sequence::~Sequence() { - for (unsigned int i = 0; i < mBlock.size(); i++) { - BlockFile *const file = mBlock.at(i).f; - if (file) - mDirManager->Deref(file); - } - + DerefAllFiles(); mDirManager->Deref(); } +void Sequence::DerefAllFiles() +{ + for (size_t i = 0, nn = mBlock.size(); i < nn; i++) + { + BlockFile *& pOldFile = mBlock.at(i).f; + if (pOldFile) { + mDirManager->Deref(pOldFile); + pOldFile = NULL; + } + } +} + sampleCount Sequence::GetMaxBlockSize() const { return mMaxSamples; @@ -133,6 +138,7 @@ sampleFormat Sequence::GetSampleFormat() const return mSampleFormat; } +/* bool Sequence::SetSampleFormat(sampleFormat format) { if (mBlock.size() > 0 || mNumSamples > 0) @@ -141,6 +147,7 @@ bool Sequence::SetSampleFormat(sampleFormat format) mSampleFormat = format; return true; } +*/ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) { @@ -171,7 +178,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) newBlockArray.reserve(mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples)); bool bSuccess = true; - for (size_t i = 0; (i < mBlock.size() && bSuccess); i++) + for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++) { SeqBlock &oldSeqBlock = mBlock.at(i); BlockFile* oldBlockFile = oldSeqBlock.f; @@ -215,12 +222,8 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) { // Invalidate all the old, non-aliased block files. // Aliased files will be converted at save, per comment above. - for (size_t i = 0; (i < mBlock.size() && bSuccess); i++) - { - BlockFile *& pOldFile = mBlock.at(i).f; - mDirManager->Deref(pOldFile); - pOldFile = NULL; //vvv ...so we don't delete the file when we swap mBlock, next. ANSWER-ME: Right, or delete? - } + + DerefAllFiles(); // Replace with new blocks. mBlock.swap(newBlockArray); @@ -257,16 +260,15 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, float max = -FLT_MAX; unsigned int block0 = FindBlock(start); - unsigned int block1 = FindBlock(start + len); + unsigned int block1 = FindBlock(start + len - 1); sampleCount s0, l0, maxl0; // First calculate the min/max of the blocks in the middle of this region; // this is very fast because we have the min/max of every entire block // already in memory. - unsigned int b; - for (b = block0 + 1; b < block1; b++) { + for (unsigned b = block0 + 1; b < block1; ++b) { float blockMin, blockMax, blockRMS; mBlock.at(b).f->GetMinMax(&blockMin, &blockMax, &blockRMS); @@ -283,7 +285,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, { float block0Min, block0Max, block0RMS; const SeqBlock &theBlock = mBlock.at(block0); - BlockFile *theFile = theBlock.f; + BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&block0Min, &block0Max, &block0RMS); if (block0Min < min || block0Max > max) { @@ -304,14 +306,14 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, } } + if (block1 > block0) { float block1Min, block1Max, block1RMS; const SeqBlock &theBlock = mBlock.at(block1); - BlockFile *theFile = theBlock.f; + BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&block1Min, &block1Max, &block1RMS); - if (block1 > block0 && - (block1Min < min || block1Max > max)) { + if (block1Min < min || block1Max > max) { s0 = 0; l0 = (start + len) - theBlock.start; @@ -347,16 +349,14 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, sampleCount length = 0; // this is the cumulative length of the bits we have the ms of so far, and should end up == len unsigned int block0 = FindBlock(start); - unsigned int block1 = FindBlock(start + len); + unsigned int block1 = FindBlock(start + len - 1); sampleCount s0, l0, maxl0; // First calculate the rms of the blocks in the middle of this region; // this is very fast because we have the rms of every entire block // already in memory. - unsigned int b; - - for (b = block0 + 1; b < block1; b++) { + for (unsigned b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; const SeqBlock &theBlock = mBlock.at(b); BlockFile *const theFile = theBlock.f; @@ -393,6 +393,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, s0 = 0; l0 = (start + len) - theBlock.start; + wxASSERT(l0 <= mMaxSamples); // PRL: I think Vaughan missed this float partialMin, partialMax, partialRMS; theFile->GetMinMax(s0, l0, &partialMin, &partialMax, &partialRMS); @@ -412,17 +413,19 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) { *dest = 0; - if (s0 >= s1 || s0 >= mNumSamples || s1 < 0) + if (s0 >= s1 || s0 >= mNumSamples || s1 >= mNumSamples || s1 < 0) return false; int numBlocks = mBlock.size(); int b0 = FindBlock(s0); - int b1 = FindBlock(s1); - - if (s1 == mNumSamples) - b1 = numBlocks; + const int b1 = FindBlock(s1 - 1); + wxASSERT(b0 >= 0); + wxASSERT(b0 < numBlocks); + wxASSERT(b1 < numBlocks); + wxASSERT(b0 <= b1); *dest = new Sequence(mDirManager, mSampleFormat); + (*dest)->mBlock.reserve(b1 - b0 + 1); samplePtr buffer = NewSamples(mMaxSamples, mSampleFormat); @@ -430,33 +433,35 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) // Do the first block - if (b0 >= 0 && b0 < numBlocks && s0 != mBlock.at(b0).start) { - const SeqBlock &block = mBlock.at(b0); - BlockFile *const file = block.f; - blocklen = block.start + file->GetLength() - s0; - if (blocklen > (s1 - s0)) - blocklen = s1 - s0; + const SeqBlock &block0 = mBlock.at(b0); + if (s0 != block0.start) { + BlockFile *const file = block0.f; + blocklen = std::min(s1, block0.start + file->GetLength()) - s0; wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 Get(buffer, mSampleFormat, s0, blocklen); (*dest)->Append(buffer, mSampleFormat, blocklen); } + else + --b0; - if (b0 >= 0 && b0 < numBlocks && s0 == mBlock.at(b0).start) { - b0--; - } // If there are blocks in the middle, copy the blockfiles directly - for (int b = b0 + 1; b < b1; b++) - (*dest)->AppendBlock(mBlock.at(b)); + for (int bb = b0 + 1; bb < b1; ++bb) + (*dest)->AppendBlock(mBlock.at(bb)); // Increase ref count or duplicate file // Do the last block - if (b1 > b0 && b1 < numBlocks) { + if (b1 > b0) { const SeqBlock &block = mBlock.at(b1); BlockFile *const file = block.f; blocklen = (s1 - block.start); wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 - Get(buffer, mSampleFormat, block.start, blocklen); - (*dest)->Append(buffer, mSampleFormat, blocklen); + if (blocklen < file->GetLength()) { + Get(buffer, mSampleFormat, block.start, blocklen); + (*dest)->Append(buffer, mSampleFormat, blocklen); + } + else + // Special case, copy exactly + (*dest)->AppendBlock(block); // Increase ref count or duplicate file } DeleteSamples(buffer); @@ -464,12 +469,20 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) return ConsistencyCheck(wxT("Sequence::Copy()")); } +namespace { + inline bool Overflows(double numSamples) + { + return numSamples > wxLL(9223372036854775807); + } +} + bool Sequence::Paste(sampleCount s, const Sequence *src) { if ((s < 0) || (s > mNumSamples)) { wxLogError( wxT("Sequence::Paste: sampleCount s %s is < 0 or > mNumSamples %s)."), + // PRL: Why bother with Internat when the above is just wxT? Internat::ToString(((wxLongLong)s).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)mNumSamples).ToDouble(), 0).c_str()); wxASSERT(false); @@ -477,10 +490,11 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) } // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)src->mNumSamples) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)src->mNumSamples))) { wxLogError( wxT("Sequence::Paste: mNumSamples %s + src->mNumSamples %s would overflow."), + // PRL: Why bother with Internat when the above is just wxT? Internat::ToString(((wxLongLong)mNumSamples).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)src->mNumSamples).ToDouble(), 0).c_str()); wxASSERT(false); @@ -498,36 +512,40 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) const BlockArray &srcBlock = src->mBlock; sampleCount addedLen = src->mNumSamples; - unsigned int srcNumBlocks = srcBlock.size(); + const unsigned int srcNumBlocks = srcBlock.size(); int sampleSize = SAMPLE_SIZE(mSampleFormat); if (addedLen == 0 || srcNumBlocks == 0) return true; - int b = FindBlock(s); - size_t numBlocks = mBlock.size(); + const size_t numBlocks = mBlock.size(); if (numBlocks == 0 || - (s == mNumSamples && mBlock.at(numBlocks-1).f->GetLength() >= mMinSamples)) { + (s == mNumSamples && mBlock.back().f->GetLength() >= mMinSamples)) { // Special case: this track is currently empty, or it's safe to append // onto the end because the current last block is longer than the // minimum size for (unsigned int i = 0; i < srcNumBlocks; i++) - AppendBlock(srcBlock.at(i)); + AppendBlock(srcBlock.at(i)); // Increase ref count or duplicate file return ConsistencyCheck(wxT("Paste branch one")); } - SeqBlock *pBlock; - sampleCount length; - if ((b >= 0 ) && (b < (int)numBlocks) - && (length = (pBlock = &mBlock.at(b))->f->GetLength()) + addedLen < mMaxSamples) { + const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s); + wxASSERT((b >= 0) && (b < (int)numBlocks)); + SeqBlock *const pBlock = &mBlock.at(b); + const sampleCount length = pBlock->f->GetLength(); + const sampleCount largerBlockLen = addedLen + length; + // PRL: when insertion point is the first sample of a block, + // and the following test fails, perhaps we could test + // whether coalescence with the previous block is possible. + if (largerBlockLen <= mMaxSamples) { // Special case: we can fit all of the new samples inside of // one block! SeqBlock &block = *pBlock; - samplePtr buffer = NewSamples(mMaxSamples, mSampleFormat); + samplePtr buffer = NewSamples(largerBlockLen, mSampleFormat); int splitPoint = s - block.start; Read(buffer, mSampleFormat, block, 0, splitPoint); @@ -537,15 +555,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) mSampleFormat, block, splitPoint, length - splitPoint); - sampleCount largerBlockLen = length + addedLen; - if (largerBlockLen > mMaxSamples) - { - wxLogError( - wxT("Sequence::Paste: (largerBlockLen %s > mMaxSamples %s). largerBlockLen truncated to mMaxSamples."), - Internat::ToString(((wxLongLong)largerBlockLen).ToDouble(), 0).c_str(), - Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); - largerBlockLen = mMaxSamples; // Prevent overruns, per NGS report for UmixIt. - } BlockFile *const file = mDirManager->NewSimpleBlockFile(buffer, largerBlockLen, mSampleFormat); @@ -562,7 +571,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) return ConsistencyCheck(wxT("Paste branch two")); } - // Case two: if we are inserting four or fewer blocks, + // Case three: if we are inserting four or fewer blocks, // it's simplest to just lump all the data together // into one big block along with the split block, // then resplit it all @@ -635,9 +644,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) Read(rightBuffer + srcLastTwoLen * sampleSize, mSampleFormat, splitBlock, splitPoint, rightSplit); - sampleCount pos = s + lastStart; - - Blockify(newBlock, pos, rightBuffer, rightLen); + Blockify(newBlock, s + lastStart, rightBuffer, rightLen); DeleteSamples(rightBuffer); } @@ -663,45 +670,56 @@ bool Sequence::SetSilence(sampleCount s0, sampleCount len) bool Sequence::InsertSilence(sampleCount s0, sampleCount len) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)len))) return false; + if (len <= 0) + return true; + // Create a new track containing as much silence as we // need to insert, and then call Paste to do the insertion. // We make use of a SilentBlockFile, which takes up no // space on disk. - Sequence *sTrack = new Sequence(mDirManager, mSampleFormat); + Sequence sTrack(mDirManager, mSampleFormat); sampleCount idealSamples = GetIdealBlockSize(); sampleCount pos = 0; - while (len) { - sampleCount l = (len > idealSamples ? idealSamples : len); + sTrack.mBlock.reserve((len + idealSamples - 1) / idealSamples); - sTrack->mBlock.push_back(SeqBlock(new SilentBlockFile(l), pos)); + BlockFile *silentFile = 0; + if (len >= idealSamples) + silentFile = new SilentBlockFile(idealSamples); + while (len >= idealSamples) { + sTrack.mBlock.push_back(SeqBlock(silentFile, pos)); + mDirManager->Ref(silentFile); - pos += l; - len -= l; + pos += idealSamples; + len -= idealSamples; + } + if (silentFile) + mDirManager->Deref(silentFile); + if (len) { + sTrack.mBlock.push_back(SeqBlock(new SilentBlockFile(len), pos)); + pos += len; } - sTrack->mNumSamples = pos; + sTrack.mNumSamples = pos; - bool bResult = Paste(s0, sTrack); + bool bResult = Paste(s0, &sTrack); wxASSERT(bResult); - delete sTrack; - return bResult && ConsistencyCheck(wxT("InsertSilence")); } bool Sequence::AppendAlias(wxString fullPath, sampleCount start, - sampleCount len, int channel,bool useOD) + sampleCount len, int channel, bool useOD) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)len))) return false; SeqBlock newBlock( @@ -711,7 +729,7 @@ bool Sequence::AppendAlias(wxString fullPath, mNumSamples ); mBlock.push_back(newBlock); - mNumSamples += newBlock.f->GetLength(); + mNumSamples += len; return true; } @@ -720,7 +738,7 @@ bool Sequence::AppendCoded(wxString fName, sampleCount start, sampleCount len, int channel, int decodeType) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)len))) return false; SeqBlock newBlock( @@ -728,7 +746,7 @@ bool Sequence::AppendCoded(wxString fName, sampleCount start, mNumSamples ); mBlock.push_back(newBlock); - mNumSamples += newBlock.f->GetLength(); + mNumSamples += len; return true; } @@ -736,11 +754,11 @@ bool Sequence::AppendCoded(wxString fName, sampleCount start, bool Sequence::AppendBlock(const SeqBlock &b) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)b.f->GetLength()) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)b.f->GetLength()))) return false; SeqBlock newBlock( - mDirManager->CopyBlockFile(b.f), + mDirManager->CopyBlockFile(b.f), // Bump ref count if not locked, else copy mNumSamples ); if (!newBlock.f) { @@ -768,9 +786,9 @@ unsigned int Sequence::GetODFlags() for (unsigned int i = 0; i < mBlock.size(); i++) { BlockFile *const file = mBlock.at(i).f; if(!file->IsDataAvailable()) - ret = ret|(static_cast(file))->GetDecodeType(); + ret |= (static_cast(file))->GetDecodeType(); else if(!file->IsSummaryAvailable()) - ret = ret|ODTask::eODPCMSummary; + ret |= ODTask::eODPCMSummary; } return ret; } @@ -786,7 +804,11 @@ sampleCount Sequence::GetBestBlockSize(sampleCount start) const // This method returns a nice number of samples you should try to grab in // one big chunk in order to land on a block boundary, based on the starting // sample. The value returned will always be nonzero and will be no larger - // than the value of GetMaxBlockSize(); + // than the value of GetMaxBlockSize() + + if (start < 0 || start >= mNumSamples) + return mMaxSamples; + int b = FindBlock(start); int numBlocks = mBlock.size(); @@ -809,7 +831,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) { sampleCount nValue; - /* handle waveblock tag and it's attributes */ + /* handle waveblock tag and its attributes */ if (!wxStrcmp(tag, wxT("waveblock"))) { SeqBlock wb; @@ -863,7 +885,7 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) return true; } - /* handle sequence tag and it's attributes */ + /* handle sequence tag and its attributes */ if (!wxStrcmp(tag, wxT("sequence"))) { while(*attrs) { const wxChar *attr = *attrs++; @@ -891,7 +913,10 @@ bool Sequence::HandleXMLTag(const wxChar *tag, const wxChar **attrs) return false; } mMaxSamples = nValue; - mDirManager->SetMaxSamples(mMaxSamples); + + // PRL: Is the following really okay? DirManager might be shared across projects! + // PRL: Yes, because it only affects DirManager's behavior in opening the project. + mDirManager->SetLoadingMaxSamples(mMaxSamples); } else if (!wxStrcmp(attr, wxT("sampleformat"))) { @@ -938,13 +963,12 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Make sure that the sequence is valid. // First, replace missing blockfiles with SilentBlockFiles - unsigned int b; - for (b = 0; b < mBlock.size(); b++) { + for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) { SeqBlock &block = mBlock.at(b); if (!block.f) { sampleCount len; - if (b < mBlock.size()-1) + if (b < nn - 1) len = mBlock.at(b+1).start - block.start; else len = mNumSamples - block.start; @@ -955,6 +979,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // the silent replacement to mMaxSamples. wxLogWarning( wxT(" Sequence has missing block file with length %s > mMaxSamples %s.\n Setting length to mMaxSamples. This will likely cause some block files to be considered orphans."), + // PRL: Why bother with Internat when the above is just wxT? Internat::ToString(((wxLongLong)len).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); len = mMaxSamples; @@ -968,7 +993,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Next, make sure that start times and lengths are consistent sampleCount numSamples = 0; - for (b = 0; b < mBlock.size(); b++) { + for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) { SeqBlock &block = mBlock.at(b); if (block.start != numSamples) { wxString sFileAndExtension = block.f->GetFileName().GetFullName(); @@ -977,10 +1002,13 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) else sFileAndExtension = wxT("\"") + sFileAndExtension + wxT("\""); wxLogWarning( - wxT("Gap detected in project file.\n Start (%s) for block file %s is more than one sample past end of previous block (%s).\n Moving start back so blocks are contiguous."), + wxT("Gap detected in project file.\n") + wxT(" Start (%s) for block file %s is not one sample past end of previous block (%s).\n") + wxT(" Moving start so blocks are contiguous."), + // PRL: Why bother with Internat when the above is just wxT? Internat::ToString(((wxLongLong)(block.start)).ToDouble(), 0).c_str(), sFileAndExtension.c_str(), - Internat::ToString(((wxLongLong)(numSamples)).ToDouble(), 0).c_str()); + Internat::ToString(((wxLongLong)numSamples).ToDouble(), 0).c_str()); block.start = numSamples; mErrorOpening = true; } @@ -989,6 +1017,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) if (mNumSamples != numSamples) { wxLogWarning( wxT("Gap detected in project file. Correcting sequence sample count from %s to %s."), + // PRL: Why bother with Internat when the above is just wxT? Internat::ToString(((wxLongLong)mNumSamples).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)numSamples).ToDouble(), 0).c_str()); mNumSamples = numSamples; @@ -1028,7 +1057,7 @@ void Sequence::WriteXML(XMLWriter &xmlFile) wxString sMsg = wxString::Format( _("Sequence has block file with length %s > mMaxSamples %s.\nTruncating to mMaxSamples."), - Internat::ToString(((wxLongLong)(bb.f->GetLength())).ToDouble(), 0).c_str(), + Internat::ToString(((wxLongLong)bb.f->GetLength()).ToDouble(), 0).c_str(), Internat::ToString(((wxLongLong)mMaxSamples).ToDouble(), 0).c_str()); wxMessageBox(sMsg, _("Warning - Length in Writing Sequence"), wxICON_EXCLAMATION | wxOK); wxLogWarning(sMsg); @@ -1098,11 +1127,11 @@ int Sequence::FindBlock(sampleCount pos) const bool Sequence::Read(samplePtr buffer, sampleFormat format, const SeqBlock &b, sampleCount start, sampleCount len) const { - wxASSERT(start >= 0); - wxASSERT(start + len <= b.f->GetLength()); - BlockFile *f = b.f; + wxASSERT(start >= 0); + wxASSERT(start + len <= f->GetLength()); + int result = f->ReadData(buffer, format, start, len); if (result != len) @@ -1126,9 +1155,10 @@ bool Sequence::CopyWrite(samplePtr buffer, SeqBlock &b, const sampleCount length = b.f->GetLength(); wxASSERT(length <= mMaxSamples); wxASSERT(start + len <= length); + wxASSERT(start >= 0); int sampleSize = SAMPLE_SIZE(mSampleFormat); - samplePtr newBuffer = NewSamples(mMaxSamples, mSampleFormat); + samplePtr newBuffer = NewSamples(len * sampleSize, mSampleFormat); wxASSERT(newBuffer); Read(newBuffer, mSampleFormat, b, 0, length); @@ -1147,18 +1177,16 @@ bool Sequence::CopyWrite(samplePtr buffer, SeqBlock &b, bool Sequence::Get(samplePtr buffer, sampleFormat format, sampleCount start, sampleCount len) const { - if (start < 0 || start > mNumSamples || + if (start < 0 || start >= mNumSamples || start+len > mNumSamples) return false; int b = FindBlock(start); while (len) { const SeqBlock &block = mBlock.at(b); - sampleCount blen = - block.start + block.f->GetLength() - start; - if (blen > len) - blen = len; - sampleCount bstart = (start - (block.start)); + const sampleCount bstart = (start - (block.start)); + const sampleCount blen = + std::min(len, block.f->GetLength() - bstart); Read(buffer, format, block, bstart, blen); @@ -1175,54 +1203,52 @@ bool Sequence::Get(samplePtr buffer, sampleFormat format, bool Sequence::Set(samplePtr buffer, sampleFormat format, sampleCount start, sampleCount len) { - if (start < 0 || start > mNumSamples || + if (start < 0 || start >= mNumSamples || start+len > mNumSamples) return false; samplePtr temp = NULL; - if (format != mSampleFormat) { - temp = NewSamples(mMaxSamples, mSampleFormat); + if (buffer && format != mSampleFormat) { + temp = NewSamples(std::min(len, mMaxSamples), mSampleFormat); wxASSERT(temp); } samplePtr silence = NULL; - if (!buffer) { - silence = NewSamples(mMaxSamples, format); - wxASSERT(silence); - ClearSamples(silence, format, 0, mMaxSamples); - } int b = FindBlock(start); while (len) { SeqBlock &block = mBlock.at(b); - int blen = block.start + block.f->GetLength() - start; - if (blen > len) - blen = len; + const sampleCount bstart = start - block.start; + const sampleCount fileLength = block.f->GetLength(); + const int blen = + std::min(len, fileLength - bstart); if (buffer) { if (format == mSampleFormat) - CopyWrite(buffer, block, start - block.start, - blen); + CopyWrite(buffer, block, bstart, blen); else { CopySamples(buffer, format, temp, mSampleFormat, blen); - CopyWrite(temp, block, start - block.start, - blen); + CopyWrite(temp, block, bstart, blen); } buffer += (blen * SAMPLE_SIZE(format)); } else { // If it's a full block of silence if (start == block.start && - blen == block.f->GetLength()) { + blen == fileLength) { mDirManager->Deref(block.f); block.f = new SilentBlockFile(blen); } else { + if (!silence) { + silence = NewSamples(blen, format); + wxASSERT(silence); + ClearSamples(silence, format, 0, blen); + } // Otherwise write silence just to the portion of the block - CopyWrite(silence, block, - start - block.start, blen); + CopyWrite(silence, block, bstart, blen); } } @@ -1231,10 +1257,10 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, b++; } - if (!buffer) + if (silence) DeleteSamples(silence); - if (format != mSampleFormat) + if (temp) DeleteSamples(temp); return ConsistencyCheck(wxT("Set")); @@ -1482,13 +1508,12 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, sampleCount Sequence::GetIdealAppendLen() { int numBlocks = mBlock.size(); - sampleCount max = GetMaxBlockSize(); - sampleCount lastBlockLen; + const sampleCount max = GetMaxBlockSize(); if (numBlocks == 0) return max; - lastBlockLen = mBlock.at(numBlocks-1).f->GetLength(); + const sampleCount lastBlockLen = mBlock.back().f->GetLength(); if (lastBlockLen == max) return max; else @@ -1499,7 +1524,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, sampleCount len, XMLWriter* blockFileLog /*=NULL*/) { // Quick check to make sure that it doesn't overflow - if (((double)mNumSamples) + ((double)len) > wxLL(9223372036854775807)) + if (Overflows(((double)mNumSamples) + ((double)len))) return false; // If the last block is not full, we need to add samples to it @@ -1508,13 +1533,9 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, SeqBlock *pLastBlock; if (numBlocks > 0 && (length = - (pLastBlock = &mBlock.at(numBlocks - 1))->f->GetLength()) < mMinSamples) { + (pLastBlock = &mBlock.back())->f->GetLength()) < mMinSamples) { SeqBlock &lastBlock = *pLastBlock; - sampleCount addLen; - if (length + len < mMaxSamples) - addLen = len; - else - addLen = GetIdealBlockSize() - length; + const sampleCount addLen = std::min(mMaxSamples - length, len); samplePtr buffer2 = NewSamples((length + addLen), mSampleFormat); Read(buffer2, mSampleFormat, lastBlock, 0, length); @@ -1525,7 +1546,7 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, mSampleFormat, addLen); - int newLastBlockLen = length + addLen; + const int newLastBlockLen = length + addLen; SeqBlock newLastBlock( mDirManager->NewSimpleBlockFile(buffer2, newLastBlockLen, mSampleFormat, @@ -1561,8 +1582,8 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, } } while (len) { - sampleCount idealSamples = GetIdealBlockSize(); - sampleCount l = (len > idealSamples ? idealSamples : len); + const sampleCount idealSamples = GetIdealBlockSize(); + const sampleCount l = std::min(idealSamples, len); BlockFile *pFile; if (format == mSampleFormat) { pFile = mDirManager->NewSimpleBlockFile(buffer, l, mSampleFormat, @@ -1620,8 +1641,6 @@ void Sequence::Blockify(BlockArray &list, sampleCount start, samplePtr buffer, s bool Sequence::Delete(sampleCount start, sampleCount len) { - - if (len == 0) return true; if (len < 0 || start < 0 || start >= mNumSamples) @@ -1632,9 +1651,9 @@ bool Sequence::Delete(sampleCount start, sampleCount len) //both functions, DeleteUpdateMutexLocker locker(*this); - unsigned int numBlocks = mBlock.size(); + const unsigned int numBlocks = mBlock.size(); - unsigned int b0 = FindBlock(start); + const unsigned int b0 = FindBlock(start); unsigned int b1 = FindBlock(start + len - 1); int sampleSize = SAMPLE_SIZE(mSampleFormat); @@ -1687,7 +1706,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). - SeqBlock &preBlock = mBlock.at(b0); + const SeqBlock &preBlock = mBlock.at(b0); sampleCount preBufferLen = start - preBlock.start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { @@ -1698,14 +1717,10 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(preBuffer); newBlock.push_back(SeqBlock(pFile, preBlock.start)); - - if (b0 != b1) { - mDirManager->Deref(preBlock.f); - } } else { - SeqBlock &prepreBlock = mBlock.at(b0 - 1); - sampleCount prepreLen = prepreBlock.f->GetLength(); - sampleCount sum = prepreLen + preBufferLen; + const SeqBlock &prepreBlock = mBlock.at(b0 - 1); + const sampleCount prepreLen = prepreBlock.f->GetLength(); + const sampleCount sum = prepreLen + preBufferLen; samplePtr sumBuffer = NewSamples(sum, mSampleFormat); @@ -1719,17 +1734,15 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(sumBuffer); mDirManager->Deref(prepreBlock.f); - - if (b0 != b1) { - mDirManager->Deref(preBlock.f); - } } - } else { + } + else { // The sample where we begin deletion happens to fall // right on the beginning of a block. - if (b0 != b1) { - mDirManager->Deref(preBlock.f); - } + } + + if (b0 != b1) { + mDirManager->Deref(preBlock.f); } // Next, delete blocks strictly between b0 and b1 @@ -1742,7 +1755,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). - SeqBlock &postBlock = mBlock.at(b1); + const SeqBlock &postBlock = mBlock.at(b1); sampleCount postBufferLen = (postBlock.start + postBlock.f->GetLength()) - (start + len); if (postBufferLen) { @@ -1750,14 +1763,12 @@ bool Sequence::Delete(sampleCount start, sampleCount len) samplePtr postBuffer = NewSamples(postBufferLen, mSampleFormat); sampleCount pos = (start + len) - postBlock.start; Read(postBuffer, mSampleFormat, postBlock, pos, postBufferLen); - BlockFile *const file= + BlockFile *const file = mDirManager->NewSimpleBlockFile(postBuffer, postBufferLen, mSampleFormat); DeleteSamples(postBuffer); newBlock.push_back(SeqBlock(file, start)); - - mDirManager->Deref(postBlock.f); } else { SeqBlock &postpostBlock = mBlock.at(b1 + 1); sampleCount postpostLen = postpostBlock.f->GetLength(); @@ -1775,13 +1786,13 @@ bool Sequence::Delete(sampleCount start, sampleCount len) DeleteSamples(sumBuffer); mDirManager->Deref(postpostBlock.f); - mDirManager->Deref(postBlock.f); } - } else { + } + else { // The sample where we begin deletion happens to fall // right on the end of a block. - mDirManager->Deref(postBlock.f); } + mDirManager->Deref(postBlock.f); // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) @@ -1796,15 +1807,15 @@ bool Sequence::Delete(sampleCount start, sampleCount len) return ConsistencyCheck(wxT("Delete - branch two")); } -bool Sequence::ConsistencyCheck(const wxChar *whereStr) +bool Sequence::ConsistencyCheck(const wxChar *whereStr) const { unsigned int i; sampleCount pos = 0; unsigned int numBlocks = mBlock.size(); bool bError = false; - for (i = 0; i < numBlocks; i++) { - SeqBlock &seqBlock = mBlock.at(i); + for (i = 0; !bError && i < numBlocks; i++) { + const SeqBlock &seqBlock = mBlock.at(i); if (pos != seqBlock.start) bError = true; @@ -1822,19 +1833,21 @@ bool Sequence::ConsistencyCheck(const wxChar *whereStr) wxString str; DebugPrintf(&str); wxLogError(wxT("%s"), str.c_str()); - wxLogError(wxT("*** Please report this error to feedback@audacityteam.org. ***\n\nRecommended course of action:\nUndo the failed operation(s), then export or save your work and quit.")); + wxLogError(wxT("*** Please report this error to feedback@audacityteam.org. ***\n\n") + wxT("Recommended course of action:\n") + wxT("Undo the failed operation(s), then export or save your work and quit.")); } return !bError; } -void Sequence::DebugPrintf(wxString *dest) +void Sequence::DebugPrintf(wxString *dest) const { unsigned int i; int pos = 0; for (i = 0; i < mBlock.size(); i++) { - SeqBlock &seqBlock = mBlock.at(i); + const SeqBlock &seqBlock = mBlock.at(i); *dest += wxString::Format (wxT(" Block %3u: start %8lld, len %8lld, refs %d, "), i, @@ -1873,6 +1886,8 @@ int Sequence::GetMaxDiskBlockSize() void Sequence::AppendBlockFile(BlockFile* blockFile) { + // We assume blockFile has the correct ref count already + mBlock.push_back(SeqBlock(blockFile, mNumSamples)); mNumSamples += blockFile->GetLength(); diff --git a/src/Sequence.h b/src/Sequence.h index 954f14265..cf266b75e 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -58,9 +58,6 @@ WX_DEFINE_ARRAY(SeqBlock *, BlockPtrArray); class Sequence: public XMLTagHandler { public: - // Temporary: only until we delete TrackArtist once and for all - friend class TrackArtist; - // // Static methods // @@ -82,7 +79,7 @@ class Sequence: public XMLTagHandler { return new Sequence(*this, projDirManager); } - virtual ~Sequence(); + ~Sequence(); // // Editing @@ -102,7 +99,7 @@ class Sequence: public XMLTagHandler { // where[p] up to (but excluding) where[p + 1]. // bl is negative wherever data are not yet available. // Return true if successful. - bool GetWaveDisplay(float *min, float *max, float *rms,int* bl, + bool GetWaveDisplay(float *min, float *max, float *rms, int* bl, int len, const sampleCount *where); bool Copy(sampleCount s0, sampleCount s1, Sequence **dest); @@ -114,7 +111,7 @@ class Sequence: public XMLTagHandler { bool Delete(sampleCount start, sampleCount len); bool AppendAlias(wxString fullPath, sampleCount start, - sampleCount len, int channel,bool useOD); + sampleCount len, int channel, bool useOD); bool AppendCoded(wxString fName, sampleCount start, sampleCount len, int channel, int decodeType); @@ -162,7 +159,7 @@ class Sequence: public XMLTagHandler { // sampleFormat GetSampleFormat() const; - bool SetSampleFormat(sampleFormat format); + // bool SetSampleFormat(sampleFormat format); bool ConvertToSampleFormat(sampleFormat format, bool* pbChanged); // @@ -239,7 +236,7 @@ class Sequence: public XMLTagHandler { // Private methods // - void CalcSummaryInfo(); + void DerefAllFiles(); int FindBlock(sampleCount pos) const; @@ -249,16 +246,9 @@ class Sequence: public XMLTagHandler { const SeqBlock &b, sampleCount start, sampleCount len) const; - // These are the two ways to write data to a block - bool FirstWrite(samplePtr buffer, SeqBlock * b, sampleCount len); bool CopyWrite(samplePtr buffer, SeqBlock &b, sampleCount start, sampleCount len); - // Both block-writing methods and AppendAlias call this - // method to write the summary data - void *GetSummary(samplePtr buffer, sampleCount len, - float *min, float *max, float *rms); - void Blockify(BlockArray &list, sampleCount start, samplePtr buffer, sampleCount len); public: @@ -269,11 +259,11 @@ class Sequence: public XMLTagHandler { // This function makes sure that the track isn't messed up // because of inconsistent block starts & lengths - bool ConsistencyCheck(const wxChar *whereStr); + bool ConsistencyCheck(const wxChar *whereStr) const; // This function prints information to stdout about the blocks in the // tracks and indicates if there are inconsistencies. - void DebugPrintf(wxString *dest); + void DebugPrintf(wxString *dest) const; }; #endif // __AUDACITY_SEQUENCE__ diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 56171ad7b..c4d759d47 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -1708,7 +1708,7 @@ void WaveClip::CloseLock() { GetSequence()->CloseLock(); for (WaveClipList::compatibility_iterator it = mCutLines.GetFirst(); it; it=it->GetNext()) - it->GetData()->Lock(); + it->GetData()->CloseLock(); } void WaveClip::Unlock() From dc599116f7265978cc6c2ba6b693e8ee1a7d6e35 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 13:53:11 -0500 Subject: [PATCH 08/16] Use SampleBuffer in Sequence, reuse so there are fewer allocations of buffers --- src/Sequence.cpp | 294 +++++++++++++++++++++-------------------------- src/Sequence.h | 3 +- 2 files changed, 132 insertions(+), 165 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 642326e49..eb991694b 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -165,57 +165,53 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) return true; } - sampleFormat oldFormat = mSampleFormat; + const sampleFormat oldFormat = mSampleFormat; mSampleFormat = format; - sampleCount oldMaxSamples = mMaxSamples; + const sampleCount oldMinSamples = mMinSamples, oldMaxSamples = mMaxSamples; // These are the same calculations as in the constructor. 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(mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples)); + newBlockArray.reserve(1 + mBlock.size() * ((float)oldMaxSamples / (float)mMaxSamples)); bool bSuccess = true; - for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++) { - SeqBlock &oldSeqBlock = mBlock.at(i); - BlockFile* oldBlockFile = oldSeqBlock.f; + SampleBuffer bufferOld(mMaxSamples, oldFormat); + SampleBuffer bufferNew(mMaxSamples, format); - sampleCount len = oldBlockFile->GetLength(); - samplePtr bufferOld = NewSamples(len, oldFormat); - samplePtr bufferNew = NewSamples(len, mSampleFormat); - - bSuccess = (oldBlockFile->ReadData(bufferOld, oldFormat, 0, len) > 0); - if (!bSuccess) + for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++) { - DeleteSamples(bufferNew); - DeleteSamples(bufferOld); - break; + SeqBlock &oldSeqBlock = mBlock.at(i); + BlockFile* oldBlockFile = oldSeqBlock.f; + + sampleCount len = oldBlockFile->GetLength(); + + bSuccess = (oldBlockFile->ReadData(bufferOld.ptr(), oldFormat, 0, len) > 0); + if (!bSuccess) + break; + + CopySamples(bufferOld.ptr(), oldFormat, bufferNew.ptr(), format, len); + + // Note this fix for http://bugzilla.audacityteam.org/show_bug.cgi?id=451, + // using Blockify, allows (len < mMinSamples). + // This will happen consistently when going from more bytes per sample to fewer... + // This will create a block that's smaller than mMinSamples, which + // shouldn't be allowed, but we agreed it's okay for now. + //vvv ANSWER-ME: Does this cause any bugs, or failures on write, elsewhere? + // If so, need to special-case (len < mMinSamples) and start combining data + // from the old blocks... Oh no! + + // Using Blockify will handle the cases where len > the new mMaxSamples. Previous code did not. + const sampleCount blockstart = oldSeqBlock.start; + const unsigned prevSize = newBlockArray.size(); + Blockify(newBlockArray, blockstart, bufferNew.ptr(), len); + bSuccess = (newBlockArray.size() > prevSize); + if (bSuccess) + *pbChanged = true; } - - CopySamples(bufferOld, oldFormat, bufferNew, mSampleFormat, len); - - // Note this fix for http://bugzilla.audacityteam.org/show_bug.cgi?id=451, - // using Blockify, allows (len < mMinSamples). - // This will happen consistently when going from more bytes per sample to fewer... - // This will create a block that's smaller than mMinSamples, which - // shouldn't be allowed, but we agreed it's okay for now. - //vvv ANSWER-ME: Does this cause any bugs, or failures on write, elsewhere? - // If so, need to special-case (len < mMinSamples) and start combining data - // from the old blocks... Oh no! - - // Using Blockify will handle the cases where len > the new mMaxSamples. Previous code did not. - const sampleCount blockstart = oldSeqBlock.start; - const unsigned prevSize = newBlockArray.size(); - Blockify(newBlockArray, blockstart, bufferNew, len); - bSuccess = (newBlockArray.size() > prevSize); - if (bSuccess) - *pbChanged = true; - - DeleteSamples(bufferNew); - DeleteSamples(bufferOld); } if (bSuccess) @@ -234,11 +230,16 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) it just assumes the conversion was successful. TODO: Uncomment this section when TrackPanel::OnFormatChange() is upgraded to check the results. - // Conversion failed. Revert these member vars. - mSampleFormat = oldFormat; - mMaxSamples = oldMaxSamples; + 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. */ + // 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. } @@ -427,7 +428,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) *dest = new Sequence(mDirManager, mSampleFormat); (*dest)->mBlock.reserve(b1 - b0 + 1); - samplePtr buffer = NewSamples(mMaxSamples, mSampleFormat); + SampleBuffer buffer(mMaxSamples, mSampleFormat); int blocklen; @@ -438,9 +439,9 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) BlockFile *const file = block0.f; blocklen = std::min(s1, block0.start + file->GetLength()) - s0; wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 - Get(buffer, mSampleFormat, s0, blocklen); + Get(buffer.ptr(), mSampleFormat, s0, blocklen); - (*dest)->Append(buffer, mSampleFormat, blocklen); + (*dest)->Append(buffer.ptr(), mSampleFormat, blocklen); } else --b0; @@ -456,16 +457,14 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) blocklen = (s1 - block.start); wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 if (blocklen < file->GetLength()) { - Get(buffer, mSampleFormat, block.start, blocklen); - (*dest)->Append(buffer, mSampleFormat, blocklen); + Get(buffer.ptr(), mSampleFormat, block.start, blocklen); + (*dest)->Append(buffer.ptr(), mSampleFormat, blocklen); } else // Special case, copy exactly (*dest)->AppendBlock(block); // Increase ref count or duplicate file } - DeleteSamples(buffer); - return ConsistencyCheck(wxT("Sequence::Copy()")); } @@ -545,18 +544,18 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // one block! SeqBlock &block = *pBlock; - samplePtr buffer = NewSamples(largerBlockLen, mSampleFormat); + SampleBuffer buffer(largerBlockLen, mSampleFormat); int splitPoint = s - block.start; - Read(buffer, mSampleFormat, block, 0, splitPoint); - src->Get(buffer + splitPoint*sampleSize, + Read(buffer.ptr(), mSampleFormat, block, 0, splitPoint); + src->Get(buffer.ptr() + splitPoint*sampleSize, mSampleFormat, 0, addedLen); - Read(buffer + (splitPoint + addedLen)*sampleSize, + Read(buffer.ptr() + (splitPoint + addedLen)*sampleSize, mSampleFormat, block, splitPoint, length - splitPoint); BlockFile *const file = - mDirManager->NewSimpleBlockFile(buffer, largerBlockLen, mSampleFormat); + mDirManager->NewSimpleBlockFile(buffer.ptr(), largerBlockLen, mSampleFormat); mDirManager->Deref(block.f); block.f = file; @@ -566,8 +565,6 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) mNumSamples += addedLen; - DeleteSamples(buffer); - return ConsistencyCheck(wxT("Paste branch two")); } @@ -588,17 +585,16 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) sampleCount sum = splitLen + addedLen; - samplePtr sumBuffer = NewSamples(sum, mSampleFormat); - Read(sumBuffer, mSampleFormat, splitBlock, 0, splitPoint); - src->Get(sumBuffer + splitPoint * sampleSize, + SampleBuffer sumBuffer(sum, mSampleFormat); + Read(sumBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint); + src->Get(sumBuffer.ptr() + splitPoint * sampleSize, mSampleFormat, 0, addedLen); - Read(sumBuffer + (splitPoint + addedLen) * sampleSize, mSampleFormat, + Read(sumBuffer.ptr() + (splitPoint + addedLen) * sampleSize, mSampleFormat, splitBlock, splitPoint, splitLen - splitPoint); - Blockify(newBlock, splitBlock.start, sumBuffer, sum); - DeleteSamples(sumBuffer); + Blockify(newBlock, splitBlock.start, sumBuffer.ptr(), sum); } else { // The final case is that we're inserting at least five blocks. @@ -607,17 +603,24 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // copied in as is, and the last two get merged with the last // half of the split block. - sampleCount srcFirstTwoLen = + const sampleCount srcFirstTwoLen = srcBlock.at(0).f->GetLength() + srcBlock.at(1).f->GetLength(); - sampleCount leftLen = splitPoint + srcFirstTwoLen; + const sampleCount leftLen = splitPoint + srcFirstTwoLen; - samplePtr leftBuffer = NewSamples(leftLen, mSampleFormat); - Read(leftBuffer, mSampleFormat, splitBlock, 0, splitPoint); - src->Get(leftBuffer + splitPoint*sampleSize, - mSampleFormat, 0, srcFirstTwoLen); + const SeqBlock &penultimate = srcBlock.at(srcNumBlocks - 2); + const sampleCount srcLastTwoLen = + penultimate.f->GetLength() + + srcBlock.at(srcNumBlocks - 1).f->GetLength(); + const sampleCount rightSplit = splitBlock.f->GetLength() - splitPoint; + const sampleCount rightLen = rightSplit + srcLastTwoLen; - Blockify(newBlock, splitBlock.start, leftBuffer, leftLen); - DeleteSamples(leftBuffer); + SampleBuffer sampleBuffer(std::max(leftLen, rightLen), mSampleFormat); + + Read(sampleBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint); + src->Get(sampleBuffer.ptr() + splitPoint*sampleSize, + mSampleFormat, 0, srcFirstTwoLen); + + Blockify(newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen); for (i = 2; i < srcNumBlocks - 2; i++) { const SeqBlock &block = srcBlock.at(i); @@ -630,22 +633,13 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) newBlock.push_back(SeqBlock(file, block.start + s)); } - const SeqBlock &penultimate = srcBlock.at(srcNumBlocks - 2); - sampleCount srcLastTwoLen = - penultimate.f->GetLength() + - srcBlock.at(srcNumBlocks - 1).f->GetLength(); - sampleCount rightSplit = splitBlock.f->GetLength() - splitPoint; - sampleCount rightLen = rightSplit + srcLastTwoLen; - - samplePtr rightBuffer = NewSamples(rightLen, mSampleFormat); sampleCount lastStart = penultimate.start; - src->Get(rightBuffer, mSampleFormat, + src->Get(sampleBuffer.ptr(), mSampleFormat, lastStart, srcLastTwoLen); - Read(rightBuffer + srcLastTwoLen * sampleSize, mSampleFormat, + Read(sampleBuffer.ptr() + srcLastTwoLen * sampleSize, mSampleFormat, splitBlock, splitPoint, rightSplit); - Blockify(newBlock, s + lastStart, rightBuffer, rightLen); - DeleteSamples(rightBuffer); + Blockify(newBlock, s + lastStart, sampleBuffer.ptr(), rightLen); } mDirManager->Deref(splitBlock.f); @@ -1145,7 +1139,8 @@ bool Sequence::Read(samplePtr buffer, sampleFormat format, return true; } -bool Sequence::CopyWrite(samplePtr buffer, SeqBlock &b, +bool Sequence::CopyWrite(SampleBuffer &scratch, + samplePtr buffer, SeqBlock &b, sampleCount start, sampleCount len) { // We don't ever write to an existing block; to support Undo, @@ -1158,19 +1153,15 @@ bool Sequence::CopyWrite(samplePtr buffer, SeqBlock &b, wxASSERT(start >= 0); int sampleSize = SAMPLE_SIZE(mSampleFormat); - samplePtr newBuffer = NewSamples(len * sampleSize, mSampleFormat); - wxASSERT(newBuffer); - Read(newBuffer, mSampleFormat, b, 0, length); - memcpy(newBuffer + start*sampleSize, buffer, len*sampleSize); + Read(scratch.ptr(), mSampleFormat, b, 0, length); + memcpy(scratch.ptr() + start*sampleSize, buffer, len*sampleSize); - BlockFile *oldBlockFile = b.f; - b.f = mDirManager->NewSimpleBlockFile(newBuffer, length, mSampleFormat); + BlockFile *const oldBlockFile = b.f; + b.f = mDirManager->NewSimpleBlockFile(scratch.ptr(), length, mSampleFormat); mDirManager->Deref(oldBlockFile); - DeleteSamples(newBuffer); - return true; } @@ -1207,13 +1198,12 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, start+len > mNumSamples) return false; - samplePtr temp = NULL; - if (buffer && format != mSampleFormat) { - temp = NewSamples(std::min(len, mMaxSamples), mSampleFormat); - wxASSERT(temp); - } + SampleBuffer scratch(mMaxSamples, mSampleFormat); - samplePtr silence = NULL; + SampleBuffer temp; + if (buffer && format != mSampleFormat) { + temp.Allocate(std::min(len, mMaxSamples), mSampleFormat); + } int b = FindBlock(start); @@ -1226,10 +1216,11 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, if (buffer) { if (format == mSampleFormat) - CopyWrite(buffer, block, bstart, blen); + CopyWrite(scratch, buffer, block, bstart, blen); else { - CopySamples(buffer, format, temp, mSampleFormat, blen); - CopyWrite(temp, block, bstart, blen); + // To do: remove the extra movement. Can we copy-samples within CopyWrite? + CopySamples(buffer, format, temp.ptr(), mSampleFormat, blen); + CopyWrite(scratch, temp.ptr(), block, bstart, blen); } buffer += (blen * SAMPLE_SIZE(format)); } @@ -1242,13 +1233,11 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, block.f = new SilentBlockFile(blen); } else { - if (!silence) { - silence = NewSamples(blen, format); - wxASSERT(silence); - ClearSamples(silence, format, 0, blen); - } + // Odd partial blocks of silence at start or end. + temp.Allocate(blen, format); + ClearSamples(temp.ptr(), format, 0, blen); // Otherwise write silence just to the portion of the block - CopyWrite(silence, block, bstart, blen); + CopyWrite(scratch, temp.ptr(), block, bstart, blen); } } @@ -1257,12 +1246,6 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, b++; } - if (silence) - DeleteSamples(silence); - - if (temp) - DeleteSamples(temp); - return ConsistencyCheck(wxT("Set")); } @@ -1531,33 +1514,31 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, int numBlocks = mBlock.size(); sampleCount length; SeqBlock *pLastBlock; + SampleBuffer buffer2(mMaxSamples, mSampleFormat); if (numBlocks > 0 && (length = (pLastBlock = &mBlock.back())->f->GetLength()) < mMinSamples) { SeqBlock &lastBlock = *pLastBlock; const sampleCount addLen = std::min(mMaxSamples - length, len); - samplePtr buffer2 = NewSamples((length + addLen), mSampleFormat); - Read(buffer2, mSampleFormat, lastBlock, 0, length); + Read(buffer2.ptr(), mSampleFormat, lastBlock, 0, length); CopySamples(buffer, format, - buffer2 + length * SAMPLE_SIZE(mSampleFormat), + buffer2.ptr() + length * SAMPLE_SIZE(mSampleFormat), mSampleFormat, addLen); const int newLastBlockLen = length + addLen; SeqBlock newLastBlock( - mDirManager->NewSimpleBlockFile(buffer2, newLastBlockLen, mSampleFormat, + mDirManager->NewSimpleBlockFile(buffer2.ptr(), newLastBlockLen, mSampleFormat, blockFileLog != NULL), lastBlock.start ); if (blockFileLog) static_cast(newLastBlock.f)->SaveXML(*blockFileLog); - DeleteSamples(buffer2); - mDirManager->Deref(lastBlock.f); lastBlock = newLastBlock; @@ -1566,21 +1547,6 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, buffer += addLen * SAMPLE_SIZE(format); } // Append the rest as new blocks - samplePtr temp = NULL; - if (format != mSampleFormat) { - temp = NewSamples(mMaxSamples, mSampleFormat); - wxASSERT(temp); - // TODO: Make error message clearer? - /* i18n-hint: Error message shown when Audacity was trying to allocate - memory to hold audio, and didn't have enough. 'New Samples' is - the name of the C++ function that failed, for use by a developer, - and should not be translated - though you could say - 'in function "NewSamples()"' to be clearer.*/ - if (!temp) { - wxMessageBox(_("Memory allocation failed -- NewSamples")); - return false; - } - } while (len) { const sampleCount idealSamples = GetIdealBlockSize(); const sampleCount l = std::min(idealSamples, len); @@ -1590,8 +1556,8 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, blockFileLog != NULL); } else { - CopySamples(buffer, format, temp, mSampleFormat, l); - pFile = mDirManager->NewSimpleBlockFile(temp, l, mSampleFormat, + CopySamples(buffer, format, buffer2.ptr(), mSampleFormat, l); + pFile = mDirManager->NewSimpleBlockFile(buffer2.ptr(), l, mSampleFormat, blockFileLog != NULL); } @@ -1604,8 +1570,6 @@ bool Sequence::Append(samplePtr buffer, sampleFormat format, mNumSamples += l; len -= l; } - if (temp) - DeleteSamples(temp); // JKC: During generate we use Append again and again. // If generating a long sequence this test would give O(n^2) @@ -1663,30 +1627,33 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // deletion within this block: SeqBlock *pBlock; sampleCount length; + + // One buffer for reuse in various branches here + SampleBuffer scratch; + // The maximum size that will ever be needed + const sampleCount scratchSize = mMaxSamples + mMinSamples; + if (b0 == b1 && (length = (pBlock = &mBlock.at(b0))->f->GetLength()) - len >= mMinSamples) { SeqBlock &b = *pBlock; sampleCount pos = start - b.start; sampleCount newLen = length - len; - samplePtr buffer = NewSamples(newLen, mSampleFormat); + scratch.Allocate(scratchSize, mSampleFormat); - Read(buffer, mSampleFormat, b, 0, pos); - Read(buffer + (pos * sampleSize), mSampleFormat, + Read(scratch.ptr(), mSampleFormat, b, 0, pos); + Read(scratch.ptr() + (pos * sampleSize), mSampleFormat, b, pos + len, newLen - pos); BlockFile *const oldFile = b.f; b = SeqBlock( - mDirManager->NewSimpleBlockFile(buffer, newLen, mSampleFormat), + mDirManager->NewSimpleBlockFile(scratch.ptr(), newLen, mSampleFormat), b.start ); + mDirManager->Deref(oldFile); for (unsigned int j = b0 + 1; j < numBlocks; j++) mBlock.at(j).start -= len; - DeleteSamples(buffer); - - mDirManager->Deref(oldFile); - mNumSamples -= len; return ConsistencyCheck(wxT("Delete - branch one")); @@ -1710,11 +1677,11 @@ bool Sequence::Delete(sampleCount start, sampleCount len) sampleCount preBufferLen = start - preBlock.start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { - samplePtr preBuffer = NewSamples(preBufferLen, mSampleFormat); - Read(preBuffer, mSampleFormat, preBlock, 0, preBufferLen); + if (!scratch.ptr()) + scratch.Allocate(scratchSize, mSampleFormat); + Read(scratch.ptr(), mSampleFormat, preBlock, 0, preBufferLen); BlockFile *const pFile = - mDirManager->NewSimpleBlockFile(preBuffer, preBufferLen, mSampleFormat); - DeleteSamples(preBuffer); + mDirManager->NewSimpleBlockFile(scratch.ptr(), preBufferLen, mSampleFormat); newBlock.push_back(SeqBlock(pFile, preBlock.start)); } else { @@ -1722,16 +1689,15 @@ bool Sequence::Delete(sampleCount start, sampleCount len) const sampleCount prepreLen = prepreBlock.f->GetLength(); const sampleCount sum = prepreLen + preBufferLen; - samplePtr sumBuffer = NewSamples(sum, mSampleFormat); + if (!scratch.ptr()) + scratch.Allocate(scratchSize, mSampleFormat); - Read(sumBuffer, mSampleFormat, prepreBlock, 0, prepreLen); - Read(sumBuffer + prepreLen*sampleSize, mSampleFormat, + Read(scratch.ptr(), mSampleFormat, prepreBlock, 0, prepreLen); + Read(scratch.ptr() + prepreLen*sampleSize, mSampleFormat, preBlock, 0, preBufferLen); newBlock.erase(newBlock.end() - 1); - Blockify(newBlock, prepreBlock.start, sumBuffer, sum); - - DeleteSamples(sumBuffer); + Blockify(newBlock, prepreBlock.start, scratch.ptr(), sum); mDirManager->Deref(prepreBlock.f); } @@ -1760,13 +1726,13 @@ bool Sequence::Delete(sampleCount start, sampleCount len) (postBlock.start + postBlock.f->GetLength()) - (start + len); if (postBufferLen) { if (postBufferLen >= mMinSamples || b1 == numBlocks - 1) { - samplePtr postBuffer = NewSamples(postBufferLen, mSampleFormat); + if (!scratch.ptr()) + // Last use of scratch, can ask for smaller + scratch.Allocate(postBufferLen, mSampleFormat); sampleCount pos = (start + len) - postBlock.start; - Read(postBuffer, mSampleFormat, postBlock, pos, postBufferLen); + Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen); BlockFile *const file = - mDirManager->NewSimpleBlockFile(postBuffer, postBufferLen, mSampleFormat); - - DeleteSamples(postBuffer); + mDirManager->NewSimpleBlockFile(scratch.ptr(), postBufferLen, mSampleFormat); newBlock.push_back(SeqBlock(file, start)); } else { @@ -1774,17 +1740,17 @@ bool Sequence::Delete(sampleCount start, sampleCount len) sampleCount postpostLen = postpostBlock.f->GetLength(); sampleCount sum = postpostLen + postBufferLen; - samplePtr sumBuffer = NewSamples(sum, mSampleFormat); + if (!scratch.ptr()) + // Last use of scratch, can ask for smaller + scratch.Allocate(sum, mSampleFormat); sampleCount pos = (start + len) - postBlock.start; - Read(sumBuffer, mSampleFormat, postBlock, pos, postBufferLen); - Read(sumBuffer + (postBufferLen * sampleSize), mSampleFormat, + Read(scratch.ptr(), mSampleFormat, postBlock, pos, postBufferLen); + Read(scratch.ptr() + (postBufferLen * sampleSize), mSampleFormat, postpostBlock, 0, postpostLen); - Blockify(newBlock, start, sumBuffer, sum); + Blockify(newBlock, start, scratch.ptr(), sum); b1++; - DeleteSamples(sumBuffer); - mDirManager->Deref(postpostBlock.f); } } diff --git a/src/Sequence.h b/src/Sequence.h index cf266b75e..e593afac2 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -246,7 +246,8 @@ class Sequence: public XMLTagHandler { const SeqBlock &b, sampleCount start, sampleCount len) const; - bool CopyWrite(samplePtr buffer, SeqBlock &b, + bool CopyWrite(SampleBuffer &scratch, + samplePtr buffer, SeqBlock &b, sampleCount start, sampleCount len); void Blockify(BlockArray &list, sampleCount start, samplePtr buffer, sampleCount len); From dd3df60a8378347660b61534392f412b81e60344 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 3 Feb 2016 23:36:36 -0500 Subject: [PATCH 09/16] Avoid repeated FindBlock call in Sequence::Get when we can --- src/Sequence.cpp | 22 ++++++++++++++-------- src/Sequence.h | 3 +++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index eb991694b..04da09858 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -439,7 +439,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) BlockFile *const file = block0.f; blocklen = std::min(s1, block0.start + file->GetLength()) - s0; wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 - Get(buffer.ptr(), mSampleFormat, s0, blocklen); + Get(b0, buffer.ptr(), mSampleFormat, s0, blocklen); (*dest)->Append(buffer.ptr(), mSampleFormat, blocklen); } @@ -457,7 +457,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) blocklen = (s1 - block.start); wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 if (blocklen < file->GetLength()) { - Get(buffer.ptr(), mSampleFormat, block.start, blocklen); + Get(b1, buffer.ptr(), mSampleFormat, block.start, blocklen); (*dest)->Append(buffer.ptr(), mSampleFormat, blocklen); } else @@ -548,7 +548,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) int splitPoint = s - block.start; Read(buffer.ptr(), mSampleFormat, block, 0, splitPoint); - src->Get(buffer.ptr() + splitPoint*sampleSize, + src->Get(0, buffer.ptr() + splitPoint*sampleSize, mSampleFormat, 0, addedLen); Read(buffer.ptr() + (splitPoint + addedLen)*sampleSize, mSampleFormat, block, @@ -587,7 +587,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) SampleBuffer sumBuffer(sum, mSampleFormat); Read(sumBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint); - src->Get(sumBuffer.ptr() + splitPoint * sampleSize, + src->Get(0, sumBuffer.ptr() + splitPoint * sampleSize, mSampleFormat, 0, addedLen); Read(sumBuffer.ptr() + (splitPoint + addedLen) * sampleSize, mSampleFormat, @@ -617,7 +617,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) SampleBuffer sampleBuffer(std::max(leftLen, rightLen), mSampleFormat); Read(sampleBuffer.ptr(), mSampleFormat, splitBlock, 0, splitPoint); - src->Get(sampleBuffer.ptr() + splitPoint*sampleSize, + src->Get(0, sampleBuffer.ptr() + splitPoint*sampleSize, mSampleFormat, 0, srcFirstTwoLen); Blockify(newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen); @@ -634,7 +634,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) } sampleCount lastStart = penultimate.start; - src->Get(sampleBuffer.ptr(), mSampleFormat, + src->Get(srcNumBlocks - 2, sampleBuffer.ptr(), mSampleFormat, lastStart, srcLastTwoLen); Read(sampleBuffer.ptr() + srcLastTwoLen * sampleSize, mSampleFormat, splitBlock, splitPoint, rightSplit); @@ -1166,13 +1166,19 @@ bool Sequence::CopyWrite(SampleBuffer &scratch, } bool Sequence::Get(samplePtr buffer, sampleFormat format, - sampleCount start, sampleCount len) const + sampleCount start, sampleCount len) const { if (start < 0 || start >= mNumSamples || - start+len > mNumSamples) + start + len > mNumSamples) return false; int b = FindBlock(start); + return Get(b, buffer, format, start, len); +} + +bool Sequence::Get(int b, samplePtr buffer, sampleFormat format, + sampleCount start, sampleCount len) const +{ while (len) { const SeqBlock &block = mBlock.at(b); const sampleCount bstart = (start - (block.start)); diff --git a/src/Sequence.h b/src/Sequence.h index e593afac2..6f3247550 100644 --- a/src/Sequence.h +++ b/src/Sequence.h @@ -252,6 +252,9 @@ class Sequence: public XMLTagHandler { void Blockify(BlockArray &list, sampleCount start, samplePtr buffer, sampleCount len); + bool Get(int b, samplePtr buffer, sampleFormat format, + sampleCount start, sampleCount len) const; + public: // From 3f4a9191ec6cbd6730ff9791a6d2869f6a60ac5e Mon Sep 17 00:00:00 2001 From: James Crook Date: Mon, 8 Feb 2016 21:47:59 +0000 Subject: [PATCH 10/16] __WXMAC__ -> __APPLE__ in Theme.cpp #ifdef This change helps macports and is (apparently) neutral for the platforms we build for. See: https://trac.macports.org/ticket/47189#comment:35 --- src/Theme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Theme.cpp b/src/Theme.cpp index 88f2aabfd..f7b47b58e 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -383,7 +383,7 @@ void ThemeBase::RegisterImage( int &iIndex, const wxImage &Image, const wxString wxASSERT( iIndex == -1 ); // Don't initialise same bitmap twice! mImages.Add( Image ); -#ifdef __WXMAC__ +#ifdef __APPLE__ // On Mac, bitmaps with alpha don't work. // So we convert to a mask and use that. // It isn't quite as good, as alpha gives smoother edges. From 5f76da4f5ba25f381f78622edfa0824fa002ecfd Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 11 Feb 2016 12:01:42 -0500 Subject: [PATCH 11/16] Bug1321 (partial): Don't change output balance when closing Preferences unless... ... you really changed Device preferences. --- src/AudioIO.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 798438c97..f5d613bd5 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -1107,8 +1107,13 @@ void AudioIO::HandleDeviceChange() return; // get the selected record and playback devices - int playDeviceNum = getPlayDevIndex(); - int recDeviceNum = getRecordDevIndex(); + const int playDeviceNum = getPlayDevIndex(); + const int recDeviceNum = getRecordDevIndex(); + + // If no change needed, return + if (mCachedPlaybackIndex == playDeviceNum && + mCachedCaptureIndex == recDeviceNum) + return; // cache playback/capture rates mCachedPlaybackRates = GetSupportedPlaybackRates(playDeviceNum); From c4657a7b0eb4c22718018a3e0f0f8d2bef5c817a Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 11 Feb 2016 12:32:53 -0500 Subject: [PATCH 12/16] Use [] not at() -- avoid array bounds checking in release build! --- src/Sequence.cpp | 94 ++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/Sequence.cpp b/src/Sequence.cpp index 04da09858..6862600f6 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -91,7 +91,7 @@ void Sequence::DerefAllFiles() { for (size_t i = 0, nn = mBlock.size(); i < nn; i++) { - BlockFile *& pOldFile = mBlock.at(i).f; + BlockFile *& pOldFile = mBlock[i].f; if (pOldFile) { mDirManager->Deref(pOldFile); pOldFile = NULL; @@ -112,7 +112,7 @@ sampleCount Sequence::GetIdealBlockSize() const bool Sequence::Lock() { for (unsigned int i = 0; i < mBlock.size(); i++) - mBlock.at(i).f->Lock(); + mBlock[i].f->Lock(); return true; } @@ -120,7 +120,7 @@ bool Sequence::Lock() bool Sequence::CloseLock() { for (unsigned int i = 0; i < mBlock.size(); i++) - mBlock.at(i).f->CloseLock(); + mBlock[i].f->CloseLock(); return true; } @@ -128,7 +128,7 @@ bool Sequence::CloseLock() bool Sequence::Unlock() { for (unsigned int i = 0; i < mBlock.size(); i++) - mBlock.at(i).f->Unlock(); + mBlock[i].f->Unlock(); return true; } @@ -184,7 +184,7 @@ bool Sequence::ConvertToSampleFormat(sampleFormat format, bool* pbChanged) for (size_t i = 0, nn = mBlock.size(); i < nn && bSuccess; i++) { - SeqBlock &oldSeqBlock = mBlock.at(i); + SeqBlock &oldSeqBlock = mBlock[i]; BlockFile* oldBlockFile = oldSeqBlock.f; sampleCount len = oldBlockFile->GetLength(); @@ -271,7 +271,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, for (unsigned b = block0 + 1; b < block1; ++b) { float blockMin, blockMax, blockRMS; - mBlock.at(b).f->GetMinMax(&blockMin, &blockMax, &blockRMS); + mBlock[b].f->GetMinMax(&blockMin, &blockMax, &blockRMS); if (blockMin < min) min = blockMin; @@ -285,7 +285,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, // If not, we need read some samples and summaries from disk. { float block0Min, block0Max, block0RMS; - const SeqBlock &theBlock = mBlock.at(block0); + const SeqBlock &theBlock = mBlock[block0]; BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&block0Min, &block0Max, &block0RMS); @@ -310,7 +310,7 @@ bool Sequence::GetMinMax(sampleCount start, sampleCount len, if (block1 > block0) { float block1Min, block1Max, block1RMS; - const SeqBlock &theBlock = mBlock.at(block1); + const SeqBlock &theBlock = mBlock[block1]; BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&block1Min, &block1Max, &block1RMS); @@ -359,7 +359,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, // already in memory. for (unsigned b = block0 + 1; b < block1; b++) { float blockMin, blockMax, blockRMS; - const SeqBlock &theBlock = mBlock.at(b); + const SeqBlock &theBlock = mBlock[b]; BlockFile *const theFile = theBlock.f; theFile->GetMinMax(&blockMin, &blockMax, &blockRMS); @@ -372,7 +372,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, // selection may only partly overlap these blocks. // If not, we need read some samples and summaries from disk. { - const SeqBlock &theBlock = mBlock.at(block0); + const SeqBlock &theBlock = mBlock[block0]; BlockFile *const theFile = theBlock.f; s0 = start - theBlock.start; l0 = len; @@ -389,7 +389,7 @@ bool Sequence::GetRMS(sampleCount start, sampleCount len, } if (block1 > block0) { - const SeqBlock &theBlock = mBlock.at(block1); + const SeqBlock &theBlock = mBlock[block1]; BlockFile *const theFile = theBlock.f; s0 = 0; @@ -434,7 +434,7 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) // Do the first block - const SeqBlock &block0 = mBlock.at(b0); + const SeqBlock &block0 = mBlock[b0]; if (s0 != block0.start) { BlockFile *const file = block0.f; blocklen = std::min(s1, block0.start + file->GetLength()) - s0; @@ -448,11 +448,11 @@ bool Sequence::Copy(sampleCount s0, sampleCount s1, Sequence **dest) // If there are blocks in the middle, copy the blockfiles directly for (int bb = b0 + 1; bb < b1; ++bb) - (*dest)->AppendBlock(mBlock.at(bb)); // Increase ref count or duplicate file + (*dest)->AppendBlock(mBlock[bb]); // Increase ref count or duplicate file // Do the last block if (b1 > b0) { - const SeqBlock &block = mBlock.at(b1); + const SeqBlock &block = mBlock[b1]; BlockFile *const file = block.f; blocklen = (s1 - block.start); wxASSERT(file->IsAlias() || (blocklen <= mMaxSamples)); // Vaughan, 2012-02-29 @@ -526,14 +526,14 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // minimum size for (unsigned int i = 0; i < srcNumBlocks; i++) - AppendBlock(srcBlock.at(i)); // Increase ref count or duplicate file + AppendBlock(srcBlock[i]); // Increase ref count or duplicate file return ConsistencyCheck(wxT("Paste branch one")); } const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s); wxASSERT((b >= 0) && (b < (int)numBlocks)); - SeqBlock *const pBlock = &mBlock.at(b); + SeqBlock *const pBlock = &mBlock[b]; const sampleCount length = pBlock->f->GetLength(); const sampleCount largerBlockLen = addedLen + length; // PRL: when insertion point is the first sample of a block, @@ -561,7 +561,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) block.f = file; for (unsigned int i = b + 1; i < numBlocks; i++) - mBlock.at(i).start += addedLen; + mBlock[i].start += addedLen; mNumSamples += addedLen; @@ -576,7 +576,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) newBlock.reserve(numBlocks + srcNumBlocks + 2); newBlock.insert(newBlock.end(), mBlock.begin(), mBlock.begin() + b); - SeqBlock &splitBlock = mBlock.at(b); + SeqBlock &splitBlock = mBlock[b]; sampleCount splitLen = splitBlock.f->GetLength(); int splitPoint = s - splitBlock.start; @@ -604,13 +604,13 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // half of the split block. const sampleCount srcFirstTwoLen = - srcBlock.at(0).f->GetLength() + srcBlock.at(1).f->GetLength(); + srcBlock[0].f->GetLength() + srcBlock[1].f->GetLength(); const sampleCount leftLen = splitPoint + srcFirstTwoLen; - const SeqBlock &penultimate = srcBlock.at(srcNumBlocks - 2); + const SeqBlock &penultimate = srcBlock[srcNumBlocks - 2]; const sampleCount srcLastTwoLen = penultimate.f->GetLength() + - srcBlock.at(srcNumBlocks - 1).f->GetLength(); + srcBlock[srcNumBlocks - 1].f->GetLength(); const sampleCount rightSplit = splitBlock.f->GetLength() - splitPoint; const sampleCount rightLen = rightSplit + srcLastTwoLen; @@ -623,7 +623,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) Blockify(newBlock, splitBlock.start, sampleBuffer.ptr(), leftLen); for (i = 2; i < srcNumBlocks - 2; i++) { - const SeqBlock &block = srcBlock.at(i); + const SeqBlock &block = srcBlock[i]; BlockFile *const file = mDirManager->CopyBlockFile(block.f); if (!file) { wxASSERT(false); // TODO: Handle this better, alert the user of failure. @@ -647,7 +647,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src) // Copy remaining blocks to new block array and // swap the new block array in for the old for (i = b + 1; i < numBlocks; i++) - newBlock.push_back(mBlock.at(i).Plus(addedLen)); + newBlock.push_back(mBlock[i].Plus(addedLen)); mBlock.swap(newBlock); @@ -778,7 +778,7 @@ unsigned int Sequence::GetODFlags() { unsigned int ret = 0; for (unsigned int i = 0; i < mBlock.size(); i++) { - BlockFile *const file = mBlock.at(i).f; + BlockFile *const file = mBlock[i].f; if(!file->IsDataAvailable()) ret |= (static_cast(file))->GetDecodeType(); else if(!file->IsSummaryAvailable()) @@ -790,7 +790,7 @@ unsigned int Sequence::GetODFlags() sampleCount Sequence::GetBlockStart(sampleCount position) const { int b = FindBlock(position); - return mBlock.at(b).start; + return mBlock[b].start; } sampleCount Sequence::GetBestBlockSize(sampleCount start) const @@ -806,12 +806,12 @@ sampleCount Sequence::GetBestBlockSize(sampleCount start) const int b = FindBlock(start); int numBlocks = mBlock.size(); - const SeqBlock &block = mBlock.at(b); + const SeqBlock &block = mBlock[b]; sampleCount result = (block.start + block.f->GetLength() - start); sampleCount length; while(result < mMinSamples && b+1GetLength()) + result) <= mMaxSamples) { + ((length = mBlock[b+1].f->GetLength()) + result) <= mMaxSamples) { b++; result += length; } @@ -958,12 +958,12 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Make sure that the sequence is valid. // First, replace missing blockfiles with SilentBlockFiles for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) { - SeqBlock &block = mBlock.at(b); + SeqBlock &block = mBlock[b]; if (!block.f) { sampleCount len; if (b < nn - 1) - len = mBlock.at(b+1).start - block.start; + len = mBlock[b+1].start - block.start; else len = mNumSamples - block.start; @@ -988,7 +988,7 @@ void Sequence::HandleXMLEndTag(const wxChar *tag) // Next, make sure that start times and lengths are consistent sampleCount numSamples = 0; for (unsigned b = 0, nn = mBlock.size(); b < nn; b++) { - SeqBlock &block = mBlock.at(b); + SeqBlock &block = mBlock[b]; if (block.start != numSamples) { wxString sFileAndExtension = block.f->GetFileName().GetFullName(); if (sFileAndExtension.IsEmpty()) @@ -1040,7 +1040,7 @@ void Sequence::WriteXML(XMLWriter &xmlFile) xmlFile.WriteAttr(wxT("numsamples"), mNumSamples); for (b = 0; b < mBlock.size(); b++) { - SeqBlock &bb = mBlock.at(b); + SeqBlock &bb = mBlock[b]; // See http://bugzilla.audacityteam.org/show_bug.cgi?id=451. // Also, don't check against mMaxSamples for AliasBlockFiles, because if you convert sample format, @@ -1088,7 +1088,7 @@ int Sequence::FindBlock(sampleCount pos) const //of the unsearched area, since samples are usually proportional to block file number. const double frac = double(pos - loSamples) / (hiSamples - loSamples); guess = std::min(hi - 1, lo + sampleCount(frac * (hi - lo))); - const SeqBlock &block = mBlock.at(guess); + const SeqBlock &block = mBlock[guess]; wxASSERT(block.f->GetLength() > 0); wxASSERT(lo <= guess && guess < hi && lo < hi); @@ -1112,8 +1112,8 @@ int Sequence::FindBlock(sampleCount pos) const const int rval = guess; wxASSERT(rval >= 0 && rval < numBlocks && - pos >= mBlock.at(rval).start && - pos < mBlock.at(rval).start + mBlock.at(rval).f->GetLength()); + pos >= mBlock[rval].start && + pos < mBlock[rval].start + mBlock[rval].f->GetLength()); return rval; } @@ -1180,7 +1180,7 @@ bool Sequence::Get(int b, samplePtr buffer, sampleFormat format, sampleCount start, sampleCount len) const { while (len) { - const SeqBlock &block = mBlock.at(b); + const SeqBlock &block = mBlock[b]; const sampleCount bstart = (start - (block.start)); const sampleCount blen = std::min(len, block.f->GetLength() - bstart); @@ -1214,7 +1214,7 @@ bool Sequence::Set(samplePtr buffer, sampleFormat format, int b = FindBlock(start); while (len) { - SeqBlock &block = mBlock.at(b); + SeqBlock &block = mBlock[b]; const sampleCount bstart = start - block.start; const sampleCount fileLength = block.f->GetLength(); const int blen = @@ -1333,7 +1333,7 @@ bool Sequence::GetWaveDisplay(float *min, float *max, float *rms, int* bl, // Find the range of sample values for this block that // are in the display. - SeqBlock &seqBlock = mBlock.at(b); + SeqBlock &seqBlock = mBlock[b]; const sampleCount start = seqBlock.start; nextSrcX = std::min(s1, start + seqBlock.f->GetLength()); @@ -1639,7 +1639,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // The maximum size that will ever be needed const sampleCount scratchSize = mMaxSamples + mMinSamples; - if (b0 == b1 && (length = (pBlock = &mBlock.at(b0))->f->GetLength()) - len >= mMinSamples) { + if (b0 == b1 && (length = (pBlock = &mBlock[b0])->f->GetLength()) - len >= mMinSamples) { SeqBlock &b = *pBlock; sampleCount pos = start - b.start; sampleCount newLen = length - len; @@ -1658,7 +1658,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) mDirManager->Deref(oldFile); for (unsigned int j = b0 + 1; j < numBlocks; j++) - mBlock.at(j).start -= len; + mBlock[j].start -= len; mNumSamples -= len; @@ -1679,7 +1679,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // or if this would be the first block in the array, write it out. // Otherwise combine it with the previous block (splitting them // 50/50 if necessary). - const SeqBlock &preBlock = mBlock.at(b0); + const SeqBlock &preBlock = mBlock[b0]; sampleCount preBufferLen = start - preBlock.start; if (preBufferLen) { if (preBufferLen >= mMinSamples || b0 == 0) { @@ -1691,7 +1691,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) newBlock.push_back(SeqBlock(pFile, preBlock.start)); } else { - const SeqBlock &prepreBlock = mBlock.at(b0 - 1); + const SeqBlock &prepreBlock = mBlock[b0 - 1]; const sampleCount prepreLen = prepreBlock.f->GetLength(); const sampleCount sum = prepreLen + preBufferLen; @@ -1719,7 +1719,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Next, delete blocks strictly between b0 and b1 for (i = b0 + 1; i < b1; i++) { - mDirManager->Deref(mBlock.at(i).f); + mDirManager->Deref(mBlock[i].f); } // Now, symmetrically, grab the samples in block b1 after the @@ -1727,7 +1727,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // for its own block, or if this would be the last block in // the array, write it out. Otherwise combine it with the // subsequent block (splitting them 50/50 if necessary). - const SeqBlock &postBlock = mBlock.at(b1); + const SeqBlock &postBlock = mBlock[b1]; sampleCount postBufferLen = (postBlock.start + postBlock.f->GetLength()) - (start + len); if (postBufferLen) { @@ -1742,7 +1742,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) newBlock.push_back(SeqBlock(file, start)); } else { - SeqBlock &postpostBlock = mBlock.at(b1 + 1); + SeqBlock &postpostBlock = mBlock[b1 + 1]; sampleCount postpostLen = postpostBlock.f->GetLength(); sampleCount sum = postpostLen + postBufferLen; @@ -1768,7 +1768,7 @@ bool Sequence::Delete(sampleCount start, sampleCount len) // Copy the remaining blocks over from the old array for (i = b1 + 1; i < numBlocks; i++) - newBlock.push_back(mBlock.at(i).Plus(-len)); + newBlock.push_back(mBlock[i].Plus(-len)); // Substitute our new array for the old one mBlock.swap(newBlock); @@ -1787,7 +1787,7 @@ bool Sequence::ConsistencyCheck(const wxChar *whereStr) const bool bError = false; for (i = 0; !bError && i < numBlocks; i++) { - const SeqBlock &seqBlock = mBlock.at(i); + const SeqBlock &seqBlock = mBlock[i]; if (pos != seqBlock.start) bError = true; @@ -1819,7 +1819,7 @@ void Sequence::DebugPrintf(wxString *dest) const int pos = 0; for (i = 0; i < mBlock.size(); i++) { - const SeqBlock &seqBlock = mBlock.at(i); + const SeqBlock &seqBlock = mBlock[i]; *dest += wxString::Format (wxT(" Block %3u: start %8lld, len %8lld, refs %d, "), i, From 01a95c50bafd81faa203f207d7d07e6ea843157e Mon Sep 17 00:00:00 2001 From: Gale Andrews Date: Fri, 12 Feb 2016 14:31:20 +0000 Subject: [PATCH 13/16] Clarify Xocde 4.3.3 for Lion has the 10.6 SDK... ...in spite of what Apple's Downloads page says. --- mac/Build.txt | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/mac/Build.txt b/mac/Build.txt index 845ae5b1c..b546ba0e1 100644 --- a/mac/Build.txt +++ b/mac/Build.txt @@ -3,38 +3,40 @@ is 10.6. To build Audacity using Xcode 5.1 or newer, you need to extract the 10.6 SDK from an earlier version of Xcode. In the instructions below, Xcode 4.3.3 (for the 10.6 SDK) and -Xcode 5.1.1 will be used. Xcode 6.1.1, 6.3, 6.4.1, and 7.0 +Xcode 5.1.1 will be used. Xcode 6.1.1, 6.3, 6.4.1, and 7.1 have been verified to work as well. -1) Download Xcode 5.1.1 or greater and install it to /Applications -2) Download Xcode 4.3.3 and open it in Finder -3) Right click the "Xcode.app" bundle and select "Show Package Contents" -4) Navigate down the directories to get to: +1) Download Xcode 5.1.1 or greater and install it to /Applications. +2) Download Xcode 4.3.3 (it includes the 10.6 and 10.7 SDK's despite + the downloads page says it only has the 10.7 SDK). +3) Open the DMG in Finder. +4) Right-click the "Xcode.app" bundle and select "Show Package Contents". +5) Navigate down the directories to get to: - Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ + Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ . -5) Copy the MacOSX10.6.sdk folder to: +6) Copy the MacOSX10.6.sdk folder to: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ Xcode is now ready. -6) Download wxWidgets. We currently require version 3.0.2, which can be downloaded from: +7) Download wxWidgets. We currently require version 3.0.2, which can be downloaded from: http://sourceforge.net/projects/wxwindows/files/3.0.2/wxWidgets-3.0.2.tar.bz2 -7) Once the download is complete, untar it (your browser may have already done this): +8) Once the download is complete, untar it (your browser may have already done this): - tar xf wxWidgets-3.0.2.tar.bz2 + tar xf wxWidgets-3.0.2.tar.bz2 . -8) Apply the following fixes to wxWidgets: +9) Apply the following fixes to wxWidgets: cd wxWidgets-3.0.2 - patch -p0 -i /mac/wxMac_additions/wxMac-3.0.2-fixes.patch + patch -p0 -i /mac/wxMac_additions/wxMac-3.0.2-fixes.patch . -9) And finally build/install wxWidgets: +10) And finally build/install wxWidgets: - sudo /mac/build_wxwidgets + sudo /mac/build_wxwidgets . You should now be able to build Audacity using either the Xcode application or the xcodebuild command line tool. From be15ddee889fd5fb3117df2b74837831cc023679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Feh=C3=A9r?= Date: Fri, 12 Feb 2016 20:59:15 +0100 Subject: [PATCH 14/16] fix linking on linux This was only working because g++ can be used to link C++ and Objective-C object files. As soon as CXX is set to a different compiler this failed on linux, trying to link objects compiled with a different compiler. --- lib-src/FileDialog/Makefile.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib-src/FileDialog/Makefile.in b/lib-src/FileDialog/Makefile.in index 52ce4c53e..35dd3c07d 100644 --- a/lib-src/FileDialog/Makefile.in +++ b/lib-src/FileDialog/Makefile.in @@ -216,6 +216,10 @@ OBJCXXLINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(OBJCXXLD) $(AM_OBJCXXFLAGS) $(OBJCXXFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_OBJCXXLD = $(am__v_OBJCXXLD_@AM_V@) +# Overwrite C++ variables with values for Objective-C, because in the end there +# is only one linker command that should be configured correctly. +@MAC_TRUE@CXXLINK = $(OBJCXXLINK) +@MAC_TRUE@AM_V_CXXLD = $(AM_V_OBJCXXLD) am__v_OBJCXXLD_ = $(am__v_OBJCXXLD_@AM_DEFAULT_V@) am__v_OBJCXXLD_0 = @echo " OBJCXXLD" $@; am__v_OBJCXXLD_1 = @@ -520,8 +524,8 @@ win/$(DEPDIR)/$(am__dirstamp): win/libFileDialog_la-FileDialogPrivate.lo: win/$(am__dirstamp) \ win/$(DEPDIR)/$(am__dirstamp) -libFileDialog.la: $(libFileDialog_la_OBJECTS) $(libFileDialog_la_DEPENDENCIES) $(EXTRA_libFileDialog_la_DEPENDENCIES) - $(AM_V_OBJCXXLD)$(OBJCXXLINK) -rpath $(libdir) $(libFileDialog_la_OBJECTS) $(libFileDialog_la_LIBADD) $(LIBS) +libFileDialog.la: $(libFileDialog_la_OBJECTS) $(libFileDialog_la_DEPENDENCIES) $(EXTRA_libFileDialog_la_DEPENDENCIES) + $(AM_V_CXXLD)$(CXXLINK) -rpath $(libdir) $(libFileDialog_la_OBJECTS) $(libFileDialog_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) From 2e552188b0e1a381a404a5c6419385405cf073d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Feh=C3=A9r?= Date: Sun, 7 Feb 2016 17:42:59 +0100 Subject: [PATCH 15/16] use gcc 4.8 for build --- .travis.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ebaa75cbf..d9cf1937b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,17 @@ +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 + - gcc-4.8 before_install: - sudo apt-get update -qq - sudo apt-get install -y libwxgtk3.0-dev libgtk2.0-dev - git show -s --format="wxT(\"%h of %cd\")" - git show -s --format="wxT(\"%h of %cd\")" > ./src/RevisionIdent.h + - export CXX="g++-4.8" CC="gcc-4.8" language: - cpp -compiler: - - gcc -script: +script: - aclocal --install -I m4 && automake && ./configure && make - From 575463252e153af9458332f573111c1083739142 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 11 Feb 2016 19:53:14 -0500 Subject: [PATCH 16/16] Compile with gcc 4.8 and -std=c++11 --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index aab92081a..38968a4b8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ libaudacity_la_SOURCES = \ $(NULL) audacity_CPPFLAGS = \ + -std=c++11 \ -Wno-deprecated-declarations \ -D__STDC_CONSTANT_MACROS \ -DLIBDIR=\"$(libdir)\" \