mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-01 16:39:30 +02:00
Use SampleBuffer in Sequence, reuse so there are fewer allocations of buffers
This commit is contained in:
parent
ca56876aaf
commit
dc599116f7
294
src/Sequence.cpp
294
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<SimpleBlockFile*>(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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user